diff --git a/.dockerignore b/.dockerignore index b01fe8d..a17bc8a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,3 @@ -backend/db_data -minio_data +backend/db_data +minio_data .env \ No newline at end of file diff --git a/.env.example b/.env.example index 83cd169..5a2317a 100644 --- a/.env.example +++ b/.env.example @@ -1,63 +1,63 @@ -#### DEV #### -NODE_ENV = development - -#### PORT BACKEND #### -PORT = PORT - -##----- No SQL-----## - -#### MONGODB ##### -MONGO_USER = MONGO_USER -MONGO_PASSWORD = MONGO_PASSWORD -MONGO_PORT = MONGO_PORT -MONGODB_URL = 'MONGODB_URL' - -#### REDIS #### - -REDIS_HOST = REDIS_HOST -REDIS_FAMILY = REDIS_FAMILY -REDIS_PORT = REDIS_PORT -REDIS_PASSWORD = 'REDIS_PASSWORD' - -##---- SQL ----## -POSTGRES_HOST = POSTGRES_HOST -POSTGRES_USER = POSTGRES_USER -POSTGRES_PASSWORD = POSTGRES_PASSWORD -POSTGRES_DB = POSTGRES_DB -POSTGRES_PORT = POSTGRES_PORT -DB_POOL_SIZE = DB_POOL_SIZE - -##---- Rate Limit ----## -IPA_API_RATE_LIMIT_DURATION = IPA_API_RATE_LIMIT_DURATION -IPA_API_RATE_LIMIT = IPA_API_RATE_LIMIT - -##---- Cloudinary ---## -CLOUD_API_KEY = CLOUD_API_KEY -CLOUD_API_SECRET = CLOUD_API_SECRET -CLOUD_NAME = CLOUD_NAME - - -###! JWT ### -JWT_SECRET = JWT_SECRET -JWT_EXPIRE = JWT_EXPIRE -JWT_KEY = JWT_KEY - -###! KEY_SESSION ### -KEY_SESSION = KEY_SESSION - -###! SEND_EMAIL ### -SMPT_HOST = SMPT_HOST -SMPT_PORT = SMPT_PORT -SMPT_SERVICE = SMPT_SERVICE -SMPT_MAIL = SMPT_MAIL -SMPT_PASSWORD = SMPT_PASSWORD - -###! TOKEN ### -REFRESH_TOKEN_SECRET = REFRESH_TOKEN_SECRET -ACCESS_TOKEN_SECRET = ACCESS_TOKEN_SECRET - -###! INLINE_RUNTIME_CHUNK ### -INLINE_RUNTIME_CHUNK=INLINE_RUNTIME_CHUNK - -###! COOKIE_EXPIRE ### +#### DEV #### +NODE_ENV = development + +#### PORT BACKEND #### +PORT = PORT + +##----- No SQL-----## + +#### MONGODB ##### +MONGO_USER = MONGO_USER +MONGO_PASSWORD = MONGO_PASSWORD +MONGO_PORT = MONGO_PORT +MONGODB_URL = 'MONGODB_URL' + +#### REDIS #### + +REDIS_HOST = REDIS_HOST +REDIS_FAMILY = REDIS_FAMILY +REDIS_PORT = REDIS_PORT +REDIS_PASSWORD = 'REDIS_PASSWORD' + +##---- SQL ----## +POSTGRES_HOST = POSTGRES_HOST +POSTGRES_USER = POSTGRES_USER +POSTGRES_PASSWORD = POSTGRES_PASSWORD +POSTGRES_DB = POSTGRES_DB +POSTGRES_PORT = POSTGRES_PORT +DB_POOL_SIZE = DB_POOL_SIZE + +##---- Rate Limit ----## +IPA_API_RATE_LIMIT_DURATION = IPA_API_RATE_LIMIT_DURATION +IPA_API_RATE_LIMIT = IPA_API_RATE_LIMIT + +##---- Cloudinary ---## +CLOUD_API_KEY = CLOUD_API_KEY +CLOUD_API_SECRET = CLOUD_API_SECRET +CLOUD_NAME = CLOUD_NAME + + +###! JWT ### +JWT_SECRET = JWT_SECRET +JWT_EXPIRE = JWT_EXPIRE +JWT_KEY = JWT_KEY + +###! KEY_SESSION ### +KEY_SESSION = KEY_SESSION + +###! SEND_EMAIL ### +SMPT_HOST = SMPT_HOST +SMPT_PORT = SMPT_PORT +SMPT_SERVICE = SMPT_SERVICE +SMPT_MAIL = SMPT_MAIL +SMPT_PASSWORD = SMPT_PASSWORD + +###! TOKEN ### +REFRESH_TOKEN_SECRET = REFRESH_TOKEN_SECRET +ACCESS_TOKEN_SECRET = ACCESS_TOKEN_SECRET + +###! INLINE_RUNTIME_CHUNK ### +INLINE_RUNTIME_CHUNK=INLINE_RUNTIME_CHUNK + +###! COOKIE_EXPIRE ### COOKIE_EXPIRE \ No newline at end of file diff --git a/.env.product.example b/.env.product.example index 1c58163..9397af4 100644 --- a/.env.product.example +++ b/.env.product.example @@ -1,77 +1,77 @@ -### --------------- BACKEND --------------- ### - -###! PORT ### -PORT=PORT - -###! MONGO_DB ### -MONGODB_URL=MONGODB_URL - -###! REDIS_DB ### -REDIS_HOST=REDIS_HOST -REDIS_PORT=REDIS_PORT -REDIS_USER=REDIS_USER -REDIS_PASSWORD=REDIS_PASSWORD - - -###! COOKIE_EXPIRE ### -COOKIE_EXPIRE=COOKIE_EXPIRE - - -###! EXPIRES_TOKEN ### -EXPIRES_ACCESS_TOKEN=EXPIRES_ACCESS_TOKEN -EXPIRES_REFRESH_TOKEN=EXPIRES_REFRESH_TOKEN - -###! JWT ### -JWT_SECRET=JWT_SECRET -JWT_EXPIRE=JWT_EXPIRE - -###! SEND_EMAIL ### -SMPT_HOST=SMPT_HOST -SMPT_PORT=SMPT_PORT -SMPT_SERVICE=SMPT_SERVICE -SMPT_MAIL=SMPT_MAIL -SMPT_PASSWORD=SMPT_PASSWORD - -###! COUND_DINARY ### - -CLOUD_API_KEY=CLOUD_API_KEY -CLOUD_API_SECRET=CLOUD_API_SECRET -CLOUD_NAME=CLOUD_NAME - - -###! CHECK CHECK ### -CHECK_VERIFY_TRUE=CHECK_VERIFY_TRUE -CHECK_VERIFY_FALSE=CHECK_VERIFY_FALSE - -### --------------- FRONTEND --------------- ### - -###! PORT_FRONTEND ### -FRONTEND_URL=FRONTEND_URL - -###! GOOGLE_CLIENT ### -GOOGLE_CLIENT_IDS=GOOGLE_CLIENT_IDS - -GOOGLE_CLIENT_SECRETS=GOOGLE_CLIENT_SECRETS - -###! GOOGLE_MAP ### -GOOGLE_APP_GOOGLE_MAPS_API_KEY=GOOGLE_APP_GOOGLE_MAPS_API_KEY - -###! STRIPE ### - -STRIPE_KEY=STRIPE_KEY -STRIPE_PUBLIC=STRIPE_PUBLIC - -###! UV_THREADPOOL ### -UV_THREADPOOL_SIZE=UV_THREADPOOL_SIZE - -###! INLINE_RUNTIME_CHUNK ### -INLINE_RUNTIME_CHUNK=INLINE_RUNTIME_CHUNK - -###! RECAPTCHA_SECRET_KEY ### -RECAPTCHA_SECRET_KEY=RECAPTCHA_SECRET_KEY - - - -## Token -REFRESH_TOKEN_SECRET=REFRESH_TOKEN_SECRET -ACCESS_TOKEN_SECRET=ACCESS_TOKEN_SECRET +### --------------- BACKEND --------------- ### + +###! PORT ### +PORT=PORT + +###! MONGO_DB ### +MONGODB_URL=MONGODB_URL + +###! REDIS_DB ### +REDIS_HOST=REDIS_HOST +REDIS_PORT=REDIS_PORT +REDIS_USER=REDIS_USER +REDIS_PASSWORD=REDIS_PASSWORD + + +###! COOKIE_EXPIRE ### +COOKIE_EXPIRE=COOKIE_EXPIRE + + +###! EXPIRES_TOKEN ### +EXPIRES_ACCESS_TOKEN=EXPIRES_ACCESS_TOKEN +EXPIRES_REFRESH_TOKEN=EXPIRES_REFRESH_TOKEN + +###! JWT ### +JWT_SECRET=JWT_SECRET +JWT_EXPIRE=JWT_EXPIRE + +###! SEND_EMAIL ### +SMPT_HOST=SMPT_HOST +SMPT_PORT=SMPT_PORT +SMPT_SERVICE=SMPT_SERVICE +SMPT_MAIL=SMPT_MAIL +SMPT_PASSWORD=SMPT_PASSWORD + +###! COUND_DINARY ### + +CLOUD_API_KEY=CLOUD_API_KEY +CLOUD_API_SECRET=CLOUD_API_SECRET +CLOUD_NAME=CLOUD_NAME + + +###! CHECK CHECK ### +CHECK_VERIFY_TRUE=CHECK_VERIFY_TRUE +CHECK_VERIFY_FALSE=CHECK_VERIFY_FALSE + +### --------------- FRONTEND --------------- ### + +###! PORT_FRONTEND ### +FRONTEND_URL=FRONTEND_URL + +###! GOOGLE_CLIENT ### +GOOGLE_CLIENT_IDS=GOOGLE_CLIENT_IDS + +GOOGLE_CLIENT_SECRETS=GOOGLE_CLIENT_SECRETS + +###! GOOGLE_MAP ### +GOOGLE_APP_GOOGLE_MAPS_API_KEY=GOOGLE_APP_GOOGLE_MAPS_API_KEY + +###! STRIPE ### + +STRIPE_KEY=STRIPE_KEY +STRIPE_PUBLIC=STRIPE_PUBLIC + +###! UV_THREADPOOL ### +UV_THREADPOOL_SIZE=UV_THREADPOOL_SIZE + +###! INLINE_RUNTIME_CHUNK ### +INLINE_RUNTIME_CHUNK=INLINE_RUNTIME_CHUNK + +###! RECAPTCHA_SECRET_KEY ### +RECAPTCHA_SECRET_KEY=RECAPTCHA_SECRET_KEY + + + +## Token +REFRESH_TOKEN_SECRET=REFRESH_TOKEN_SECRET +ACCESS_TOKEN_SECRET=ACCESS_TOKEN_SECRET diff --git a/.gitignore b/.gitignore index 90ca708..ae256cc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,21 @@ -###! Frontend ### -/frontend/node_modules -/frontend/.env -/frontend/.git - - -###! backend ### -/backend/node_modules -/backend/.env -/backend/data -/backend/mongo-entrypoint -/backend/mongoconfig -/backend/db_data -/backend/data - - -###! General ### -.env -.env.docker - -dump.rdb +###! Frontend ### +/frontend/node_modules +/frontend/.env +/frontend/.git + + +###! backend ### +/backend/node_modules +/backend/.env +/backend/data +/backend/mongo-entrypoint +/backend/mongoconfig +/backend/db_data +/backend/data + + +###! General ### +.env +.env.docker + +dump.rdb diff --git a/.vscode/settings.json b/.vscode/settings.json index 6b665aa..0540b81 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,5 @@ -{ - "liveServer.settings.port": 5501 -} +{ + "editor.formatOnSave": false, + "liveServer.settings.port": 5501, + "editor.defaultFormatter": "esbenp.prettier-vscode" +} diff --git a/README.md b/README.md index 51edb63..9c9a786 100644 --- a/README.md +++ b/README.md @@ -1,252 +1,252 @@ -

- -

-Linkedin -Profile -Phone -License -

- - -# BackEnd Code By: Nguyễn Tiến Tài :octocat: - -## Mục Tiêu: Giải quyết vấn đề thực tế,tối ưu hóa code và setup,... - -## WebSite (Hosting): https://shopshoes.cf - -## Tài Khoản thanh toán tiền chuyển khoản. - -## Tk: nguyentientai@gmail.com - -## Mk: Taideptrai123 - -## Note: Thay localhost bằng Api. - -## Api Online (Hoting và Aws Đầy đủ ) : https://shopshoedev.cf ( Aws đã hết phí sử dụng 😄 ). - -## Tài Khoản Donate li Cf để có động lực code cho anh em tham khảo 😄😄 - -![giphy](https://3.bp.blogspot.com/-SzGvXn2sTmw/V6k-90GH3ZI/AAAAAAAAIsk/Q678Pil-0kITLPa3fD--JkNdnJVKi_BygCLcB/s1600/cf10-fbc08%2B%25281%2529.gif) - -## Mk: NGUYEN TIEN TAI - -## STK: 1651002972052 - -## Chi Nhánh: NGAN HANG TMCP AN BINH (ABBANK). - -## SUPORT CONTACT:https://profile-forme.surge.sh/ - -## Upload General - -- Upload Storage : post --> http://localhost:5000/api/upload - -- Destroy Storage: post --> http://localhost:5000/api/destroy - -## 1. API Admin - -## Admin - -- Register admin: post --> http://localhost:5000/api/admin/register - -- Verification OTP: post --> http://localhost:5000/api/admin/verification/otp - -- Login admin: post --> http://localhost:5000/api/admin/login - -- logout admin: get --> http://localhost:5000/api/admin/logout - -- Get Profile Admin: get --> http://localhost:5000/api/admin/profile - -- Update profile: post --> http://localhost:5000/api/admin/update/profile - -- New access Token : get --> http://localhost:5000/api/admin/new/access - -- Change Password : post --> http://localhost:5000/api/admin/change/password - -- Forget password admin: post --> http://localhost:5000/api/admin/forget - -- Login google Admin: post --> http://localhost:5000/api/admin/login/google - -- Get all account users: get --> http://localhost:5000/api/admin/getall/users - -- Update Users and Admin : post --> http://localhost:5000/api/admin/upload/account/:id - -- Delete Users and Admins : delete --> http://localhost:5000/api/admin/delete/account/:id - -- Get all Admin: get --> http://localhost:5000/api/admin/getall/admin - - -## Categories - -- Get all category: get --> http://localhost:5000/api/category - -- Create category: post --> http://localhost:5000/api/category/create - -- Update category: post --> http://localhost:5000/api/category/edit/:id - -- Delete category: delete --> http://localhost:5000/api/category/delete/:id - -## Carousels - -- Get all Carousels: get --> http://localhost:5000/api/admin/carousel - -- Create Carousels: post --> http://localhost:5000/api/admin/carousel/create - -- Upload Carousel: post --> http://localhost:5000/api/admin/carousel/edit/:id - -- Delete Carousel: delete --> http://localhost:5000/api/admin/carousel/delete/:id - -## Vouchers - -- Get all Vouchers : get --> http://localhost:5000/api/admin/voucher - -- Create Vouchers: post --> http://localhost:5000/api/admin/voucher/create - -- Upadate Vouchers: post --> http://localhost:5000/api/admin/voucher/update/:id" - -- Delete Vouchers: delete --> http://localhost:5000/api/admin/voucher/delete/:id - -## FeedBacks - -- Get all feedback: get --> http://localhost:5000/api/feedback - -- Response Feedback: post --> http://localhost:5000/api/feedback/response/:id - -- Read Feedback: get --> http://localhost:5000/api/feedback/read/:id - -- Filter Feedback: post --> http://localhost:5000/api/feedback/filter - -## Products - -- Get all product(Sort,filter,page) : get --> http://localhost:5000/api/admin/product - -- Get detail product : get --> http://localhost:5000/api/admin/product/getId/:id - -- Create product : post --> http://localhost:5000/api/admin/product/create - -- Update product : post --> http://localhost:5000/api/admin/product/update/:id - -- Delete product : delete --> http://localhost:5000/api/admin/product/delete/:id - -## Orders - -- Get all orders: get --> http://localhost:5000/api/admin/order - -- Get all order delete : get --> http://localhost:5000/api/admin/order/delete - -- Undo order customer delete : post --> http://localhost:5000/api/admin/order/update/:id - -- Orders detail : get --> http://localhost:5000/api/admin/order/:id - -- Change status Orders: post --> http://localhost:5000/api/admin/order/upload/status/:id - - -## Statisticals - -- List users register new 3 days: get --> http://localhost:5000/api/admin/getall/user/new - -- List Monthly Registered Customers: get --> http://localhost:5000/api/admin/getall/user/register/month - -- Total turnover : get --> http://localhost:5000/api/admin/statistical/sum - -- Turnover orders order delivery this month with before month: get --> http://localhost:5000/api/admin/statistical/compare/month/received - -- Turnover orders order not delivery this month with before month: get --> http://localhost:5000/api/admin/statistical/compare/month/not/received - -- Get monthly the income customer have received (12 month): get --> http://localhost:5000/api/admin/statistical/month/received - -- Take orders order delivery new 3 days : get --> http://localhost:5000/api/admin/statistical/buy/new - -- Statisticals account register every 12 month : get --> http://localhost:5000/api/admin/getall/user/register/month - -## 2. API Users - -## Authentication Users: - -- Register Users: post --> http://localhost:5000/api/user/register - -- Verification Users: get --> http://localhost:5000/api/user/verify/:userId/:uniqueString - -- Login Email and Phone: post --> http://localhost:5000/api/user/login - -- Logout Users : get --> http://localhost:5000/api/user/logout - -- Profile Users : get --> http://localhost:5000/api/user/profile - -- Upload Profile: patch --> http://localhost:5000/api/user/update/profile - -- New Acceptoken : get --> http://localhost:5000/api/user/new/accessToken - -- Change Password : post --> http://localhost:5000/api/user/change/password - -- Forget: post --> http://localhost:5000/api/user/forget - -- Reset Passwrod : post --> http://localhost:5000/api/user/password/reset/:token - -- Login Google Users : post --> http://localhost:5000/api/user/login/google - -- Login Facebook Users: post --> http://localhost:5000/api/user/login/facebook - - -## Categories - -- Get all category : get --> http://localhost:5000/api/user/category - -## Carousels - -- Get all carousel : get --> http://localhost:5000/api/carousel - -## Carts - -- Add to cart : post --> http://localhost:5000/api/product/add/cart - -- InCrement Cart product --> http://localhost:5000/api/product/increment/cart - -- DeCrement Cart product --> http://localhost:5000/api/product/decrement/cart - -- Del Cart Product -> http://localhost:5000/api/product/del/cart - -- Get cart users: ->http://localhost:5000/api/product/get/cart - -## Feedbacks - -- Send Feedback : post --> http://localhost:5000/api/feedback/send - -## Products - -- Get all product: get --> http://localhost:5000/api/product - -- Get Product detail : get --> http://localhost:5000/api/product/detail/:id - -## Reviews - -- Comment Product: post -->http://localhost:5000/api/review/create/:id - -- Edit comment review : post --> http://localhost:5000/api/review/:productId/update/:commentId - -- Delete comment : delete --> http://localhost:5000/api/review/:productId/delete/:commentId - -- Detail Profile Users Comment: get --> http://localhost:5000/api/user/info/:id - -## Vouchers - -- Add voucher: post --> http://localhost:5000/api/user/voucher - -- Del voucher: get --> http://localhost:5000/api/user/voucher/del - -## Orders - -- Delete order flag: post --> http://localhost:5000/api/order/delete/:id - -- History orders: get --> http://localhost:5000/api/order/history - -- Get Detail orders: get -->http://localhost:5000/api/order/:id - -## Payments - -- Payment paypal: post --> http://localhost:5000/api/payment/paypal - -- Tính tiền bằng Stripe Quản lý bắng Stripe: post --> http://localhost:5000/api/payment/paymentStripe - -- Payment checkStock : get --> http://localhost:5000/api/payment/check/stock - -- Payment total : Post -->http://localhost:5000/api/payment/total +

+ +

+Linkedin +Profile +Phone +License +

+ + +# BackEnd Code By: Nguyễn Tiến Tài :octocat: + +## Mục Tiêu: Giải quyết vấn đề thực tế,tối ưu hóa code và setup,... + +## WebSite (Hosting): https://shopshoes.cf + +## Tài Khoản thanh toán tiền chuyển khoản. + +## Tk: nguyentientai@gmail.com + +## Mk: Taideptrai123 + +## Note: Thay localhost bằng Api. + +## Api Online (Hoting và Aws Đầy đủ ) : https://shopshoedev.cf ( Aws đã hết phí sử dụng 😄 ). + +## Tài Khoản Donate li Cf để có động lực code cho anh em tham khảo 😄😄 + +![giphy](https://3.bp.blogspot.com/-SzGvXn2sTmw/V6k-90GH3ZI/AAAAAAAAIsk/Q678Pil-0kITLPa3fD--JkNdnJVKi_BygCLcB/s1600/cf10-fbc08%2B%25281%2529.gif) + +## Mk: NGUYEN TIEN TAI + +## STK: 1651002972052 + +## Chi Nhánh: NGAN HANG TMCP AN BINH (ABBANK). + +## SUPORT CONTACT:https://profile-forme.surge.sh/ + +## Upload General + +- Upload Storage : post --> http://localhost:5000/api/upload + +- Destroy Storage: post --> http://localhost:5000/api/destroy + +## 1. API Admin + +## Admin + +- Register admin: post --> http://localhost:5000/api/admin/register + +- Verification OTP: post --> http://localhost:5000/api/admin/verification/otp + +- Login admin: post --> http://localhost:5000/api/admin/login + +- logout admin: get --> http://localhost:5000/api/admin/logout + +- Get Profile Admin: get --> http://localhost:5000/api/admin/profile + +- Update profile: post --> http://localhost:5000/api/admin/update/profile + +- New access Token : get --> http://localhost:5000/api/admin/new/access + +- Change Password : post --> http://localhost:5000/api/admin/change/password + +- Forget password admin: post --> http://localhost:5000/api/admin/forget + +- Login google Admin: post --> http://localhost:5000/api/admin/login/google + +- Get all account users: get --> http://localhost:5000/api/admin/getall/users + +- Update Users and Admin : post --> http://localhost:5000/api/admin/upload/account/:id + +- Delete Users and Admins : delete --> http://localhost:5000/api/admin/delete/account/:id + +- Get all Admin: get --> http://localhost:5000/api/admin/getall/admin + + +## Categories + +- Get all category: get --> http://localhost:5000/api/category + +- Create category: post --> http://localhost:5000/api/category/create + +- Update category: post --> http://localhost:5000/api/category/edit/:id + +- Delete category: delete --> http://localhost:5000/api/category/delete/:id + +## Carousels + +- Get all Carousels: get --> http://localhost:5000/api/admin/carousel + +- Create Carousels: post --> http://localhost:5000/api/admin/carousel/create + +- Upload Carousel: post --> http://localhost:5000/api/admin/carousel/edit/:id + +- Delete Carousel: delete --> http://localhost:5000/api/admin/carousel/delete/:id + +## Vouchers + +- Get all Vouchers : get --> http://localhost:5000/api/admin/voucher + +- Create Vouchers: post --> http://localhost:5000/api/admin/voucher/create + +- Upadate Vouchers: post --> http://localhost:5000/api/admin/voucher/update/:id" + +- Delete Vouchers: delete --> http://localhost:5000/api/admin/voucher/delete/:id + +## FeedBacks + +- Get all feedback: get --> http://localhost:5000/api/feedback + +- Response Feedback: post --> http://localhost:5000/api/feedback/response/:id + +- Read Feedback: get --> http://localhost:5000/api/feedback/read/:id + +- Filter Feedback: post --> http://localhost:5000/api/feedback/filter + +## Products + +- Get all product(Sort,filter,page) : get --> http://localhost:5000/api/admin/product + +- Get detail product : get --> http://localhost:5000/api/admin/product/getId/:id + +- Create product : post --> http://localhost:5000/api/admin/product/create + +- Update product : post --> http://localhost:5000/api/admin/product/update/:id + +- Delete product : delete --> http://localhost:5000/api/admin/product/delete/:id + +## Orders + +- Get all orders: get --> http://localhost:5000/api/admin/order + +- Get all order delete : get --> http://localhost:5000/api/admin/order/delete + +- Undo order customer delete : post --> http://localhost:5000/api/admin/order/update/:id + +- Orders detail : get --> http://localhost:5000/api/admin/order/:id + +- Change status Orders: post --> http://localhost:5000/api/admin/order/upload/status/:id + + +## Statisticals + +- List users register new 3 days: get --> http://localhost:5000/api/admin/getall/user/new + +- List Monthly Registered Customers: get --> http://localhost:5000/api/admin/getall/user/register/month + +- Total turnover : get --> http://localhost:5000/api/admin/statistical/sum + +- Turnover orders order delivery this month with before month: get --> http://localhost:5000/api/admin/statistical/compare/month/received + +- Turnover orders order not delivery this month with before month: get --> http://localhost:5000/api/admin/statistical/compare/month/not/received + +- Get monthly the income customer have received (12 month): get --> http://localhost:5000/api/admin/statistical/month/received + +- Take orders order delivery new 3 days : get --> http://localhost:5000/api/admin/statistical/buy/new + +- Statisticals account register every 12 month : get --> http://localhost:5000/api/admin/getall/user/register/month + +## 2. API Users + +## Authentication Users: + +- Register Users: post --> http://localhost:5000/api/user/register + +- Verification Users: get --> http://localhost:5000/api/user/verify/:userId/:uniqueString + +- Login Email and Phone: post --> http://localhost:5000/api/user/login + +- Logout Users : get --> http://localhost:5000/api/user/logout + +- Profile Users : get --> http://localhost:5000/api/user/profile + +- Upload Profile: patch --> http://localhost:5000/api/user/update/profile + +- New Acceptoken : get --> http://localhost:5000/api/user/new/accessToken + +- Change Password : post --> http://localhost:5000/api/user/change/password + +- Forget: post --> http://localhost:5000/api/user/forget + +- Reset Passwrod : post --> http://localhost:5000/api/user/password/reset/:token + +- Login Google Users : post --> http://localhost:5000/api/user/login/google + +- Login Facebook Users: post --> http://localhost:5000/api/user/login/facebook + + +## Categories + +- Get all category : get --> http://localhost:5000/api/user/category + +## Carousels + +- Get all carousel : get --> http://localhost:5000/api/carousel + +## Carts + +- Add to cart : post --> http://localhost:5000/api/product/add/cart + +- InCrement Cart product --> http://localhost:5000/api/product/increment/cart + +- DeCrement Cart product --> http://localhost:5000/api/product/decrement/cart + +- Del Cart Product -> http://localhost:5000/api/product/del/cart + +- Get cart users: ->http://localhost:5000/api/product/get/cart + +## Feedbacks + +- Send Feedback : post --> http://localhost:5000/api/feedback/send + +## Products + +- Get all product: get --> http://localhost:5000/api/product + +- Get Product detail : get --> http://localhost:5000/api/product/detail/:id + +## Reviews + +- Comment Product: post -->http://localhost:5000/api/review/create/:id + +- Edit comment review : post --> http://localhost:5000/api/review/:productId/update/:commentId + +- Delete comment : delete --> http://localhost:5000/api/review/:productId/delete/:commentId + +- Detail Profile Users Comment: get --> http://localhost:5000/api/user/info/:id + +## Vouchers + +- Add voucher: post --> http://localhost:5000/api/user/voucher + +- Del voucher: get --> http://localhost:5000/api/user/voucher/del + +## Orders + +- Delete order flag: post --> http://localhost:5000/api/order/delete/:id + +- History orders: get --> http://localhost:5000/api/order/history + +- Get Detail orders: get -->http://localhost:5000/api/order/:id + +## Payments + +- Payment paypal: post --> http://localhost:5000/api/payment/paypal + +- Tính tiền bằng Stripe Quản lý bắng Stripe: post --> http://localhost:5000/api/payment/paymentStripe + +- Payment checkStock : get --> http://localhost:5000/api/payment/check/stock + +- Payment total : Post -->http://localhost:5000/api/payment/total diff --git a/backend/.dockerignore b/backend/.dockerignore index d992b0f..4eb1c79 100644 --- a/backend/.dockerignore +++ b/backend/.dockerignore @@ -1,2 +1,2 @@ -node_modules +node_modules .git \ No newline at end of file diff --git a/backend/.gitignore b/backend/.gitignore index de8e564..e566c61 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,15 +1,15 @@ - - - -###! backend ### -node_modules -.env -data -mongo-entrypoint -mongoconfig -db_data -data -tmp - - - + + + +###! backend ### +node_modules +.env +data +mongo-entrypoint +mongoconfig +db_data +data +tmp + + + diff --git a/backend/Dockerfile.dev b/backend/Dockerfile.dev index 2889ae4..c07a05a 100644 --- a/backend/Dockerfile.dev +++ b/backend/Dockerfile.dev @@ -1,13 +1,13 @@ -FROM node:14-alpine3.12 - -WORKDIR /app - -COPY . . - -RUN npm install -g nodemon - -HEALTHCHECK --interval=60s --timeout=2s --retries=3 CMD wget localhost:5000/api/ -q -O - > /dev/null 2>&1 - -CMD [ "npm","run","dev"] - +FROM node:14-alpine3.12 + +WORKDIR /app + +COPY . . + +RUN npm install -g nodemon + +HEALTHCHECK --interval=60s --timeout=2s --retries=3 CMD wget localhost:5000/api/ -q -O - > /dev/null 2>&1 + +CMD [ "npm","run","dev"] + EXPOSE 5000 \ No newline at end of file diff --git a/backend/app.js b/backend/app.js index fad235f..6536c6c 100644 --- a/backend/app.js +++ b/backend/app.js @@ -1,174 +1,174 @@ -//! Library -const express = require("express"); -const cookieParser = require("cookie-parser"); -const fileUpload = require("express-fileupload"); -const cors = require("cors"); -const helmet = require("helmet"); -const session = require("express-session"); -let RedisStore = require("connect-redis")(session); -const bodyParser = require("body-parser"); -const compression = require("compression"); -const cron = require("node-cron"); - -//! Import -const REDIS = require("./src/v1/db/redis_db"); -const Mongo_DB = require("./src/v1/db/mongo_db"); -const CONSTANTS = require("./src/v1/configs/constants"); -const Cron_Users = require("./src/v1/user_api/cron_users/index"); -//! Connect -Mongo_DB(); - -//! used library -const app = express(); -if (process.env.NODE_ENV === "PRODUCTION") { - app.enable("trust proxy"); -} -app.enable("trust proxy"); -app.use(helmet()); -app.use(express.json()); -app.use(cookieParser()); -app.use(cors()); -app.use(bodyParser.urlencoded({ extended: true })); -app.use( - fileUpload({ - useTempFiles: true, - }) -); -app.use( - express.json({ - verify: (req, res, buffer) => (req["rawBody"] = buffer), - }) -); -app.use( - session({ - store: new RedisStore({ client: REDIS }), - secret: CONSTANTS.KEY_SESSION, - resave: process.env.NODE_ENV === "PRODUCTION" ? true : false, - saveUninitialized: true, - cookie: { - secure: process.env.NODE_ENV === "PRODUCTION" ? true : false, - httpOnly: true, - maxAge: CONSTANTS._5_MINUTES, - }, - }) -); -app.use( - compression({ - level: 6, - threshold: 100 * 1000, - filter: (req, res) => { - if (req.headers["x-no-compression"]) { - return false; - } - return compression.filter(req, res); - }, - }) -); - -//***** Run Cron ******/ -cron.schedule("*/5 * * * *", function() { - console.log("Run Check Uncheck Users"); - Cron_Users.Delete_User_Un_Check_Expired(); -}); - -//* ------------------------- Upload General ------------------------- // -const upload_routes = require("./src/v1/upload_cloudinary/routes/upload.routes"); -app.use("/api", upload_routes); - -//* ------------------------- Users ------------------------- // - -// !! USER_ROUTES -const users_routes = require("./src/v1/user_api/routes/user.routes"); - -app.use("/api", users_routes); - -//* ------------------------- Products ------------------------- // - -// !! PRODUCT_ROUTES -const products_routes = require("./src/v1/user_api/routes/product.routes"); - -app.use("/api", products_routes); - -//* ------------------------- Category ------------------------- // - -// !! CATEGORY_ROUTES -const category_routes = require("./src/v1/user_api/routes/categories.routes"); - -app.use("/api", category_routes); - -// !! REVIEW_ROUTES -const user_review = require("./src/v1/user_api/routes/review.routes"); - -app.use("/api", user_review); - -// !! FEEDBACK_ROUTES -const user_feedback = require("./src/v1/user_api/routes/feedback.routes"); - -app.use("/api", user_feedback); - -// !! CAROUSEL_ROUTES -const user_carousel = require("./src/v1/user_api/routes/carousel.routes"); - -app.use("/api", user_carousel); -// !! VOUCHER_ROUTES -const voucher_carousel = require("./src/v1/user_api/routes/voucher.routes"); - -app.use("/api", voucher_carousel); - -// !! PAYMENT_ROUTES -const payment_carousel = require("./src/v1/user_api/routes/payment.routes"); - -app.use("/api", payment_carousel); - -// !! ORDER_ROUTES -const order_carousel = require("./src/v1/user_api/routes/order.routes"); - -app.use("/api", order_carousel); - -//* ------------------------- Admins ------------------------- // -//!! ADMIN_ROUTE -const admins_routes = require("./src/v1/admin_api/routes/admin.routes"); - -//!Route Admin -app.use("/api", admins_routes); - -//!Product Admin -const product_routes = require("./src/v1/admin_api/routes/product_admin.route"); -app.use("/api", product_routes); - -// !! CATEGORY_ROUTES -const category_routes_admin = require("./src/v1/admin_api/routes/categories.routes"); - -app.use("/api", category_routes_admin); - -// !! FEEDBACK_ROUTES -const feedback_routes_admin = require("./src/v1/admin_api/routes/feedback.route"); - -app.use("/api", feedback_routes_admin); - -// !! FEEDBACK_ROUTES -const carousel_routes_admin = require("./src/v1/admin_api/routes/carousel.routes"); - -app.use("/api", carousel_routes_admin); - -// !! VOUCHER_ROUTES -const voucher_routes_admin = require("./src/v1/admin_api/routes/voucher.routes"); - -app.use("/api", voucher_routes_admin); - -//!! Manager_Users_ROUTES -const manager_user_routes = require("./src/v1/admin_api/routes/manager_user.routes"); - -app.use("/api", manager_user_routes); - -//!! Order_Admin_ROUTES -const order_admin_routes = require("./src/v1/admin_api/routes/order.routes"); - -app.use("/api", order_admin_routes); - -// !! _ROUTES -const statistical_carousel = require("./src/v1/admin_api/routes/statistical.routes"); - -app.use("/api", statistical_carousel); - -module.exports = app; +//! Library +const express = require("express"); +const cookieParser = require("cookie-parser"); +const fileUpload = require("express-fileupload"); +const cors = require("cors"); +const helmet = require("helmet"); +const session = require("express-session"); +let RedisStore = require("connect-redis")(session); +const bodyParser = require("body-parser"); +const compression = require("compression"); +const cron = require("node-cron"); + +//! Import +const REDIS = require("./src/v1/db/redis_db"); +const Mongo_DB = require("./src/v1/db/mongo_db"); +const CONSTANTS = require("./src/v1/configs/constants"); +const Cron_Users = require("./src/v1/user_api/cron_users/index"); +//! Connect +Mongo_DB(); + +//! used library +const app = express(); +if (process.env.NODE_ENV === "PRODUCTION") { + app.enable("trust proxy"); +} +app.enable("trust proxy"); +app.use(helmet()); +app.use(express.json()); +app.use(cookieParser()); +app.use(cors()); +app.use(bodyParser.urlencoded({ extended: true })); +app.use( + fileUpload({ + useTempFiles: true, + }) +); +app.use( + express.json({ + verify: (req, res, buffer) => (req["rawBody"] = buffer), + }) +); +app.use( + session({ + store: new RedisStore({ client: REDIS }), + secret: CONSTANTS.KEY_SESSION, + resave: process.env.NODE_ENV === "PRODUCTION" ? true : false, + saveUninitialized: true, + cookie: { + secure: process.env.NODE_ENV === "PRODUCTION" ? true : false, + httpOnly: true, + maxAge: CONSTANTS._5_MINUTES, + }, + }) +); +app.use( + compression({ + level: 6, + threshold: 100 * 1000, + filter: (req, res) => { + if (req.headers["x-no-compression"]) { + return false; + } + return compression.filter(req, res); + }, + }) +); + +//***** Run Cron ******/ +cron.schedule("*/5 * * * *", function() { + console.log("Run Check Uncheck Users"); + Cron_Users.Delete_User_Un_Check_Expired(); +}); + +//* ------------------------- Upload General ------------------------- // +const upload_routes = require("./src/v1/upload_cloudinary/routes/upload.routes"); +app.use("/api", upload_routes); + +//* ------------------------- Users ------------------------- // + +// !! USER_ROUTES +const users_routes = require("./src/v1/user_api/routes/user.routes"); + +app.use("/api", users_routes); + +//* ------------------------- Products ------------------------- // + +// !! PRODUCT_ROUTES +const products_routes = require("./src/v1/user_api/routes/product.routes"); + +app.use("/api", products_routes); + +//* ------------------------- Category ------------------------- // + +// !! CATEGORY_ROUTES +const category_routes = require("./src/v1/user_api/routes/categories.routes"); + +app.use("/api", category_routes); + +// !! REVIEW_ROUTES +const user_review = require("./src/v1/user_api/routes/review.routes"); + +app.use("/api", user_review); + +// !! FEEDBACK_ROUTES +const user_feedback = require("./src/v1/user_api/routes/feedback.routes"); + +app.use("/api", user_feedback); + +// !! CAROUSEL_ROUTES +const user_carousel = require("./src/v1/user_api/routes/carousel.routes"); + +app.use("/api", user_carousel); +// !! VOUCHER_ROUTES +const voucher_carousel = require("./src/v1/user_api/routes/voucher.routes"); + +app.use("/api", voucher_carousel); + +// !! PAYMENT_ROUTES +const payment_carousel = require("./src/v1/user_api/routes/payment.routes"); + +app.use("/api", payment_carousel); + +// !! ORDER_ROUTES +const order_carousel = require("./src/v1/user_api/routes/order.routes"); + +app.use("/api", order_carousel); + +//* ------------------------- Admins ------------------------- // +//!! ADMIN_ROUTE +const admins_routes = require("./src/v1/admin_api/routes/admin.routes"); + +//!Route Admin +app.use("/api", admins_routes); + +//!Product Admin +const product_routes = require("./src/v1/admin_api/routes/product_admin.route"); +app.use("/api", product_routes); + +// !! CATEGORY_ROUTES +const category_routes_admin = require("./src/v1/admin_api/routes/categories.routes"); + +app.use("/api", category_routes_admin); + +// !! FEEDBACK_ROUTES +const feedback_routes_admin = require("./src/v1/admin_api/routes/feedback.route"); + +app.use("/api", feedback_routes_admin); + +// !! FEEDBACK_ROUTES +const carousel_routes_admin = require("./src/v1/admin_api/routes/carousel.routes"); + +app.use("/api", carousel_routes_admin); + +// !! VOUCHER_ROUTES +const voucher_routes_admin = require("./src/v1/admin_api/routes/voucher.routes"); + +app.use("/api", voucher_routes_admin); + +//!! Manager_Users_ROUTES +const manager_user_routes = require("./src/v1/admin_api/routes/manager_user.routes"); + +app.use("/api", manager_user_routes); + +//!! Order_Admin_ROUTES +const order_admin_routes = require("./src/v1/admin_api/routes/order.routes"); + +app.use("/api", order_admin_routes); + +// !! _ROUTES +const statistical_carousel = require("./src/v1/admin_api/routes/statistical.routes"); + +app.use("/api", statistical_carousel); + +module.exports = app; diff --git a/backend/package-lock.json b/backend/package-lock.json index a34bf04..1feb0bc 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1,2528 +1,2528 @@ -{ - "name": "backend", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@ioredis/commands": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", - "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" - }, - "@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", - "requires": { - "detect-libc": "^2.0.0", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.7", - "nopt": "^5.0.0", - "npmlog": "^5.0.1", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.11" - } - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "optional": true - }, - "@types/node": { - "version": "18.7.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz", - "integrity": "sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==" - }, - "@types/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" - }, - "@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "requires": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "optional": true - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "optional": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz", - "integrity": "sha512-TnB6ziK363p7lR8QpeLC8aMr8EGYBKZTpgzQLfqTs3bR0Oo5VbKdwKf8h0dSzsYrB7lSCgfJnMZKqShvlq5Oyg==" - }, - "algoliasearch": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.35.1.tgz", - "integrity": "sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ==", - "requires": { - "agentkeepalive": "^2.2.0", - "debug": "^2.6.9", - "envify": "^4.0.0", - "es6-promise": "^4.1.0", - "events": "^1.1.0", - "foreach": "^2.0.5", - "global": "^4.3.2", - "inherits": "^2.0.1", - "isarray": "^2.0.1", - "load-script": "^1.0.0", - "object-keys": "^1.0.11", - "querystring-es3": "^0.2.1", - "reduce": "^1.0.1", - "semver": "^5.1.0", - "tunnel-agent": "^0.6.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" - }, - "are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" - }, - "ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "optional": true, - "requires": { - "tslib": "^2.0.1" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" - }, - "bcrypt": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", - "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", - "requires": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^3.1.0" - } - }, - "bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" - }, - "bignumber.js": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", - "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==" - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "body-parser": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", - "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "requires": { - "fill-range": "^7.0.1" - } - }, - "bson": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", - "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", - "requires": { - "buffer": "^5.6.0" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, - "busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "requires": { - "streamsearch": "^1.1.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" - }, - "cli-color": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", - "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", - "requires": { - "ansi-regex": "^2.1.1", - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.14", - "timers-ext": "^0.1.5" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" - } - } - }, - "cloudinary": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.32.0.tgz", - "integrity": "sha512-hbc5/ilOkwD49+Lucqze3z+2Tejc3YdH4tkI+y1Ciabi9Qh9MYcy4M3rYeDAYiMS/jIz5FfHOzx+JjVnPJxNAQ==", - "requires": { - "cloudinary-core": "^2.10.2", - "core-js": "^3.6.5", - "lodash": "^4.17.21", - "proxy-agent": "^5.0.0", - "q": "^1.5.1" - } - }, - "cloudinary-core": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.13.0.tgz", - "integrity": "sha512-Nt0Q5I2FtenmJghtC4YZ3MZZbGg1wLm84SsxcuVwZ83OyJqG9CNIGp86CiI6iDv3QobaqBUpOT7vg+HqY5HxEA==" - }, - "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "connect-redis": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.1.3.tgz", - "integrity": "sha512-aaNluLlAn/3JPxRwdzw7lhvEoU6Enb+d83xnokUNhC9dktqBoawKWL+WuxinxvBLTz6q9vReTnUDnUslaz74aw==" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "cookie-parser": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", - "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", - "requires": { - "cookie": "0.4.1", - "cookie-signature": "1.0.6" - } - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "core-js": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.2.tgz", - "integrity": "sha512-YB4IAT1bjEfxTJ1XYy11hJAKskO+qmhuDBM8/guIfMz4JvdsAQAqvyb97zXX7JgSrfPLG5mRGFWJwJD39ruq2A==" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "optional": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, - "data-uri-to-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", - "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", - "optional": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "optional": true - }, - "deep-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/deep-keys/-/deep-keys-0.4.0.tgz", - "integrity": "sha512-rZL9YWyM1/5PHWbVwAMdv73FM2r94Ns/IimrdIAGOxAUrja2UKwrNRSCcJOZT+JZMtl7GWSlT3ZPUYgLxXbLLQ==" - }, - "degenerator": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.2.tgz", - "integrity": "sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==", - "optional": true, - "requires": { - "ast-types": "^0.13.2", - "escodegen": "^1.8.1", - "esprima": "^4.0.0", - "vm2": "^3.9.8" - } - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" - }, - "denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" - }, - "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" - }, - "dom-walk": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", - "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" - }, - "ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" - }, - "envify": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", - "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==", - "requires": { - "esprima": "^4.0.0", - "through": "~2.3.4" - } - }, - "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "requires": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "requires": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "optional": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "optional": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "optional": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" - }, - "express": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", - "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "express-async-handler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/express-async-handler/-/express-async-handler-1.2.0.tgz", - "integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==" - }, - "express-fileupload": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.4.0.tgz", - "integrity": "sha512-RjzLCHxkv3umDeZKeFeMg8w7qe0V09w3B7oGZprr/oO2H/ISCgNzuqzn7gV3HRWb37GjRk429CCpSLS2KNTqMQ==", - "requires": { - "busboy": "^1.6.0" - } - }, - "express-handlebars": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.6.tgz", - "integrity": "sha512-E4QHYCh+9fyfdBEb8uKJ8p6HD4qq/sUSHBq83lRNlLJp2TQKEg2nFJYbVdC+M3QzaV19dODe43lgjQWVaIpbyQ==", - "requires": { - "glob": "^8.0.2", - "graceful-fs": "^4.2.10", - "handlebars": "^4.7.7" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, - "express-rate-limit": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz", - "integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==" - }, - "express-session": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", - "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", - "requires": { - "cookie": "0.4.2", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.1", - "uid-safe": "~2.1.5" - }, - "dependencies": { - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "requires": { - "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "optional": true - }, - "fast-text-encoding": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", - "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" - }, - "file-uri-to-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", - "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", - "optional": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "foreach": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", - "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==" - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "optional": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "requires": { - "minipass": "^3.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "ftp": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", - "integrity": "sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==", - "optional": true, - "requires": { - "readable-stream": "1.1.x", - "xregexp": "2.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "optional": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, - "gaxios": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", - "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", - "requires": { - "abort-controller": "^3.0.0", - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.7" - } - }, - "gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", - "requires": { - "gaxios": "^4.0.0", - "json-bigint": "^1.0.0" - } - }, - "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", - "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "data-uri-to-buffer": "3", - "debug": "4", - "file-uri-to-path": "2", - "fs-extra": "^8.1.0", - "ftp": "^0.3.10" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "global": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", - "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", - "requires": { - "min-document": "^2.19.0", - "process": "^0.11.10" - } - }, - "google-auth-library": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", - "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", - "requires": { - "arrify": "^2.0.0", - "base64-js": "^1.3.0", - "ecdsa-sig-formatter": "^1.0.11", - "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", - "jws": "^4.0.0", - "lru-cache": "^6.0.0" - } - }, - "google-p12-pem": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", - "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", - "requires": { - "node-forge": "^1.3.1" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", - "requires": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", - "jws": "^4.0.0" - } - }, - "handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" - }, - "helmet": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-6.0.0.tgz", - "integrity": "sha512-FO9RpR1wNJepH/GbLPQVtkE2eESglXL641p7SdyoT4LngHFJcZheHMoyUcjCZF4qpuMMO1u5q6RK0l9Ux8JBcg==" - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ioredis": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.3.tgz", - "integrity": "sha512-gQNcMF23/NpvjCaa1b5YycUyQJ9rBNH2xP94LWinNpodMWVUPP5Ai/xXANn/SM7gfIvI62B5CCvZxhg5pOgyMw==", - "requires": { - "@ioredis/commands": "^1.1.1", - "cluster-key-slot": "^1.1.0", - "debug": "^4.3.4", - "denque": "^2.0.1", - "lodash.defaults": "^4.2.0", - "lodash.isarguments": "^3.1.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0", - "standard-as-callback": "^2.1.0" - } - }, - "ip": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", - "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", - "optional": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "optional": true - }, - "json-bigint": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", - "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", - "requires": { - "bignumber.js": "^9.0.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "optional": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "requires": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "dependencies": { - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", - "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", - "requires": { - "jwa": "^2.0.0", - "safe-buffer": "^5.0.1" - } - }, - "kareem": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.4.1.tgz", - "integrity": "sha512-aJ9opVoXroQUPfovYP5kaj2lM7Jn02Gw13bL0lg9v0V7SaUc0qavPs0Eue7d2DcC3NjqI6QAUElXNsuZSeM+EA==" - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-script": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", - "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==" - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" - }, - "lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" - }, - "lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "requires": { - "es5-ext": "~0.10.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" - }, - "memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "requires": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, - "memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", - "requires": { - "dom-walk": "^0.1.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "requires": { - "yallist": "^4.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mongodb": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.1.tgz", - "integrity": "sha512-ZhgI/qBf84fD7sI4waZBoLBNJYPQN5IOC++SBCiPiyhzpNKOxN/fi0tBHvH2dEC42HXtNEbFB0zmNz4+oVtorQ==", - "requires": { - "bson": "^4.7.0", - "denque": "^2.1.0", - "mongodb-connection-string-url": "^2.5.3", - "saslprep": "^1.0.3", - "socks": "^2.7.0" - } - }, - "mongodb-connection-string-url": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", - "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", - "requires": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" - }, - "dependencies": { - "tr46": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", - "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", - "requires": { - "punycode": "^2.1.1" - } - }, - "webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" - }, - "whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", - "requires": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - } - } - } - }, - "mongoose": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.6.1.tgz", - "integrity": "sha512-hPDamnn6quL9TjIrOudqUS5sMilENmP/gfxoCIb+rDmlzawtM7+MVCAWrM9930fzD20N7qAema/zE9QIDuifhQ==", - "requires": { - "bson": "^4.6.5", - "kareem": "2.4.1", - "mongodb": "4.9.1", - "mpath": "0.9.0", - "mquery": "4.0.3", - "ms": "2.1.3", - "sift": "16.0.0" - }, - "dependencies": { - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "mongoose-algolia": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/mongoose-algolia/-/mongoose-algolia-1.10.1.tgz", - "integrity": "sha512-vA1cH81xbSoaFB6nYyLctEtYcKSyH98OOGabvPWneuCmkOgeq/cJ++iPPShgZvhc9DfwSiiyuzx2a9R6AH1h0Q==", - "requires": { - "algoliasearch": "^3.35.1", - "cli-color": "^1.1.0", - "deep-keys": "^0.4.0" - } - }, - "mpath": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", - "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" - }, - "mquery": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.3.tgz", - "integrity": "sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA==", - "requires": { - "debug": "4.x" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "optional": true - }, - "next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" - }, - "node-cron": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.2.tgz", - "integrity": "sha512-iP8l0yGlNpE0e6q1o185yOApANRe47UPbLf4YxfbiNHt/RU5eBcGB/e0oudruheSf+LQeDMezqC5BVAb5wwRcQ==", - "requires": { - "uuid": "8.3.2" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" - }, - "nodemailer": { - "version": "6.7.8", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.8.tgz", - "integrity": "sha512-2zaTFGqZixVmTxpJRCFC+Vk5eGRd/fYtvIR+dl5u9QXLTQWGIf48x/JXvo58g9sa0bU6To04XUv554Paykum3g==" - }, - "nodemailer-express-handlebars": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nodemailer-express-handlebars/-/nodemailer-express-handlebars-5.0.0.tgz", - "integrity": "sha512-DMeoCr8kSyLjzXZR+wclDidPDcgy68mIiuSlDZeeDP4IQLJmRzXrlTv+3C2r+uYUnajN5vxqB8pTBdju6aH/yA==", - "requires": { - "express-handlebars": "^6.0.0" - } - }, - "nodemon": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", - "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", - "requires": { - "chokidar": "^3.5.2", - "debug": "^3.2.7", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.1.2", - "pstree.remy": "^1.1.8", - "semver": "^5.7.1", - "simple-update-notifier": "^1.0.7", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.5" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "optional": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "otp-generator": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/otp-generator/-/otp-generator-4.0.0.tgz", - "integrity": "sha512-P0nG+RVCRDkZdEjXgoMeOTVF3jwMShAk8qYYNx+VNdWgxhcLbZQjdx3GfzgRTZENTx+9I14XfTDJZjKQJdBcVw==" - }, - "pac-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", - "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", - "optional": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4", - "get-uri": "3", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "5", - "pac-resolver": "^5.0.0", - "raw-body": "^2.2.0", - "socks-proxy-agent": "5" - } - }, - "pac-resolver": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.1.tgz", - "integrity": "sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==", - "optional": true, - "requires": { - "degenerator": "^3.0.2", - "ip": "^1.1.5", - "netmask": "^2.0.2" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "optional": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - } - }, - "proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", - "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", - "optional": true, - "requires": { - "agent-base": "^6.0.0", - "debug": "4", - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "lru-cache": "^5.1.1", - "pac-proxy-agent": "^5.0.0", - "proxy-from-env": "^1.0.0", - "socks-proxy-agent": "^5.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "optional": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "optional": true - } - } - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "optional": true - }, - "pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" - }, - "qs": { - "version": "6.10.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", - "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" - }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - }, - "redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" - }, - "redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", - "requires": { - "redis-errors": "^1.0.0" - } - }, - "reduce": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", - "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", - "requires": { - "object-keys": "^1.1.0" - } - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "sift": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", - "integrity": "sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "simple-update-notifier": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", - "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", - "requires": { - "semver": "~7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" - } - } - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" - }, - "socks": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", - "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - }, - "dependencies": { - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" - } - } - }, - "socks-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", - "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", - "optional": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "4", - "socks": "^2.3.3" - } - }, - "sonyflake": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sonyflake/-/sonyflake-1.1.2.tgz", - "integrity": "sha512-A9CEnf/a7xOvNtVWoDyFxHxVdL/LXlm0YMpFyARGguR5LjJWGY6oVU9L/Y43p7HaGgE3ombWa6TiDGkLB/SYug==" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", - "optional": true, - "requires": { - "memory-pager": "^1.0.2" - } - }, - "standard-as-callback": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", - "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "stripe": { - "version": "8.222.0", - "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.222.0.tgz", - "integrity": "sha512-hrA79fjmN2Eb6K3kxkDzU4ODeVGGjXQsuVaAPSUro6I9MM3X+BvIsVqdphm3BXWfimAGFvUqWtPtHy25mICY1w==", - "requires": { - "@types/node": ">=8.1.0", - "qs": "^6.10.3" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "requires": { - "nopt": "~1.0.10" - }, - "dependencies": { - "nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", - "requires": { - "abbrev": "1" - } - } - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "optional": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "uglify-js": { - "version": "3.17.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz", - "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==", - "optional": true - }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "requires": { - "random-bytes": "~1.0.0" - } - }, - "undefsafe": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", - "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "optional": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "validator": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", - "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" - }, - "vm2": { - "version": "3.9.11", - "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.11.tgz", - "integrity": "sha512-PFG8iJRSjvvBdisowQ7iVF580DXb1uCIiGaXgm7tynMR1uTBlv7UJlB1zdv5KJ+Tmq1f0Upnj3fayoEOPpCBKg==", - "optional": true, - "requires": { - "acorn": "^8.7.0", - "acorn-walk": "^8.2.0" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "optional": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "xregexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", - "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", - "optional": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } -} +{ + "name": "backend", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ioredis/commands": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz", + "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==" + }, + "@mapbox/node-pre-gyp": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", + "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true + }, + "@types/node": { + "version": "18.7.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz", + "integrity": "sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg==" + }, + "@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "optional": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "optional": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz", + "integrity": "sha512-TnB6ziK363p7lR8QpeLC8aMr8EGYBKZTpgzQLfqTs3bR0Oo5VbKdwKf8h0dSzsYrB7lSCgfJnMZKqShvlq5Oyg==" + }, + "algoliasearch": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.35.1.tgz", + "integrity": "sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ==", + "requires": { + "agentkeepalive": "^2.2.0", + "debug": "^2.6.9", + "envify": "^4.0.0", + "es6-promise": "^4.1.0", + "events": "^1.1.0", + "foreach": "^2.0.5", + "global": "^4.3.2", + "inherits": "^2.0.1", + "isarray": "^2.0.1", + "load-script": "^1.0.0", + "object-keys": "^1.0.11", + "querystring-es3": "^0.2.1", + "reduce": "^1.0.1", + "semver": "^5.1.0", + "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + }, + "ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "optional": true, + "requires": { + "tslib": "^2.0.1" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bcrypt": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", + "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^3.1.0" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "bignumber.js": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", + "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "bson": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.0.tgz", + "integrity": "sha512-VrlEE4vuiO1WTpfof4VmaVolCVYkYTgB9iWgYNOrVlnifpME/06fhFRmONgBhClD5pFC1t9ZWqFUQEQAzY43bA==", + "requires": { + "buffer": "^5.6.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "cli-color": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz", + "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==", + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + } + } + }, + "cloudinary": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.32.0.tgz", + "integrity": "sha512-hbc5/ilOkwD49+Lucqze3z+2Tejc3YdH4tkI+y1Ciabi9Qh9MYcy4M3rYeDAYiMS/jIz5FfHOzx+JjVnPJxNAQ==", + "requires": { + "cloudinary-core": "^2.10.2", + "core-js": "^3.6.5", + "lodash": "^4.17.21", + "proxy-agent": "^5.0.0", + "q": "^1.5.1" + } + }, + "cloudinary-core": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.13.0.tgz", + "integrity": "sha512-Nt0Q5I2FtenmJghtC4YZ3MZZbGg1wLm84SsxcuVwZ83OyJqG9CNIGp86CiI6iDv3QobaqBUpOT7vg+HqY5HxEA==" + }, + "cluster-key-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", + "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "connect-redis": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/connect-redis/-/connect-redis-6.1.3.tgz", + "integrity": "sha512-aaNluLlAn/3JPxRwdzw7lhvEoU6Enb+d83xnokUNhC9dktqBoawKWL+WuxinxvBLTz6q9vReTnUDnUslaz74aw==" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "core-js": { + "version": "3.25.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.2.tgz", + "integrity": "sha512-YB4IAT1bjEfxTJ1XYy11hJAKskO+qmhuDBM8/guIfMz4JvdsAQAqvyb97zXX7JgSrfPLG5mRGFWJwJD39ruq2A==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "optional": true + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "data-uri-to-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz", + "integrity": "sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==", + "optional": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "optional": true + }, + "deep-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/deep-keys/-/deep-keys-0.4.0.tgz", + "integrity": "sha512-rZL9YWyM1/5PHWbVwAMdv73FM2r94Ns/IimrdIAGOxAUrja2UKwrNRSCcJOZT+JZMtl7GWSlT3ZPUYgLxXbLLQ==" + }, + "degenerator": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-3.0.2.tgz", + "integrity": "sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==", + "optional": true, + "requires": { + "ast-types": "^0.13.2", + "escodegen": "^1.8.1", + "esprima": "^4.0.0", + "vm2": "^3.9.8" + } + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "envify": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", + "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==", + "requires": { + "esprima": "^4.0.0", + "through": "~2.3.4" + } + }, + "es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "optional": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "optional": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "optional": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "express-async-handler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/express-async-handler/-/express-async-handler-1.2.0.tgz", + "integrity": "sha512-rCSVtPXRmQSW8rmik/AIb2P0op6l7r1fMW538yyvTMltCO4xQEWMmobfrIxN2V1/mVrgxB8Az3reYF6yUZw37w==" + }, + "express-fileupload": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.4.0.tgz", + "integrity": "sha512-RjzLCHxkv3umDeZKeFeMg8w7qe0V09w3B7oGZprr/oO2H/ISCgNzuqzn7gV3HRWb37GjRk429CCpSLS2KNTqMQ==", + "requires": { + "busboy": "^1.6.0" + } + }, + "express-handlebars": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/express-handlebars/-/express-handlebars-6.0.6.tgz", + "integrity": "sha512-E4QHYCh+9fyfdBEb8uKJ8p6HD4qq/sUSHBq83lRNlLJp2TQKEg2nFJYbVdC+M3QzaV19dODe43lgjQWVaIpbyQ==", + "requires": { + "glob": "^8.0.2", + "graceful-fs": "^4.2.10", + "handlebars": "^4.7.7" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "express-rate-limit": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz", + "integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==" + }, + "express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "requires": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "requires": { + "type": "^2.7.2" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "optional": true + }, + "fast-text-encoding": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" + }, + "file-uri-to-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-2.0.0.tgz", + "integrity": "sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==", + "optional": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "foreach": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.6.tgz", + "integrity": "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==" + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "optional": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==", + "optional": true, + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "gaxios": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz", + "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==", + "requires": { + "abort-controller": "^3.0.0", + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.7" + } + }, + "gcp-metadata": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", + "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "requires": { + "gaxios": "^4.0.0", + "json-bigint": "^1.0.0" + } + }, + "get-intrinsic": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-uri": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-3.0.2.tgz", + "integrity": "sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==", + "optional": true, + "requires": { + "@tootallnate/once": "1", + "data-uri-to-buffer": "3", + "debug": "4", + "file-uri-to-path": "2", + "fs-extra": "^8.1.0", + "ftp": "^0.3.10" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "google-auth-library": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", + "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "requires": { + "arrify": "^2.0.0", + "base64-js": "^1.3.0", + "ecdsa-sig-formatter": "^1.0.11", + "fast-text-encoding": "^1.0.0", + "gaxios": "^4.0.0", + "gcp-metadata": "^4.2.0", + "gtoken": "^5.0.4", + "jws": "^4.0.0", + "lru-cache": "^6.0.0" + } + }, + "google-p12-pem": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz", + "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==", + "requires": { + "node-forge": "^1.3.1" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "gtoken": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", + "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "requires": { + "gaxios": "^4.0.0", + "google-p12-pem": "^3.1.3", + "jws": "^4.0.0" + } + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, + "helmet": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-6.0.0.tgz", + "integrity": "sha512-FO9RpR1wNJepH/GbLPQVtkE2eESglXL641p7SdyoT4LngHFJcZheHMoyUcjCZF4qpuMMO1u5q6RK0l9Ux8JBcg==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ioredis": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.3.tgz", + "integrity": "sha512-gQNcMF23/NpvjCaa1b5YycUyQJ9rBNH2xP94LWinNpodMWVUPP5Ai/xXANn/SM7gfIvI62B5CCvZxhg5pOgyMw==", + "requires": { + "@ioredis/commands": "^1.1.1", + "cluster-key-slot": "^1.1.0", + "debug": "^4.3.4", + "denque": "^2.0.1", + "lodash.defaults": "^4.2.0", + "lodash.isarguments": "^3.1.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0", + "standard-as-callback": "^2.1.0" + } + }, + "ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "optional": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "optional": true + }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "requires": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, + "kareem": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.4.1.tgz", + "integrity": "sha512-aJ9opVoXroQUPfovYP5kaj2lM7Jn02Gw13bL0lg9v0V7SaUc0qavPs0Eue7d2DcC3NjqI6QAUElXNsuZSeM+EA==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==" + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "requires": { + "es5-ext": "~0.10.2" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "requires": { + "dom-walk": "^0.1.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mongodb": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.9.1.tgz", + "integrity": "sha512-ZhgI/qBf84fD7sI4waZBoLBNJYPQN5IOC++SBCiPiyhzpNKOxN/fi0tBHvH2dEC42HXtNEbFB0zmNz4+oVtorQ==", + "requires": { + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", + "saslprep": "^1.0.3", + "socks": "^2.7.0" + } + }, + "mongodb-connection-string-url": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.3.tgz", + "integrity": "sha512-f+/WsED+xF4B74l3k9V/XkTVj5/fxFH2o5ToKXd8Iyi5UhM+sO9u0Ape17Mvl/GkZaFtM0HQnzAG5OTmhKw+tQ==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + }, + "dependencies": { + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } + }, + "mongoose": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.6.1.tgz", + "integrity": "sha512-hPDamnn6quL9TjIrOudqUS5sMilENmP/gfxoCIb+rDmlzawtM7+MVCAWrM9930fzD20N7qAema/zE9QIDuifhQ==", + "requires": { + "bson": "^4.6.5", + "kareem": "2.4.1", + "mongodb": "4.9.1", + "mpath": "0.9.0", + "mquery": "4.0.3", + "ms": "2.1.3", + "sift": "16.0.0" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "mongoose-algolia": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/mongoose-algolia/-/mongoose-algolia-1.10.1.tgz", + "integrity": "sha512-vA1cH81xbSoaFB6nYyLctEtYcKSyH98OOGabvPWneuCmkOgeq/cJ++iPPShgZvhc9DfwSiiyuzx2a9R6AH1h0Q==", + "requires": { + "algoliasearch": "^3.35.1", + "cli-color": "^1.1.0", + "deep-keys": "^0.4.0" + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-4.0.3.tgz", + "integrity": "sha512-J5heI+P08I6VJ2Ky3+33IpCdAvlYGTSUjwTPxkAr8i8EoduPMBX2OY/wa3IKZIQl7MU4SbFk8ndgSKyB/cl1zA==", + "requires": { + "debug": "4.x" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "optional": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, + "node-cron": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.2.tgz", + "integrity": "sha512-iP8l0yGlNpE0e6q1o185yOApANRe47UPbLf4YxfbiNHt/RU5eBcGB/e0oudruheSf+LQeDMezqC5BVAb5wwRcQ==", + "requires": { + "uuid": "8.3.2" + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "nodemailer": { + "version": "6.7.8", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.8.tgz", + "integrity": "sha512-2zaTFGqZixVmTxpJRCFC+Vk5eGRd/fYtvIR+dl5u9QXLTQWGIf48x/JXvo58g9sa0bU6To04XUv554Paykum3g==" + }, + "nodemailer-express-handlebars": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nodemailer-express-handlebars/-/nodemailer-express-handlebars-5.0.0.tgz", + "integrity": "sha512-DMeoCr8kSyLjzXZR+wclDidPDcgy68mIiuSlDZeeDP4IQLJmRzXrlTv+3C2r+uYUnajN5vxqB8pTBdju6aH/yA==", + "requires": { + "express-handlebars": "^6.0.0" + } + }, + "nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "optional": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "otp-generator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/otp-generator/-/otp-generator-4.0.0.tgz", + "integrity": "sha512-P0nG+RVCRDkZdEjXgoMeOTVF3jwMShAk8qYYNx+VNdWgxhcLbZQjdx3GfzgRTZENTx+9I14XfTDJZjKQJdBcVw==" + }, + "pac-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-5.0.0.tgz", + "integrity": "sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==", + "optional": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4", + "get-uri": "3", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "5", + "pac-resolver": "^5.0.0", + "raw-body": "^2.2.0", + "socks-proxy-agent": "5" + } + }, + "pac-resolver": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-5.0.1.tgz", + "integrity": "sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==", + "optional": true, + "requires": { + "degenerator": "^3.0.2", + "ip": "^1.1.5", + "netmask": "^2.0.2" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "optional": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-5.0.0.tgz", + "integrity": "sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==", + "optional": true, + "requires": { + "agent-base": "^6.0.0", + "debug": "4", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "lru-cache": "^5.1.1", + "pac-proxy-agent": "^5.0.0", + "proxy-from-env": "^1.0.0", + "socks-proxy-agent": "^5.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "optional": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "optional": true + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "optional": true + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + }, + "redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "requires": { + "redis-errors": "^1.0.0" + } + }, + "reduce": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", + "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", + "requires": { + "object-keys": "^1.1.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "sift": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.0.tgz", + "integrity": "sha512-ILTjdP2Mv9V1kIxWMXeMTIRbOBrqKc4JAXmFMnFq3fKeyQ2Qwa3Dw1ubcye3vR+Y6ofA0b9gNDr/y2t6eUeIzQ==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socks": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.0.tgz", + "integrity": "sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "dependencies": { + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + } + } + }, + "socks-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.1.tgz", + "integrity": "sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==", + "optional": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "4", + "socks": "^2.3.3" + } + }, + "sonyflake": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sonyflake/-/sonyflake-1.1.2.tgz", + "integrity": "sha512-A9CEnf/a7xOvNtVWoDyFxHxVdL/LXlm0YMpFyARGguR5LjJWGY6oVU9L/Y43p7HaGgE3ombWa6TiDGkLB/SYug==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "standard-as-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz", + "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==" + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "stripe": { + "version": "8.222.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.222.0.tgz", + "integrity": "sha512-hrA79fjmN2Eb6K3kxkDzU4ODeVGGjXQsuVaAPSUro6I9MM3X+BvIsVqdphm3BXWfimAGFvUqWtPtHy25mICY1w==", + "requires": { + "@types/node": ">=8.1.0", + "qs": "^6.10.3" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "requires": { + "abbrev": "1" + } + } + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "optional": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "optional": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uglify-js": { + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.2.tgz", + "integrity": "sha512-bbxglRjsGQMchfvXZNusUcYgiB9Hx2K4AHYXQy2DITZ9Rd+JzhX7+hoocE5Winr7z2oHvPsekkBwXtigvxevXg==", + "optional": true + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "optional": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "vm2": { + "version": "3.9.11", + "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.11.tgz", + "integrity": "sha512-PFG8iJRSjvvBdisowQ7iVF580DXb1uCIiGaXgm7tynMR1uTBlv7UJlB1zdv5KJ+Tmq1f0Upnj3fayoEOPpCBKg==", + "optional": true, + "requires": { + "acorn": "^8.7.0", + "acorn-walk": "^8.2.0" + } + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==", + "optional": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/backend/package.json b/backend/package.json index b788d51..892f50e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,46 +1,46 @@ -{ - "name": "backend", - "version": "1.0.0", - "description": "", - "main": "server.js", - "scripts": { - "start": "node server.js", - "dev": "nodemon server.js" - }, - "dependencies": { - "bcrypt": "^5.0.1", - "bcryptjs": "^2.4.3", - "body-parser": "^1.19.1", - "cloudinary": "^1.28.1", - "cloudinary-core": "^2.12.2", - "compression": "^1.7.4", - "connect-redis": "^6.1.3", - "cookie-parser": "^1.4.6", - "cors": "^2.8.5", - "dotenv": "^10.0.0", - "express": "^4.18.1", - "express-async-handler": "^1.2.0", - "express-fileupload": "^1.2.1", - "express-rate-limit": "^6.6.0", - "express-session": "^1.17.3", - "google-auth-library": "^7.11.0", - "helmet": "^6.0.0", - "ioredis": "^5.2.3", - "jsonwebtoken": "^8.5.1", - "mongoose": "^6.1.4", - "mongoose-algolia": "^1.10.1", - "node-cron": "^3.0.1", - "node-fetch": "^2.6.7", - "nodemailer": "^6.7.2", - "nodemailer-express-handlebars": "^5.0.0", - "nodemon": "^2.0.20", - "otp-generator": "^4.0.0", - "sonyflake": "^1.1.2", - "stripe": "^8.219.0", - "uuid": "^8.3.2", - "validator": "^13.7.0" - }, - "keywords": [], - "author": "", - "license": "ISC" -} +{ + "name": "backend", + "version": "1.0.0", + "description": "", + "main": "server.js", + "scripts": { + "start": "node server.js", + "dev": "nodemon server.js" + }, + "dependencies": { + "bcrypt": "^5.0.1", + "bcryptjs": "^2.4.3", + "body-parser": "^1.19.1", + "cloudinary": "^1.28.1", + "cloudinary-core": "^2.12.2", + "compression": "^1.7.4", + "connect-redis": "^6.1.3", + "cookie-parser": "^1.4.6", + "cors": "^2.8.5", + "dotenv": "^10.0.0", + "express": "^4.18.1", + "express-async-handler": "^1.2.0", + "express-fileupload": "^1.2.1", + "express-rate-limit": "^6.6.0", + "express-session": "^1.17.3", + "google-auth-library": "^7.11.0", + "helmet": "^6.0.0", + "ioredis": "^5.2.3", + "jsonwebtoken": "^8.5.1", + "mongoose": "^6.1.4", + "mongoose-algolia": "^1.10.1", + "node-cron": "^3.0.1", + "node-fetch": "^2.6.7", + "nodemailer": "^6.7.2", + "nodemailer-express-handlebars": "^5.0.0", + "nodemon": "^2.0.20", + "otp-generator": "^4.0.0", + "sonyflake": "^1.1.2", + "stripe": "^8.219.0", + "uuid": "^8.3.2", + "validator": "^13.7.0" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/backend/server.js b/backend/server.js index 3130e73..9ea5b30 100644 --- a/backend/server.js +++ b/backend/server.js @@ -1,55 +1,55 @@ -const dotenv = require("dotenv"); -const mongoose = require("mongoose"); -const cluster = require("cluster"); -const os = require("os"); -const app = require("./app.js"); -dotenv.config({ path: __dirname + "../.env" }); -if (process.env.NODE_ENV !== "PRODUCTION") { - require("dotenv").config({ path: "../.env" }); -} -const numCpu = os.cpus().length; - -app.get("/api/", (req, res) => { - const health_check = { - uptime: process.uptime(), - message: "Tài Đẹp trai ", - timestamp: Date.now(), - }; - return res.send(health_check); -}); - -if (cluster.isMaster) { - for (let i = 0; i < numCpu; i++) { - cluster.fork(); - } - cluster.on("online", function (worker) { - console.log("Worker " + worker.process.pid + " is online"); - }); - - cluster.on("exit", function (worker, code, signal) { - console.log( - "Worker " + - worker.process.pid + - " died with code: " + - code + - ", and signal: " + - signal - ); - console.log("Starting a new worker"); - cluster.fork(); - }); -} else { - const PORT = process.env.PORT || 5000; - const server = app.listen(PORT, () => - console.log(`server is listening on port:http://localhost:${PORT}`) - ); - process.on("SIGTERM", () => { - process.exit(0); - }); - process.on("SIGINT", () => { - server.close(() => { - mongoose.connection.close(); - process.exit(0); - }); - }); -} +const dotenv = require("dotenv"); +const mongoose = require("mongoose"); +const cluster = require("cluster"); +const os = require("os"); +const app = require("./app.js"); +dotenv.config({ path: __dirname + "../.env" }); +if (process.env.NODE_ENV !== "PRODUCTION") { + require("dotenv").config({ path: "../.env" }); +} +const numCpu = os.cpus().length; + +app.get("/api/", (req, res) => { + const health_check = { + uptime: process.uptime(), + message: "Tài Đẹp trai ", + timestamp: Date.now(), + }; + return res.send(health_check); +}); + +if (cluster.isMaster) { + for (let i = 0; i < numCpu; i++) { + cluster.fork(); + } + cluster.on("online", function (worker) { + console.log("Worker " + worker.process.pid + " is online"); + }); + + cluster.on("exit", function (worker, code, signal) { + console.log( + "Worker " + + worker.process.pid + + " died with code: " + + code + + ", and signal: " + + signal + ); + console.log("Starting a new worker"); + cluster.fork(); + }); +} else { + const PORT = process.env.PORT || 5000; + const server = app.listen(PORT, () => + console.log(`server is listening on port:http://localhost:${PORT}`) + ); + process.on("SIGTERM", () => { + process.exit(0); + }); + process.on("SIGINT", () => { + server.close(() => { + mongoose.connection.close(); + process.exit(0); + }); + }); +} diff --git a/backend/src/v1/admin_api/controllers/admin.controllers.js b/backend/src/v1/admin_api/controllers/admin.controllers.js index 45bb675..8c5ff2b 100644 --- a/backend/src/v1/admin_api/controllers/admin.controllers.js +++ b/backend/src/v1/admin_api/controllers/admin.controllers.js @@ -1,253 +1,253 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - CreateNewAcceptToken, - HandleUploadProfile, -} = require("../../user_api/services/user.service/user.service"); -const { - handleLoginAdmin, - handleRegisterAdmin, - handleVerifyOtp, - handleForgotAdmin, - handleProfileAdmin, - handleLoginGoogleAdmin, - handleLogoutAdmin, - HandleChangePassword, -} = require("../services/auth_admin/auth_admin_service"); - -const adminCtrl = { - loginAdmin: async (req, res) => { - try { - const { email_phone, password } = req.body; - let session = req.session; - const { status, success, element } = await handleLoginAdmin({ - email_phone, - password, - res, - session, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Registers - registerAdmin: async (req, res) => { - try { - const { email } = req.body; - const { status, success, element } = await handleRegisterAdmin({ - email, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Verification - verifyOtpAdmin: async (req, res) => { - try { - const { email, otp } = req.body; - const { status, success, element } = await handleVerifyOtp({ - email, - otp, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* New Access Token - createNewAccessTokens: async (req, res) => { - try { - const user_id = req.user.id; - const { status, success, element } = await CreateNewAcceptToken({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //*Forget - forgetAdmin: async (req, res) => { - try { - const { email } = req.body; - const { status, success, element } = await handleForgotAdmin({ - email, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Profile - ProfileAdmin: async (req, res) => { - try { - const user_id = req.user.id; - - const session = req.session; - - const { status, success, element } = await handleProfileAdmin({ - user_id, - session, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Login Google - loginAdminGoogle: async (req, res) => { - try { - const { tokenId } = req.body; - const { status, success, element } = await handleLoginGoogleAdmin({ - tokenId, - res, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Logout Admin - logoutAdmin: async (req, res) => { - try { - const user_id = req.user.id; - const token = req.token; - const session = req.session; - const { status, success, element } = await handleLogoutAdmin({ - user_id, - token, - session, - res, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //*Update profile Admin - UpdateProfileAdmin: async (req, res) => { - try { - const { name, image, phone_number, sex, date_of_birth } = req.body; - const user_id = req.user.id; - const { status, success, element } = await HandleUploadProfile({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Change Password User - ChangePasswordAdmin: async (req, res) => { - try { - const { oldPassword, password, confirmPassword } = req.body; - const user_id = req.user.id; - const { status, success, element } = await HandleChangePassword({ - password, - oldPassword, - confirmPassword, - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = adminCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + CreateNewAcceptToken, + HandleUploadProfile, +} = require("../../user_api/services/user.service/user.service"); +const { + handleLoginAdmin, + handleRegisterAdmin, + handleVerifyOtp, + handleForgotAdmin, + handleProfileAdmin, + handleLoginGoogleAdmin, + handleLogoutAdmin, + HandleChangePassword, +} = require("../services/auth_admin/auth_admin_service"); + +const adminCtrl = { + loginAdmin: async (req, res) => { + try { + const { email_phone, password } = req.body; + let session = req.session; + const { status, success, element } = await handleLoginAdmin({ + email_phone, + password, + res, + session, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Registers + registerAdmin: async (req, res) => { + try { + const { email } = req.body; + const { status, success, element } = await handleRegisterAdmin({ + email, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Verification + verifyOtpAdmin: async (req, res) => { + try { + const { email, otp } = req.body; + const { status, success, element } = await handleVerifyOtp({ + email, + otp, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* New Access Token + createNewAccessTokens: async (req, res) => { + try { + const user_id = req.user.id; + const { status, success, element } = await CreateNewAcceptToken({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //*Forget + forgetAdmin: async (req, res) => { + try { + const { email } = req.body; + const { status, success, element } = await handleForgotAdmin({ + email, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Profile + ProfileAdmin: async (req, res) => { + try { + const user_id = req.user.id; + + const session = req.session; + + const { status, success, element } = await handleProfileAdmin({ + user_id, + session, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Login Google + loginAdminGoogle: async (req, res) => { + try { + const { tokenId } = req.body; + const { status, success, element } = await handleLoginGoogleAdmin({ + tokenId, + res, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Logout Admin + logoutAdmin: async (req, res) => { + try { + const user_id = req.user.id; + const token = req.token; + const session = req.session; + const { status, success, element } = await handleLogoutAdmin({ + user_id, + token, + session, + res, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //*Update profile Admin + UpdateProfileAdmin: async (req, res) => { + try { + const { name, image, phone_number, sex, date_of_birth } = req.body; + const user_id = req.user.id; + const { status, success, element } = await HandleUploadProfile({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Change Password User + ChangePasswordAdmin: async (req, res) => { + try { + const { oldPassword, password, confirmPassword } = req.body; + const user_id = req.user.id; + const { status, success, element } = await HandleChangePassword({ + password, + oldPassword, + confirmPassword, + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = adminCtrl; diff --git a/backend/src/v1/admin_api/controllers/category.controller.js b/backend/src/v1/admin_api/controllers/category.controller.js index b0c1fad..c1ab8ea 100644 --- a/backend/src/v1/admin_api/controllers/category.controller.js +++ b/backend/src/v1/admin_api/controllers/category.controller.js @@ -1,96 +1,96 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - HandleGetCategory, - handleCreateCategory, - handleEditCategory, - handleDeleteCategory, -} = require("../services/category_admin/category.service"); - -const categoriesCtrl = { - //* Get All Category - getCategory: async (req, res) => { - try { - const { status, success, element } = await HandleGetCategory(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Create Category - createCategory: async (req, res) => { - try { - const { name, image } = req.body; - const { status, success, element } = await handleCreateCategory({ - name, - image, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Edit Category - editCategory: async (req, res) => { - try { - const { name, image } = req.body; - let category_id = req.params.id; - const { status, success, element } = await handleEditCategory({ - category_id, - name, - image, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* deleteCategory - deleteCategory: async (req, res) => { - try { - let category_id = req.params.id; - const { status, success, element } = await handleDeleteCategory({ - category_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = categoriesCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + HandleGetCategory, + handleCreateCategory, + handleEditCategory, + handleDeleteCategory, +} = require("../services/category_admin/category.service"); + +const categoriesCtrl = { + //* Get All Category + getCategory: async (req, res) => { + try { + const { status, success, element } = await HandleGetCategory(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Create Category + createCategory: async (req, res) => { + try { + const { name, image } = req.body; + const { status, success, element } = await handleCreateCategory({ + name, + image, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Edit Category + editCategory: async (req, res) => { + try { + const { name, image } = req.body; + let category_id = req.params.id; + const { status, success, element } = await handleEditCategory({ + category_id, + name, + image, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* deleteCategory + deleteCategory: async (req, res) => { + try { + let category_id = req.params.id; + const { status, success, element } = await handleDeleteCategory({ + category_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = categoriesCtrl; diff --git a/backend/src/v1/admin_api/controllers/courousel.controllers.js b/backend/src/v1/admin_api/controllers/courousel.controllers.js index e252ff4..34afb94 100644 --- a/backend/src/v1/admin_api/controllers/courousel.controllers.js +++ b/backend/src/v1/admin_api/controllers/courousel.controllers.js @@ -1,92 +1,92 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetallCarousel, - handleCreateCarousel, - handleEditCarousel, - handleDeleteCarousel, -} = require("../services/carousel_admin/carousel.service"); -const carouselCtrl = { - getallCarousel: async (req, res) => { - try { - const { status, success, element } = await handleGetallCarousel(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - createCarousel: async (req, res) => { - try { - const { heading, descriptions, image } = req.body; - const { status, success, element } = await handleCreateCarousel({ - heading, - descriptions, - image, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - editCarousel: async (req, res) => { - try { - const { heading, descriptions, image } = req.body; - const _id = req.params.id; - const { status, success, element } = await handleEditCarousel({ - heading, - descriptions, - image, - _id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - deleteCarousel: async (req, res) => { - try { - const _id = req.params.id; - - const { status, success, element } = await handleDeleteCarousel({ _id }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = carouselCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetallCarousel, + handleCreateCarousel, + handleEditCarousel, + handleDeleteCarousel, +} = require("../services/carousel_admin/carousel.service"); +const carouselCtrl = { + getallCarousel: async (req, res) => { + try { + const { status, success, element } = await handleGetallCarousel(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + createCarousel: async (req, res) => { + try { + const { heading, descriptions, image } = req.body; + const { status, success, element } = await handleCreateCarousel({ + heading, + descriptions, + image, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + editCarousel: async (req, res) => { + try { + const { heading, descriptions, image } = req.body; + const _id = req.params.id; + const { status, success, element } = await handleEditCarousel({ + heading, + descriptions, + image, + _id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + deleteCarousel: async (req, res) => { + try { + const _id = req.params.id; + + const { status, success, element } = await handleDeleteCarousel({ _id }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = carouselCtrl; diff --git a/backend/src/v1/admin_api/controllers/feedback.controllers.js b/backend/src/v1/admin_api/controllers/feedback.controllers.js index c9006a3..018f3d5 100644 --- a/backend/src/v1/admin_api/controllers/feedback.controllers.js +++ b/backend/src/v1/admin_api/controllers/feedback.controllers.js @@ -1,94 +1,94 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetAllFeedback, - handleResponseFeedback, - handleReadFeedback, - handleSearchFeedbackDate, -} = require("../services/feedback_admin/feedback.service"); -const feedbackCtrl = { - //* Get All Feedback - getAllFeedback: async (req, res) => { - try { - const { status, success, element } = await handleGetAllFeedback(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Response feedback user - responseFeedbackUsers: async (req, res) => { - try { - const id = req.params.id; - const { response_content } = req.body; - const { status, success, element } = await handleResponseFeedback({ - id, - response_content, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Read Email - readEmailFeedbackUsers: async (req, res) => { - try { - const id = req.params.id; - const { status, success, element } = await handleReadFeedback({ - id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Filter email - filterFeedbackUsers: async (req, res) => { - try { - let { checked } = req.body; - - const { status, success, element } = await handleSearchFeedbackDate({ - checked, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = feedbackCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetAllFeedback, + handleResponseFeedback, + handleReadFeedback, + handleSearchFeedbackDate, +} = require("../services/feedback_admin/feedback.service"); +const feedbackCtrl = { + //* Get All Feedback + getAllFeedback: async (req, res) => { + try { + const { status, success, element } = await handleGetAllFeedback(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Response feedback user + responseFeedbackUsers: async (req, res) => { + try { + const id = req.params.id; + const { response_content } = req.body; + const { status, success, element } = await handleResponseFeedback({ + id, + response_content, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Read Email + readEmailFeedbackUsers: async (req, res) => { + try { + const id = req.params.id; + const { status, success, element } = await handleReadFeedback({ + id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Filter email + filterFeedbackUsers: async (req, res) => { + try { + let { checked } = req.body; + + const { status, success, element } = await handleSearchFeedbackDate({ + checked, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = feedbackCtrl; diff --git a/backend/src/v1/admin_api/controllers/manager_users_controllers.js b/backend/src/v1/admin_api/controllers/manager_users_controllers.js index a7db147..4a12d5e 100644 --- a/backend/src/v1/admin_api/controllers/manager_users_controllers.js +++ b/backend/src/v1/admin_api/controllers/manager_users_controllers.js @@ -1,153 +1,153 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetAllUsers, - handleGetAllAdmin, - handleUploadAccount, - handleDeleteAccount, - handleListUserNews, - handleListUserDeleteOrders, - handleListUsersMonthlyRegistered, -} = require("../services/manager_users/manager_user.service"); -const manger_userCtrl = { - //* Get All manger_user - getAllUsers: async (req, res) => { - try { - const { status, success, element } = await handleGetAllUsers(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* get All Admin - getAllAdmin: async (req, res) => { - try { - const { status, success, element } = await handleGetAllAdmin(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Upload account users and admin - uploadAccountUserAndAdmin: async (req, res) => { - try { - const { name, image, phone_number, role, sex, date_of_birth } = req.body; - const user_id = req.params.id; - const { status, success, element } = await handleUploadAccount({ - name, - image, - phone_number, - role, - sex, - date_of_birth, - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Delete account users and admin - deleteAccountUserAndAdmin: async (req, res) => { - try { - const user_id = req.params.id; - const { status, success, element } = await handleDeleteAccount({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* List account register new 3 days. - ListAccountUserNew: async (req, res) => { - try { - const { status, success, element } = await handleListUserNews(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* List account Users delete orders - ListAccountUserDeleteOrder: async (req, res) => { - try { - const { status, success, element } = await handleListUserDeleteOrders(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Lis users monthly registered customers - ListMonthlyRegisteredCustomers: async (req, res) => { - try { - const { status, success, element } = - await handleListUsersMonthlyRegistered(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = manger_userCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetAllUsers, + handleGetAllAdmin, + handleUploadAccount, + handleDeleteAccount, + handleListUserNews, + handleListUserDeleteOrders, + handleListUsersMonthlyRegistered, +} = require("../services/manager_users/manager_user.service"); +const manger_userCtrl = { + //* Get All manger_user + getAllUsers: async (req, res) => { + try { + const { status, success, element } = await handleGetAllUsers(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* get All Admin + getAllAdmin: async (req, res) => { + try { + const { status, success, element } = await handleGetAllAdmin(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Upload account users and admin + uploadAccountUserAndAdmin: async (req, res) => { + try { + const { name, image, phone_number, role, sex, date_of_birth } = req.body; + const user_id = req.params.id; + const { status, success, element } = await handleUploadAccount({ + name, + image, + phone_number, + role, + sex, + date_of_birth, + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Delete account users and admin + deleteAccountUserAndAdmin: async (req, res) => { + try { + const user_id = req.params.id; + const { status, success, element } = await handleDeleteAccount({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* List account register new 3 days. + ListAccountUserNew: async (req, res) => { + try { + const { status, success, element } = await handleListUserNews(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* List account Users delete orders + ListAccountUserDeleteOrder: async (req, res) => { + try { + const { status, success, element } = await handleListUserDeleteOrders(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Lis users monthly registered customers + ListMonthlyRegisteredCustomers: async (req, res) => { + try { + const { status, success, element } = + await handleListUsersMonthlyRegistered(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = manger_userCtrl; diff --git a/backend/src/v1/admin_api/controllers/order.controller.js b/backend/src/v1/admin_api/controllers/order.controller.js index 37dc46b..1eb8155 100644 --- a/backend/src/v1/admin_api/controllers/order.controller.js +++ b/backend/src/v1/admin_api/controllers/order.controller.js @@ -1,112 +1,112 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleUpdateOrderDeleteUsers, - handleGetAllOrderUsers, - handleUploadStatus, - handleGetDetail, - handleGetAllOrderDeleteUsers, -} = require("../services/order_admin/order.service"); - -module.exports = { - //* Undo order delete - updateOrderDeleteUser: async (req, res) => { - try { - const payment_id = req.params.id; - const { status, success, element } = await handleUpdateOrderDeleteUsers( - payment_id - ); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Get all orders - GetAllOrderUsers: async (req, res) => { - try { - const { status, success, element } = await handleGetAllOrderUsers(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Get all orders delete - GetAllOrderUsersDelete: async (req, res) => { - try { - const { status, success, element } = await handleGetAllOrderDeleteUsers(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Update status orders - updateStatusOrders: async (req, res) => { - try { - const id = req.params.id; - const { order_status } = req.body; - const { status, success, element } = await handleUploadStatus({ - order_status, - id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Get detail orders - detailOrder: async (req, res) => { - try { - const order_id = req.params.id; - const { status, success, element } = await handleGetDetail({ - order_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleUpdateOrderDeleteUsers, + handleGetAllOrderUsers, + handleUploadStatus, + handleGetDetail, + handleGetAllOrderDeleteUsers, +} = require("../services/order_admin/order.service"); + +module.exports = { + //* Undo order delete + updateOrderDeleteUser: async (req, res) => { + try { + const payment_id = req.params.id; + const { status, success, element } = await handleUpdateOrderDeleteUsers( + payment_id + ); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Get all orders + GetAllOrderUsers: async (req, res) => { + try { + const { status, success, element } = await handleGetAllOrderUsers(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Get all orders delete + GetAllOrderUsersDelete: async (req, res) => { + try { + const { status, success, element } = await handleGetAllOrderDeleteUsers(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Update status orders + updateStatusOrders: async (req, res) => { + try { + const id = req.params.id; + const { order_status } = req.body; + const { status, success, element } = await handleUploadStatus({ + order_status, + id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Get detail orders + detailOrder: async (req, res) => { + try { + const order_id = req.params.id; + const { status, success, element } = await handleGetDetail({ + order_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; diff --git a/backend/src/v1/admin_api/controllers/productadmin.controllers.js b/backend/src/v1/admin_api/controllers/productadmin.controllers.js index 421926c..eb6b4d1 100644 --- a/backend/src/v1/admin_api/controllers/productadmin.controllers.js +++ b/backend/src/v1/admin_api/controllers/productadmin.controllers.js @@ -1,149 +1,149 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetallProduct, - handleProductId, - handleCreateProduct, - handleEditProduct, - handleDeleteProduct, -} = require("../services/product_admin/products.service"); - -const productCtrl = { - //* Get all - getallProduct: async (req, res) => { - try { - const { status, success, element } = await handleGetallProduct({ req }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Get Detail - getProductId: async (req, res) => { - try { - let product_id = req.params.id; - const { status, success, element } = await handleProductId({ - product_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Create Product - createProduct: async (req, res) => { - try { - const { - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - } = req.body; - const { status, success, element } = await handleCreateProduct({ - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Edit Product - editProduct: async (req, res) => { - try { - const { - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - } = req.body; - let product_id = req.params.id; - const { status, success, element } = await handleEditProduct({ - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - product_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Delete Product - deleteProduct: async (req, res) => { - try { - let product_id = req.params.id; - const { status, success, element } = await handleDeleteProduct({ - product_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; - -module.exports = productCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetallProduct, + handleProductId, + handleCreateProduct, + handleEditProduct, + handleDeleteProduct, +} = require("../services/product_admin/products.service"); + +const productCtrl = { + //* Get all + getallProduct: async (req, res) => { + try { + const { status, success, element } = await handleGetallProduct({ req }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Get Detail + getProductId: async (req, res) => { + try { + let product_id = req.params.id; + const { status, success, element } = await handleProductId({ + product_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Create Product + createProduct: async (req, res) => { + try { + const { + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + } = req.body; + const { status, success, element } = await handleCreateProduct({ + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Edit Product + editProduct: async (req, res) => { + try { + const { + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + } = req.body; + let product_id = req.params.id; + const { status, success, element } = await handleEditProduct({ + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + product_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Delete Product + deleteProduct: async (req, res) => { + try { + let product_id = req.params.id; + const { status, success, element } = await handleDeleteProduct({ + product_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; + +module.exports = productCtrl; diff --git a/backend/src/v1/admin_api/controllers/statistical.controllers.js b/backend/src/v1/admin_api/controllers/statistical.controllers.js index 74ca9ca..40a1360 100644 --- a/backend/src/v1/admin_api/controllers/statistical.controllers.js +++ b/backend/src/v1/admin_api/controllers/statistical.controllers.js @@ -1,102 +1,102 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetSumInCome, - handleGetUserBuy3days, - handleMonthlyIncomeCustomerReceived, - handleIncomeCustomerReceivedThisAndLastMonth, - handleIncomeCustomerNotReceivedThisAndLastMonth, -} = require("../services/tatistical_admin/statistical.service"); -module.exports = { - //* Statistical Sum total - StatisticalSumTotal: async (req, res) => { - try { - const { status, success, element } = await handleGetSumInCome(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* List account buy new 3 days. - ListUserBuyNew3days: async (req, res) => { - try { - const { status, success, element } = await handleGetUserBuy3days(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Get monthly the income customer have received (12 month) - getMonthlyIncomeCustomerReceived: async (req, res) => { - try { - const { status, success, element } = - await handleMonthlyIncomeCustomerReceived(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //*Get the income customer received this month and compare to last month - getIncomeCustomerReceivedThisAndLastMonth: async (req, res) => { - try { - const { status, success, element } = - await handleIncomeCustomerReceivedThisAndLastMonth(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - getIncomeCustomerNotReceivedThisAndLastMonth: async (req, res) => { - try { - const { status, success, element } = - await handleIncomeCustomerNotReceivedThisAndLastMonth(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetSumInCome, + handleGetUserBuy3days, + handleMonthlyIncomeCustomerReceived, + handleIncomeCustomerReceivedThisAndLastMonth, + handleIncomeCustomerNotReceivedThisAndLastMonth, +} = require("../services/tatistical_admin/statistical.service"); +module.exports = { + //* Statistical Sum total + StatisticalSumTotal: async (req, res) => { + try { + const { status, success, element } = await handleGetSumInCome(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* List account buy new 3 days. + ListUserBuyNew3days: async (req, res) => { + try { + const { status, success, element } = await handleGetUserBuy3days(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Get monthly the income customer have received (12 month) + getMonthlyIncomeCustomerReceived: async (req, res) => { + try { + const { status, success, element } = + await handleMonthlyIncomeCustomerReceived(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //*Get the income customer received this month and compare to last month + getIncomeCustomerReceivedThisAndLastMonth: async (req, res) => { + try { + const { status, success, element } = + await handleIncomeCustomerReceivedThisAndLastMonth(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + getIncomeCustomerNotReceivedThisAndLastMonth: async (req, res) => { + try { + const { status, success, element } = + await handleIncomeCustomerNotReceivedThisAndLastMonth(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; diff --git a/backend/src/v1/admin_api/controllers/voucher.controllers.js b/backend/src/v1/admin_api/controllers/voucher.controllers.js index 02f31b6..769dec4 100644 --- a/backend/src/v1/admin_api/controllers/voucher.controllers.js +++ b/backend/src/v1/admin_api/controllers/voucher.controllers.js @@ -1,96 +1,96 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetallVoucher, - handleCreateVoucher, - handleUpdateVoucher, - handleDeleteVoucher, -} = require("../services/voucher_admin/voucher.service"); - -const voucherCtrl = { - //* Get All Voucher - getVoucher: async (req, res) => { - try { - const { status, success, element } = await handleGetallVoucher(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Create Voucher - createVoucher: async (req, res) => { - try { - const { title, value } = req.body; - const { status, success, element } = await handleCreateVoucher({ - title, - value, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Edit Voucher - editVoucher: async (req, res) => { - try { - const { title, value } = req.body; - let voucher_id = req.params.id; - const { status, success, element } = await handleUpdateVoucher({ - voucher_id, - title, - value, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* deleteVoucher - deleteVoucher: async (req, res) => { - try { - let voucher_id = req.params.id; - const { status, success, element } = await handleDeleteVoucher({ - voucher_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = voucherCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetallVoucher, + handleCreateVoucher, + handleUpdateVoucher, + handleDeleteVoucher, +} = require("../services/voucher_admin/voucher.service"); + +const voucherCtrl = { + //* Get All Voucher + getVoucher: async (req, res) => { + try { + const { status, success, element } = await handleGetallVoucher(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Create Voucher + createVoucher: async (req, res) => { + try { + const { title, value } = req.body; + const { status, success, element } = await handleCreateVoucher({ + title, + value, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Edit Voucher + editVoucher: async (req, res) => { + try { + const { title, value } = req.body; + let voucher_id = req.params.id; + const { status, success, element } = await handleUpdateVoucher({ + voucher_id, + title, + value, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* deleteVoucher + deleteVoucher: async (req, res) => { + try { + let voucher_id = req.params.id; + const { status, success, element } = await handleDeleteVoucher({ + voucher_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = voucherCtrl; diff --git a/backend/src/v1/admin_api/routes/admin.routes.js b/backend/src/v1/admin_api/routes/admin.routes.js index 29719d8..1bfd68b 100644 --- a/backend/src/v1/admin_api/routes/admin.routes.js +++ b/backend/src/v1/admin_api/routes/admin.routes.js @@ -1,53 +1,53 @@ -const router = require("express").Router(); -const adminCtrl = require("../controllers/admin.controllers"); -const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -const RateLimitMiddleware = require("../../middlewares/ratelimit.middleware") -// * ------------- Login ------------- -//!Login Email and Phone -router.post("/admin/login", adminCtrl.loginAdmin); -//!Login Google -router.post("/admin/login/google", adminCtrl.loginAdminGoogle); -//! Register send otp -router.post("/admin/register", RateLimitMiddleware, adminCtrl.registerAdmin); -//! Logout admin -router.get( - "/admin/logout", - VerifyAcceptToken, - authAdmin, - adminCtrl.logoutAdmin -); - -//! Check Otp -router.post("/admin/verification/otp", adminCtrl.verifyOtpAdmin); -//! new access token -router.post( - "/admin/new/access", - VerifyRefreshToken, - adminCtrl.createNewAccessTokens -); -//! Forget Admin -router.post("/admin/forget", adminCtrl.forgetAdmin); -//! Profile admin -router.get( - "/admin/profile", - VerifyAcceptToken, - authAdmin, - adminCtrl.ProfileAdmin -); -//! upload profile admin -router.post( - "/admin/update/profile", - VerifyAcceptToken, - authAdmin, - adminCtrl.UpdateProfileAdmin -); -//! Change password -router.post( - "/admin/change/password", - VerifyAcceptToken, - authAdmin, - adminCtrl.ChangePasswordAdmin -); -module.exports = router; +const router = require("express").Router(); +const adminCtrl = require("../controllers/admin.controllers"); +const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +const RateLimitMiddleware = require("../../middlewares/ratelimit.middleware") +// * ------------- Login ------------- +//!Login Email and Phone +router.post("/admin/login", adminCtrl.loginAdmin); +//!Login Google +router.post("/admin/login/google", adminCtrl.loginAdminGoogle); +//! Register send otp +router.post("/admin/register", RateLimitMiddleware, adminCtrl.registerAdmin); +//! Logout admin +router.get( + "/admin/logout", + VerifyAcceptToken, + authAdmin, + adminCtrl.logoutAdmin +); + +//! Check Otp +router.post("/admin/verification/otp", adminCtrl.verifyOtpAdmin); +//! new access token +router.post( + "/admin/new/access", + VerifyRefreshToken, + adminCtrl.createNewAccessTokens +); +//! Forget Admin +router.post("/admin/forget", adminCtrl.forgetAdmin); +//! Profile admin +router.get( + "/admin/profile", + VerifyAcceptToken, + authAdmin, + adminCtrl.ProfileAdmin +); +//! upload profile admin +router.post( + "/admin/update/profile", + VerifyAcceptToken, + authAdmin, + adminCtrl.UpdateProfileAdmin +); +//! Change password +router.post( + "/admin/change/password", + VerifyAcceptToken, + authAdmin, + adminCtrl.ChangePasswordAdmin +); +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/carousel.routes.js b/backend/src/v1/admin_api/routes/carousel.routes.js index cd53324..9b1cabb 100644 --- a/backend/src/v1/admin_api/routes/carousel.routes.js +++ b/backend/src/v1/admin_api/routes/carousel.routes.js @@ -1,32 +1,32 @@ -const router = require("express").Router(); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -const carouselCtrl = require("../controllers/courousel.controllers"); - -//* Get All carousel -router.get( - "/admin/carousel", - VerifyAcceptToken, - authAdmin, - carouselCtrl.getallCarousel - //* Create carousel -); -router.post( - "/admin/carousel/create", - VerifyAcceptToken, - authAdmin, - carouselCtrl.createCarousel -); -router.post( - "/admin/carousel/edit/:id", - VerifyAcceptToken, - authAdmin, - carouselCtrl.editCarousel -); -router.delete( - "/admin/carousel/delete/:id", - VerifyAcceptToken, - authAdmin, - carouselCtrl.deleteCarousel -); -module.exports = router; +const router = require("express").Router(); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +const carouselCtrl = require("../controllers/courousel.controllers"); + +//* Get All carousel +router.get( + "/admin/carousel", + VerifyAcceptToken, + authAdmin, + carouselCtrl.getallCarousel + //* Create carousel +); +router.post( + "/admin/carousel/create", + VerifyAcceptToken, + authAdmin, + carouselCtrl.createCarousel +); +router.post( + "/admin/carousel/edit/:id", + VerifyAcceptToken, + authAdmin, + carouselCtrl.editCarousel +); +router.delete( + "/admin/carousel/delete/:id", + VerifyAcceptToken, + authAdmin, + carouselCtrl.deleteCarousel +); +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/categories.routes.js b/backend/src/v1/admin_api/routes/categories.routes.js index ff048e2..0a572c7 100644 --- a/backend/src/v1/admin_api/routes/categories.routes.js +++ b/backend/src/v1/admin_api/routes/categories.routes.js @@ -1,36 +1,36 @@ -const router = require("express").Router(); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -const categoriesCtrl = require("../controllers/category.controller"); - -//* Get All Category -router.get( - "/category", - VerifyAcceptToken, - authAdmin, - categoriesCtrl.getCategory -); - -//* Create Category -router.post( - "/category/create", - VerifyAcceptToken, - authAdmin, - categoriesCtrl.createCategory -); -//* Edit Category - -router.post( - "/category/edit/:id", - VerifyAcceptToken, - authAdmin, - categoriesCtrl.editCategory -); -//* Edit Category -router.delete( - "/category/delete/:id", - VerifyAcceptToken, - authAdmin, - categoriesCtrl.deleteCategory -); -module.exports = router; +const router = require("express").Router(); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +const categoriesCtrl = require("../controllers/category.controller"); + +//* Get All Category +router.get( + "/category", + VerifyAcceptToken, + authAdmin, + categoriesCtrl.getCategory +); + +//* Create Category +router.post( + "/category/create", + VerifyAcceptToken, + authAdmin, + categoriesCtrl.createCategory +); +//* Edit Category + +router.post( + "/category/edit/:id", + VerifyAcceptToken, + authAdmin, + categoriesCtrl.editCategory +); +//* Edit Category +router.delete( + "/category/delete/:id", + VerifyAcceptToken, + authAdmin, + categoriesCtrl.deleteCategory +); +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/feedback.route.js b/backend/src/v1/admin_api/routes/feedback.route.js index 4e1d6b9..7e2196d 100644 --- a/backend/src/v1/admin_api/routes/feedback.route.js +++ b/backend/src/v1/admin_api/routes/feedback.route.js @@ -1,34 +1,34 @@ -const router = require("express").Router(); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -const feedbackCtrl = require("../controllers/feedback.controllers"); -//* Get All feedback -router.get( - "/feedback", - VerifyAcceptToken, - authAdmin, - feedbackCtrl.getAllFeedback -); -//* response feedback -router.post( - "/feedback/response/:id", - VerifyAcceptToken, - authAdmin, - feedbackCtrl.responseFeedbackUsers -); -//* read feedback -router.get( - "/feedback/read/:id", - VerifyAcceptToken, - authAdmin, - feedbackCtrl.readEmailFeedbackUsers -); -//* Filter feedback -router.post( - "/feedback/filter", - VerifyAcceptToken, - authAdmin, - feedbackCtrl.filterFeedbackUsers -); - -module.exports = router; +const router = require("express").Router(); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +const feedbackCtrl = require("../controllers/feedback.controllers"); +//* Get All feedback +router.get( + "/feedback", + VerifyAcceptToken, + authAdmin, + feedbackCtrl.getAllFeedback +); +//* response feedback +router.post( + "/feedback/response/:id", + VerifyAcceptToken, + authAdmin, + feedbackCtrl.responseFeedbackUsers +); +//* read feedback +router.get( + "/feedback/read/:id", + VerifyAcceptToken, + authAdmin, + feedbackCtrl.readEmailFeedbackUsers +); +//* Filter feedback +router.post( + "/feedback/filter", + VerifyAcceptToken, + authAdmin, + feedbackCtrl.filterFeedbackUsers +); + +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/manager_user.routes.js b/backend/src/v1/admin_api/routes/manager_user.routes.js index 6339d7b..e95b2ab 100644 --- a/backend/src/v1/admin_api/routes/manager_user.routes.js +++ b/backend/src/v1/admin_api/routes/manager_user.routes.js @@ -1,56 +1,56 @@ -const router = require("express").Router(); -const manager_userCtrl = require("../controllers/manager_users_controllers"); -const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -//! get all Users -router.get( - "/admin/getall/users", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.getAllUsers -); -//! get all Admin -router.get( - "/admin/getall/admin", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.getAllAdmin -); -//! Upload Account Users and Admin -router.post( - "/admin/upload/account/:id", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.uploadAccountUserAndAdmin -); -//! Delete Account Users and Admin -router.delete( - "/admin/delete/account/:id", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.deleteAccountUserAndAdmin -); - -//! List account register new 3 days. -router.get( - "/admin/getall/user/new", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.ListAccountUserNew -); -//! List account user delete order -router.get( - "/admin/getall/user/delete/order", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.ListAccountUserDeleteOrder -); -//! List Monthly Registered Customer -router.get( - "/admin/getall/user/register/month", - VerifyAcceptTokenAdmin, - authAdmin, - manager_userCtrl.ListMonthlyRegisteredCustomers -); - -module.exports = router; +const router = require("express").Router(); +const manager_userCtrl = require("../controllers/manager_users_controllers"); +const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +//! get all Users +router.get( + "/admin/getall/users", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.getAllUsers +); +//! get all Admin +router.get( + "/admin/getall/admin", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.getAllAdmin +); +//! Upload Account Users and Admin +router.post( + "/admin/upload/account/:id", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.uploadAccountUserAndAdmin +); +//! Delete Account Users and Admin +router.delete( + "/admin/delete/account/:id", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.deleteAccountUserAndAdmin +); + +//! List account register new 3 days. +router.get( + "/admin/getall/user/new", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.ListAccountUserNew +); +//! List account user delete order +router.get( + "/admin/getall/user/delete/order", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.ListAccountUserDeleteOrder +); +//! List Monthly Registered Customer +router.get( + "/admin/getall/user/register/month", + VerifyAcceptTokenAdmin, + authAdmin, + manager_userCtrl.ListMonthlyRegisteredCustomers +); + +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/order.routes.js b/backend/src/v1/admin_api/routes/order.routes.js index 944b91d..a1c7bf5 100644 --- a/backend/src/v1/admin_api/routes/order.routes.js +++ b/backend/src/v1/admin_api/routes/order.routes.js @@ -1,43 +1,43 @@ -const router = require("express").Router(); -const orderCtrl = require("../controllers/order.controller"); -const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -//! Update Order Delete -router.get( - "/admin/order/update/:id", - VerifyAcceptTokenAdmin, - authAdmin, - orderCtrl.updateOrderDeleteUser -); - -//! Get all Orders -router.get( - "/admin/order", - VerifyAcceptTokenAdmin, - authAdmin, - orderCtrl.GetAllOrderUsers -); -//! Get all Orders -router.get( - "/admin/order/delete", - VerifyAcceptTokenAdmin, - authAdmin, - orderCtrl.GetAllOrderUsersDelete -); - -//! upload status -router.post( - "/admin/order/upload/status/:id", - VerifyAcceptTokenAdmin, - authAdmin, - orderCtrl.updateStatusOrders -); -//! detail orders -router.get( - "/admin/order/:id", - VerifyAcceptTokenAdmin, - authAdmin, - orderCtrl.detailOrder -); - -module.exports = router; +const router = require("express").Router(); +const orderCtrl = require("../controllers/order.controller"); +const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +//! Update Order Delete +router.get( + "/admin/order/update/:id", + VerifyAcceptTokenAdmin, + authAdmin, + orderCtrl.updateOrderDeleteUser +); + +//! Get all Orders +router.get( + "/admin/order", + VerifyAcceptTokenAdmin, + authAdmin, + orderCtrl.GetAllOrderUsers +); +//! Get all Orders +router.get( + "/admin/order/delete", + VerifyAcceptTokenAdmin, + authAdmin, + orderCtrl.GetAllOrderUsersDelete +); + +//! upload status +router.post( + "/admin/order/upload/status/:id", + VerifyAcceptTokenAdmin, + authAdmin, + orderCtrl.updateStatusOrders +); +//! detail orders +router.get( + "/admin/order/:id", + VerifyAcceptTokenAdmin, + authAdmin, + orderCtrl.detailOrder +); + +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/product_admin.route.js b/backend/src/v1/admin_api/routes/product_admin.route.js index 42152f3..6768447 100644 --- a/backend/src/v1/admin_api/routes/product_admin.route.js +++ b/backend/src/v1/admin_api/routes/product_admin.route.js @@ -1,41 +1,41 @@ -const router = require("express").Router(); -const productCtrl = require("../controllers/productadmin.controllers"); -const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -//! get all product sort,limit,filter -router.get( - "/admin/product", - VerifyAcceptTokenAdmin, - authAdmin, - productCtrl.getallProduct -); -//! get Product Id -router.get( - "/admin/product/:id", - VerifyAcceptTokenAdmin, - authAdmin, - productCtrl.getProductId -); -//! Create Product -router.post( - "/admin/product/create", - VerifyAcceptTokenAdmin, - authAdmin, - productCtrl.createProduct -); -//! Edit Product -router.post( - "/admin/product/edit/:id", - VerifyAcceptTokenAdmin, - authAdmin, - productCtrl.editProduct -); -//! Delete Product -router.delete( - "/admin/product/delete/:id", - VerifyAcceptTokenAdmin, - authAdmin, - productCtrl.deleteProduct -); - -module.exports = router; +const router = require("express").Router(); +const productCtrl = require("../controllers/productadmin.controllers"); +const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +//! get all product sort,limit,filter +router.get( + "/admin/product", + VerifyAcceptTokenAdmin, + authAdmin, + productCtrl.getallProduct +); +//! get Product Id +router.get( + "/admin/product/:id", + VerifyAcceptTokenAdmin, + authAdmin, + productCtrl.getProductId +); +//! Create Product +router.post( + "/admin/product/create", + VerifyAcceptTokenAdmin, + authAdmin, + productCtrl.createProduct +); +//! Edit Product +router.post( + "/admin/product/edit/:id", + VerifyAcceptTokenAdmin, + authAdmin, + productCtrl.editProduct +); +//! Delete Product +router.delete( + "/admin/product/delete/:id", + VerifyAcceptTokenAdmin, + authAdmin, + productCtrl.deleteProduct +); + +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/statistical.routes.js b/backend/src/v1/admin_api/routes/statistical.routes.js index e3d783b..a7ac758 100644 --- a/backend/src/v1/admin_api/routes/statistical.routes.js +++ b/backend/src/v1/admin_api/routes/statistical.routes.js @@ -1,41 +1,41 @@ -const router = require("express").Router(); -const statisticalCtrl = require("../controllers/statistical.controllers"); -const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -//! Statistical Sum total -router.get( - "/admin/statistical/sum", - VerifyAcceptTokenAdmin, - authAdmin, - statisticalCtrl.StatisticalSumTotal -); -//! Statistical Sum total 3 day -router.get( - "/admin/statistical/buy/new", - VerifyAcceptTokenAdmin, - authAdmin, - statisticalCtrl.ListUserBuyNew3days -); -//!Get monthly the income customer have received (12 month) -router.get( - "/admin/statistical/month/received", - VerifyAcceptTokenAdmin, - authAdmin, - statisticalCtrl.getMonthlyIncomeCustomerReceived -); -//! Get the income customer received this month and compare to last month -router.get( - "/admin/statistical/compare/month/received", - VerifyAcceptTokenAdmin, - authAdmin, - statisticalCtrl.getIncomeCustomerReceivedThisAndLastMonth -); -//!Get the income customer not received this month and compare to last month - -router.get( - "/admin/statistical/compare/month/not/received", - VerifyAcceptTokenAdmin, - authAdmin, - statisticalCtrl.getIncomeCustomerNotReceivedThisAndLastMonth -); -module.exports = router; +const router = require("express").Router(); +const statisticalCtrl = require("../controllers/statistical.controllers"); +const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +//! Statistical Sum total +router.get( + "/admin/statistical/sum", + VerifyAcceptTokenAdmin, + authAdmin, + statisticalCtrl.StatisticalSumTotal +); +//! Statistical Sum total 3 day +router.get( + "/admin/statistical/buy/new", + VerifyAcceptTokenAdmin, + authAdmin, + statisticalCtrl.ListUserBuyNew3days +); +//!Get monthly the income customer have received (12 month) +router.get( + "/admin/statistical/month/received", + VerifyAcceptTokenAdmin, + authAdmin, + statisticalCtrl.getMonthlyIncomeCustomerReceived +); +//! Get the income customer received this month and compare to last month +router.get( + "/admin/statistical/compare/month/received", + VerifyAcceptTokenAdmin, + authAdmin, + statisticalCtrl.getIncomeCustomerReceivedThisAndLastMonth +); +//!Get the income customer not received this month and compare to last month + +router.get( + "/admin/statistical/compare/month/not/received", + VerifyAcceptTokenAdmin, + authAdmin, + statisticalCtrl.getIncomeCustomerNotReceivedThisAndLastMonth +); +module.exports = router; diff --git a/backend/src/v1/admin_api/routes/voucher.routes.js b/backend/src/v1/admin_api/routes/voucher.routes.js index dfec3ea..db3f93a 100644 --- a/backend/src/v1/admin_api/routes/voucher.routes.js +++ b/backend/src/v1/admin_api/routes/voucher.routes.js @@ -1,34 +1,34 @@ -const router = require("express").Router(); -const voucherCtrl = require("../controllers/voucher.controllers"); -const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -//! get all voucher -router.get( - "/admin/voucher", - VerifyAcceptTokenAdmin, - authAdmin, - voucherCtrl.getVoucher -); -//! create voucher -router.post( - "/admin/voucher/create", - VerifyAcceptTokenAdmin, - authAdmin, - voucherCtrl.createVoucher -); -//! edit voucher -router.post( - "/admin/voucher/update/:id", - VerifyAcceptTokenAdmin, - authAdmin, - voucherCtrl.editVoucher -); -//! delete voucher -router.delete( - "/admin/voucher/delete/:id", - VerifyAcceptTokenAdmin, - authAdmin, - voucherCtrl.deleteVoucher -); - -module.exports = router; +const router = require("express").Router(); +const voucherCtrl = require("../controllers/voucher.controllers"); +const VerifyAcceptTokenAdmin = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +//! get all voucher +router.get( + "/admin/voucher", + VerifyAcceptTokenAdmin, + authAdmin, + voucherCtrl.getVoucher +); +//! create voucher +router.post( + "/admin/voucher/create", + VerifyAcceptTokenAdmin, + authAdmin, + voucherCtrl.createVoucher +); +//! edit voucher +router.post( + "/admin/voucher/update/:id", + VerifyAcceptTokenAdmin, + authAdmin, + voucherCtrl.editVoucher +); +//! delete voucher +router.delete( + "/admin/voucher/delete/:id", + VerifyAcceptTokenAdmin, + authAdmin, + voucherCtrl.deleteVoucher +); + +module.exports = router; diff --git a/backend/src/v1/admin_api/services/auth_admin/Crud.admin.service.js b/backend/src/v1/admin_api/services/auth_admin/Crud.admin.service.js index 8fe9606..9b597fe 100644 --- a/backend/src/v1/admin_api/services/auth_admin/Crud.admin.service.js +++ b/backend/src/v1/admin_api/services/auth_admin/Crud.admin.service.js @@ -1,125 +1,125 @@ -const Users = require("../../../models/userModel"); -const UserVerifications = require("../../../models/userVerificationModel"); -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -const PASSWORD = require("../../../utils/password"); -const { RedisPub } = require("../../../utils/limited_redis"); -// ** Delete Verification -const deleteVerification = async (userId) => { - await UserVerifications.deleteOne({ userId }); -}; -//** Create User */ -const createAdmin = async ( - name, - email, - password, - sex, - date_of_birth, - phone_number -) => { - const newUser = new Users({ - name, - email, - password, - role: 1, - sex, - date_of_birth, - phone_number, - }); - return await newUser.save(); -}; -//** Create User Social*/ -const createAdminSocial = async ({ name, email, picture, password }) => { - const password_random = await PASSWORD.encodePassword(password); - const newUser = new Users({ - name, - email, - password: password_random, - role: 1, - image: picture, - verified: CONSTANTS.DELETED_ENABLE, - }); - await RedisPub( - "admin_register_password_google_facebook", - JSON.stringify({ - password, - name, - email, - }) - ); - return await newUser.save(); -}; -//* Update Profile */ -const UpdateProfile = async ({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, -}) => { - await Users.findOneAndUpdate( - { _id: user_id }, - { - name, - image, - phone_number, - sex, - date_of_birth, - } - ); - let userId = user_id; - await getProfileId(userId); - return true; -}; -//** Delete User And Verification */ -const deleteVerificationAndUser = async (userId) => { - await UserVerifications.deleteOne({ userId }); - await Users.deleteOne({ _id: userId }); - return true; -}; -//** Update Verification CheckEmail */ -const UpdateVerificationUser = async (userId) => { - await Users.findOneAndUpdate( - { _id: userId }, - { - verified: CONSTANTS.DELETED_ENABLE, - checkLogin: CONSTANTS.DELETED_ENABLE, - } - ); - await deleteVerification(userId); - return true; -}; -//** Create_acceptToken */ -const NewAcceptToken = (user) => { - return HELPER.createAccessToken(user); -}; -//** Update Password */ -const UpdatePassword = async (user_id, password) => { - return Users.findByIdAndUpdate( - { _id: user_id }, - { password: password }, - { new: true } - ); -}; -const getDetailUser = async (user_id) => { - return await Users.findById(user_id); -}; -module.exports = { - //* Create Admin - createAdmin, - //* Create Admin Social - createAdminSocial, - //** Delete User And Verification */ - deleteVerificationAndUser, - // ** Update User Check Verification - UpdateVerificationUser, - //** New access TokenId */ - NewAcceptToken, - //* Update Password - UpdatePassword, - //* Update Profile - UpdateProfile, - //* Detail - getDetailUser, -}; +const Users = require("../../../models/userModel"); +const UserVerifications = require("../../../models/userVerificationModel"); +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +const PASSWORD = require("../../../utils/password"); +const { RedisPub } = require("../../../utils/limited_redis"); +// ** Delete Verification +const deleteVerification = async (userId) => { + await UserVerifications.deleteOne({ userId }); +}; +//** Create User */ +const createAdmin = async ( + name, + email, + password, + sex, + date_of_birth, + phone_number +) => { + const newUser = new Users({ + name, + email, + password, + role: 1, + sex, + date_of_birth, + phone_number, + }); + return await newUser.save(); +}; +//** Create User Social*/ +const createAdminSocial = async ({ name, email, picture, password }) => { + const password_random = await PASSWORD.encodePassword(password); + const newUser = new Users({ + name, + email, + password: password_random, + role: 1, + image: picture, + verified: CONSTANTS.DELETED_ENABLE, + }); + await RedisPub( + "admin_register_password_google_facebook", + JSON.stringify({ + password, + name, + email, + }) + ); + return await newUser.save(); +}; +//* Update Profile */ +const UpdateProfile = async ({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, +}) => { + await Users.findOneAndUpdate( + { _id: user_id }, + { + name, + image, + phone_number, + sex, + date_of_birth, + } + ); + let userId = user_id; + await getProfileId(userId); + return true; +}; +//** Delete User And Verification */ +const deleteVerificationAndUser = async (userId) => { + await UserVerifications.deleteOne({ userId }); + await Users.deleteOne({ _id: userId }); + return true; +}; +//** Update Verification CheckEmail */ +const UpdateVerificationUser = async (userId) => { + await Users.findOneAndUpdate( + { _id: userId }, + { + verified: CONSTANTS.DELETED_ENABLE, + checkLogin: CONSTANTS.DELETED_ENABLE, + } + ); + await deleteVerification(userId); + return true; +}; +//** Create_acceptToken */ +const NewAcceptToken = (user) => { + return HELPER.createAccessToken(user); +}; +//** Update Password */ +const UpdatePassword = async (user_id, password) => { + return Users.findByIdAndUpdate( + { _id: user_id }, + { password: password }, + { new: true } + ); +}; +const getDetailUser = async (user_id) => { + return await Users.findById(user_id); +}; +module.exports = { + //* Create Admin + createAdmin, + //* Create Admin Social + createAdminSocial, + //** Delete User And Verification */ + deleteVerificationAndUser, + // ** Update User Check Verification + UpdateVerificationUser, + //** New access TokenId */ + NewAcceptToken, + //* Update Password + UpdatePassword, + //* Update Profile + UpdateProfile, + //* Detail + getDetailUser, +}; diff --git a/backend/src/v1/admin_api/services/auth_admin/auth.type.admin.js b/backend/src/v1/admin_api/services/auth_admin/auth.type.admin.js index f13efc4..f127b0a 100644 --- a/backend/src/v1/admin_api/services/auth_admin/auth.type.admin.js +++ b/backend/src/v1/admin_api/services/auth_admin/auth.type.admin.js @@ -1,209 +1,209 @@ -"use strict"; -const STORAGE = require("../../../utils/storage"); -const PASSWORD = require("../../../utils/password"); -const Users = require("../../../models/userModel"); -const CONFIGS = require("../../../configs/config"); -const HELPER = require("../../../utils/helper.js"); -const { getDetailUser } = require("./Crud.admin.service"); - -module.exports = { - LoginEmailAdmin: async (email_phone, password) => { - try { - const admin_email = await STORAGE.checkAdminExit(email_phone); - if (!admin_email) - return { - status: 305, - success: false, - }; - if (admin_email.verified === false) { - return { - status: 400, - success: false, - element: { - msg: "Email hasn't been verified. Please check email inbox", - }, - }; - } - const admin_password = await PASSWORD.comparePassword( - password, - admin_email?.password - ); - if (!admin_password) { - return { - status: 403, - success: false, - }; - } - return admin_email; - } catch (error) { - return { - status: 503, - }; - } - }, - LoginPhoneAdmin: async (email_phone) => { - try { - const check_phone = HELPER.isVietnamesePhoneNumber(email_phone); - if (!check_phone) { - return { - status: 306, - success: false, - }; - } - const user_phone = await STORAGE.checkPhoneExit(email_phone); - return user_phone; - } catch (error) { - return { - status: 503, - }; - } - }, - CheckEmailAdmin: async (email) => { - const user_email = await STORAGE.checkUserExit(email); - return user_email; - }, - //* Register Login - RegisterSocialAdmin: async ({ name, email, picture, password }) => { - const password_random = await PASSWORD.encodePassword(password); - let newUser = new Users({ - name: name, - email, - password: password_random, - image: { - public_id: STORAGE.createID(), - url: picture, - }, - verified: true, - }); - await newUser.save(); - await sendEmail({ - from: CONFIGS.SMTP_MAIL, - to: email, - subject: `Password For You`, - template: "password-register", - context: { - password, - name, - email, - }, - }); - return newUser; - }, - //* Check Forget - - CheckForgetAdmin: async ({ email }) => { - const account_admin = await STORAGE.checkAdminExit(email); - const checkEmail = await HELPER.validateEmail(email); - if (!email) { - return { - status: 308, - success: false, - element: { - msg: "Please enter Email", - }, - }; - } else if (!checkEmail) { - return { - status: 305, - success: false, - element: { - msg: "Email Fail", - }, - }; - } - - if (!account_admin) { - return { - status: 305, - success: false, - element: { - msg: "Account not exit ", - }, - }; - } - return { success: true, element: account_admin }; - }, - //* Check Change Password - - CheckChangePassword: async ({ - password, - oldPassword, - confirmPassword, - user_id, - }) => { - console.log("oke"); - const user = await getDetailUser(user_id); - if (!password) - return { - status: 400, - success: false, - element: { - msg: "Password are not empty.", - }, - }; - - if (!confirmPassword) - return { - status: 400, - success: false, - element: { - msg: " Confirm are not empty.", - }, - }; - - if (!oldPassword) - return { - status: 400, - success: false, - element: { - msg: "Old Password are not empty.", - }, - }; - - if (password.length < 6) - return { - status: 400, - success: false, - element: { - msg: "Password is at least 6 characters long.", - }, - }; - - const reg = HELPER.isPassword(password); - if (!reg) { - return { - status: 400, - success: false, - element: { - msg: "Includes 6 characters, uppercase, lowercase and some and special characters.", - }, - }; - } - if (confirmPassword !== password) { - return { - status: 400, - success: false, - element: { - msg: "Password and confirm password does not match!", - }, - }; - } - - const isMatch = await PASSWORD.comparePassword(oldPassword, user.password); - if (!isMatch) { - return { - status: 400, - success: false, - element: { - msg: " Old Password Incorrect", - }, - }; - } - console.log(user); - return { - status: 200, - success: true, - element: user, - }; - }, -}; +"use strict"; +const STORAGE = require("../../../utils/storage"); +const PASSWORD = require("../../../utils/password"); +const Users = require("../../../models/userModel"); +const CONFIGS = require("../../../configs/config"); +const HELPER = require("../../../utils/helper.js"); +const { getDetailUser } = require("./Crud.admin.service"); + +module.exports = { + LoginEmailAdmin: async (email_phone, password) => { + try { + const admin_email = await STORAGE.checkAdminExit(email_phone); + if (!admin_email) + return { + status: 305, + success: false, + }; + if (admin_email.verified === false) { + return { + status: 400, + success: false, + element: { + msg: "Email hasn't been verified. Please check email inbox", + }, + }; + } + const admin_password = await PASSWORD.comparePassword( + password, + admin_email?.password + ); + if (!admin_password) { + return { + status: 403, + success: false, + }; + } + return admin_email; + } catch (error) { + return { + status: 503, + }; + } + }, + LoginPhoneAdmin: async (email_phone) => { + try { + const check_phone = HELPER.isVietnamesePhoneNumber(email_phone); + if (!check_phone) { + return { + status: 306, + success: false, + }; + } + const user_phone = await STORAGE.checkPhoneExit(email_phone); + return user_phone; + } catch (error) { + return { + status: 503, + }; + } + }, + CheckEmailAdmin: async (email) => { + const user_email = await STORAGE.checkUserExit(email); + return user_email; + }, + //* Register Login + RegisterSocialAdmin: async ({ name, email, picture, password }) => { + const password_random = await PASSWORD.encodePassword(password); + let newUser = new Users({ + name: name, + email, + password: password_random, + image: { + public_id: STORAGE.createID(), + url: picture, + }, + verified: true, + }); + await newUser.save(); + await sendEmail({ + from: CONFIGS.SMTP_MAIL, + to: email, + subject: `Password For You`, + template: "password-register", + context: { + password, + name, + email, + }, + }); + return newUser; + }, + //* Check Forget + + CheckForgetAdmin: async ({ email }) => { + const account_admin = await STORAGE.checkAdminExit(email); + const checkEmail = await HELPER.validateEmail(email); + if (!email) { + return { + status: 308, + success: false, + element: { + msg: "Please enter Email", + }, + }; + } else if (!checkEmail) { + return { + status: 305, + success: false, + element: { + msg: "Email Fail", + }, + }; + } + + if (!account_admin) { + return { + status: 305, + success: false, + element: { + msg: "Account not exit ", + }, + }; + } + return { success: true, element: account_admin }; + }, + //* Check Change Password + + CheckChangePassword: async ({ + password, + oldPassword, + confirmPassword, + user_id, + }) => { + console.log("oke"); + const user = await getDetailUser(user_id); + if (!password) + return { + status: 400, + success: false, + element: { + msg: "Password are not empty.", + }, + }; + + if (!confirmPassword) + return { + status: 400, + success: false, + element: { + msg: " Confirm are not empty.", + }, + }; + + if (!oldPassword) + return { + status: 400, + success: false, + element: { + msg: "Old Password are not empty.", + }, + }; + + if (password.length < 6) + return { + status: 400, + success: false, + element: { + msg: "Password is at least 6 characters long.", + }, + }; + + const reg = HELPER.isPassword(password); + if (!reg) { + return { + status: 400, + success: false, + element: { + msg: "Includes 6 characters, uppercase, lowercase and some and special characters.", + }, + }; + } + if (confirmPassword !== password) { + return { + status: 400, + success: false, + element: { + msg: "Password and confirm password does not match!", + }, + }; + } + + const isMatch = await PASSWORD.comparePassword(oldPassword, user.password); + if (!isMatch) { + return { + status: 400, + success: false, + element: { + msg: " Old Password Incorrect", + }, + }; + } + console.log(user); + return { + status: 200, + success: true, + element: user, + }; + }, +}; diff --git a/backend/src/v1/admin_api/services/auth_admin/auth_admin_service.js b/backend/src/v1/admin_api/services/auth_admin/auth_admin_service.js index aa84d55..4e98a07 100644 --- a/backend/src/v1/admin_api/services/auth_admin/auth_admin_service.js +++ b/backend/src/v1/admin_api/services/auth_admin/auth_admin_service.js @@ -1,284 +1,284 @@ -const OtpGenerator = require("otp-generator"); -const { - LoginPhoneAdmin, - LoginEmailAdmin, - CheckForgetAdmin, - CheckChangePassword, -} = require("./auth.type.admin"); -const { insertOtp, validOtp } = require("./otp.service"); -const { _Otp } = require("../../../models/Otp.model"); -const { UpdatePassword, createAdminSocial } = require("./Crud.admin.service"); -const { - getProfileId, -} = require("../../../user_api/services/user.service/getalluser.service"); -const { get, RedisPub, del } = require("../../../utils/limited_redis"); -const STORAGE = require("../../../utils/storage"); -const HELPER = require("../../../utils/helper"); -const PASSWORD = require("../../../utils/password"); -const Users = require("../../../models/userModel"); -const CONSTANTS = require("../../../configs/constants"); - -module.exports = { - handleLoginAdmin: async ({ email_phone, password, res, session }) => { - let result_admin = null; - if (email_phone.includes("@") == true) { - result_admin = await LoginEmailAdmin(email_phone, password); - } else { - result_admin = await LoginPhoneAdmin(email_phone); - } - if (!result_admin || result_admin.success === false) { - return { - status: result_admin?.status, - success: result_admin?.success, - element: result_admin.element, - }; - } - session.users = { - id: result_admin._id, - email: email_phone, - }; - session.save(); - const accessToken = HELPER.createAccessToken({ id: result_admin._id }); - const refreshToken = await STORAGE.GenerateRefreshToken({ - id: result_admin._id, - }); - STORAGE.saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - }, - handleRegisterAdmin: async ({ email }) => { - const checkEmailExit = await STORAGE.checkUserExit(email); - if (checkEmailExit) { - return { - status: 307, - success: false, - }; - } - const OTP = OtpGenerator.generate(6, { - digits: true, - lowerCaseAlphabets: false, - upperCaseAlphabets: false, - specialChars: false, - }); - await RedisPub( - "admin_register_send_otp", - JSON.stringify({ - OTP, - email, - }) - ); - - return { - status: 200, - success: true, - element: await insertOtp({ - otp: OTP, - email, - }), - }; - }, - handleVerifyOtp: async ({ email, otp }) => { - const otpHolder = await _Otp.find({ - email, - }); - if (!otpHolder.length) { - return { - status: 404, - success: false, - element: { - msg: "Expired OTP !!!", - }, - }; - } - - const lastOtp = otpHolder[otpHolder.length - 1]; - const isValid = await validOtp({ - otp, - hashOtp: lastOtp.otp, - }); - if (!isValid) { - return { - status: 401, - success: false, - element: { - msg: "Invalid OTP!!!", - }, - }; - } - - if (isValid && email === lastOtp.email) { - let password = HELPER.randomString(10); - const password_random = await PASSWORD.encodePassword(password); - const user = await Users.create({ - name: "", - password: password_random, - email, - role: 1, - verified: CONSTANTS.DELETED_ENABLE, - checkLogin: CONSTANTS.DELETED_ENABLE, - }); - await RedisPub( - "admin_register_otp_new_password", - JSON.stringify({ - password, - email, - }) - ); - if (user) { - await _Otp.deleteMany({ - email, - }); - } - } - return { - status: 200, - success: true, - element: { - msg: `Password Create send to your ${email}`, - }, - }; - }, - handleForgotAdmin: async ({ email }) => { - const { status, success, element } = await CheckForgetAdmin({ email }); - if (!success) { - return { status, success, element }; - } - let password = HELPER.randomString(10); - const password_random = await PASSWORD.encodePassword(password); - await UpdatePassword(element._id, password_random); - await RedisPub( - "admin_forget_password", - JSON.stringify({ - password, - email, - }) - ); - return { - status: 200, - success: true, - element: { - msg: `Password reset send to your ${email}`, - }, - }; - }, - handleProfileAdmin: async ({ user_id, session }) => { - let profile_user_id = await get(`userId:${user_id}`); - if (profile_user_id) { - return { - status: 200, - success: true, - element: JSON.parse(profile_user_id), - }; - } - if (session?.users?.id) { - const user = await getProfileId(session?.users?.id); - return { - status: 200, - success: true, - element: user, - }; - } - - const user = await getProfileId(user_id); - return { - status: 200, - success: true, - element: user, - }; - }, - handleLoginGoogleAdmin: async ({ tokenId, res }) => { - const user_google = await STORAGE.callDataGoogle(tokenId); - const { name, email, picture } = user_google.payload; - let result_user = await STORAGE.checkAdminExit(email); - if (result_user) { - const accessToken = HELPER.createAccessToken({ id: result_user._id }); - const refreshToken = await STORAGE.GenerateRefreshToken({ - id: result_user._id, - }); - STORAGE.saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - } else { - var password = HELPER.randomString(10); - let newUser = await createAdminSocial({ - name, - email, - picture, - password, - }); - if (!newUser) { - return { - status: 503, - success: false, - }; - } - const accessToken = HELPER.createAccessToken({ id: newUser._id }); - const refreshToken = HELPER.createRefreshToken({ id: newUser._id }); - STORAGE.saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - } - }, - handleLogoutAdmin: async ({ user_id, token, session, res }) => { - await del(`cartUserId:${user_id}`); - res.clearCookie("refreshtoken", { - path: "/api/auth/refresh_token", - }); - session.destroy(); - return { - status: 200, - success: true, - element: { msg: "Logged out success" }, - }; - }, - HandleChangePassword: async ({ - password, - oldPassword, - confirmPassword, - user_id, - }) => { - const { status, success, element } = await CheckChangePassword({ - password, - oldPassword, - confirmPassword, - user_id, - }); - - if (!success) { - return { - status, - success, - element, - }; - } - let user = element; - const salt = await PASSWORD.genSalt(); - const passwordHash = await PASSWORD.encodeResetPassword(password, salt); - await UpdatePassword(user.id, passwordHash); - return { - status: 200, - success: true, - element: { - msg: "Change Password Successfully 😂!", - }, - }; - }, -}; +const OtpGenerator = require("otp-generator"); +const { + LoginPhoneAdmin, + LoginEmailAdmin, + CheckForgetAdmin, + CheckChangePassword, +} = require("./auth.type.admin"); +const { insertOtp, validOtp } = require("./otp.service"); +const { _Otp } = require("../../../models/Otp.model"); +const { UpdatePassword, createAdminSocial } = require("./Crud.admin.service"); +const { + getProfileId, +} = require("../../../user_api/services/user.service/getalluser.service"); +const { get, RedisPub, del } = require("../../../utils/limited_redis"); +const STORAGE = require("../../../utils/storage"); +const HELPER = require("../../../utils/helper"); +const PASSWORD = require("../../../utils/password"); +const Users = require("../../../models/userModel"); +const CONSTANTS = require("../../../configs/constants"); + +module.exports = { + handleLoginAdmin: async ({ email_phone, password, res, session }) => { + let result_admin = null; + if (email_phone.includes("@") == true) { + result_admin = await LoginEmailAdmin(email_phone, password); + } else { + result_admin = await LoginPhoneAdmin(email_phone); + } + if (!result_admin || result_admin.success === false) { + return { + status: result_admin?.status, + success: result_admin?.success, + element: result_admin.element, + }; + } + session.users = { + id: result_admin._id, + email: email_phone, + }; + session.save(); + const accessToken = HELPER.createAccessToken({ id: result_admin._id }); + const refreshToken = await STORAGE.GenerateRefreshToken({ + id: result_admin._id, + }); + STORAGE.saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + }, + handleRegisterAdmin: async ({ email }) => { + const checkEmailExit = await STORAGE.checkUserExit(email); + if (checkEmailExit) { + return { + status: 307, + success: false, + }; + } + const OTP = OtpGenerator.generate(6, { + digits: true, + lowerCaseAlphabets: false, + upperCaseAlphabets: false, + specialChars: false, + }); + await RedisPub( + "admin_register_send_otp", + JSON.stringify({ + OTP, + email, + }) + ); + + return { + status: 200, + success: true, + element: await insertOtp({ + otp: OTP, + email, + }), + }; + }, + handleVerifyOtp: async ({ email, otp }) => { + const otpHolder = await _Otp.find({ + email, + }); + if (!otpHolder.length) { + return { + status: 404, + success: false, + element: { + msg: "Expired OTP !!!", + }, + }; + } + + const lastOtp = otpHolder[otpHolder.length - 1]; + const isValid = await validOtp({ + otp, + hashOtp: lastOtp.otp, + }); + if (!isValid) { + return { + status: 401, + success: false, + element: { + msg: "Invalid OTP!!!", + }, + }; + } + + if (isValid && email === lastOtp.email) { + let password = HELPER.randomString(10); + const password_random = await PASSWORD.encodePassword(password); + const user = await Users.create({ + name: "", + password: password_random, + email, + role: 1, + verified: CONSTANTS.DELETED_ENABLE, + checkLogin: CONSTANTS.DELETED_ENABLE, + }); + await RedisPub( + "admin_register_otp_new_password", + JSON.stringify({ + password, + email, + }) + ); + if (user) { + await _Otp.deleteMany({ + email, + }); + } + } + return { + status: 200, + success: true, + element: { + msg: `Password Create send to your ${email}`, + }, + }; + }, + handleForgotAdmin: async ({ email }) => { + const { status, success, element } = await CheckForgetAdmin({ email }); + if (!success) { + return { status, success, element }; + } + let password = HELPER.randomString(10); + const password_random = await PASSWORD.encodePassword(password); + await UpdatePassword(element._id, password_random); + await RedisPub( + "admin_forget_password", + JSON.stringify({ + password, + email, + }) + ); + return { + status: 200, + success: true, + element: { + msg: `Password reset send to your ${email}`, + }, + }; + }, + handleProfileAdmin: async ({ user_id, session }) => { + let profile_user_id = await get(`userId:${user_id}`); + if (profile_user_id) { + return { + status: 200, + success: true, + element: JSON.parse(profile_user_id), + }; + } + if (session?.users?.id) { + const user = await getProfileId(session?.users?.id); + return { + status: 200, + success: true, + element: user, + }; + } + + const user = await getProfileId(user_id); + return { + status: 200, + success: true, + element: user, + }; + }, + handleLoginGoogleAdmin: async ({ tokenId, res }) => { + const user_google = await STORAGE.callDataGoogle(tokenId); + const { name, email, picture } = user_google.payload; + let result_user = await STORAGE.checkAdminExit(email); + if (result_user) { + const accessToken = HELPER.createAccessToken({ id: result_user._id }); + const refreshToken = await STORAGE.GenerateRefreshToken({ + id: result_user._id, + }); + STORAGE.saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + } else { + var password = HELPER.randomString(10); + let newUser = await createAdminSocial({ + name, + email, + picture, + password, + }); + if (!newUser) { + return { + status: 503, + success: false, + }; + } + const accessToken = HELPER.createAccessToken({ id: newUser._id }); + const refreshToken = HELPER.createRefreshToken({ id: newUser._id }); + STORAGE.saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + } + }, + handleLogoutAdmin: async ({ user_id, token, session, res }) => { + await del(`cartUserId:${user_id}`); + res.clearCookie("refreshtoken", { + path: "/api/auth/refresh_token", + }); + session.destroy(); + return { + status: 200, + success: true, + element: { msg: "Logged out success" }, + }; + }, + HandleChangePassword: async ({ + password, + oldPassword, + confirmPassword, + user_id, + }) => { + const { status, success, element } = await CheckChangePassword({ + password, + oldPassword, + confirmPassword, + user_id, + }); + + if (!success) { + return { + status, + success, + element, + }; + } + let user = element; + const salt = await PASSWORD.genSalt(); + const passwordHash = await PASSWORD.encodeResetPassword(password, salt); + await UpdatePassword(user.id, passwordHash); + return { + status: 200, + success: true, + element: { + msg: "Change Password Successfully 😂!", + }, + }; + }, +}; diff --git a/backend/src/v1/admin_api/services/auth_admin/otp.service.js b/backend/src/v1/admin_api/services/auth_admin/otp.service.js index d6710d4..a7eafe3 100644 --- a/backend/src/v1/admin_api/services/auth_admin/otp.service.js +++ b/backend/src/v1/admin_api/services/auth_admin/otp.service.js @@ -1,18 +1,18 @@ -"use strict"; -const { _Otp } = require("../../../models/Otp.model"); -const PASSWORD = require("../../../utils/password"); -module.exports = { - validOtp: async ({ otp, hashOtp }) => { - const invalidOtp = await PASSWORD.comparePassword(otp, hashOtp); - return invalidOtp; - }, - insertOtp: async ({ otp, email }) => { - const salt = await PASSWORD.genSalt(); - const hashOtp = await PASSWORD.encodeResetPassword(otp, salt); - const Otp = await _Otp.create({ - email, - otp: hashOtp, - }); - return Otp ? `OTP sent to your ${email}` : 0; - }, -}; +"use strict"; +const { _Otp } = require("../../../models/Otp.model"); +const PASSWORD = require("../../../utils/password"); +module.exports = { + validOtp: async ({ otp, hashOtp }) => { + const invalidOtp = await PASSWORD.comparePassword(otp, hashOtp); + return invalidOtp; + }, + insertOtp: async ({ otp, email }) => { + const salt = await PASSWORD.genSalt(); + const hashOtp = await PASSWORD.encodeResetPassword(otp, salt); + const Otp = await _Otp.create({ + email, + otp: hashOtp, + }); + return Otp ? `OTP sent to your ${email}` : 0; + }, +}; diff --git a/backend/src/v1/admin_api/services/carousel_admin/carousel.service.js b/backend/src/v1/admin_api/services/carousel_admin/carousel.service.js index 984d0cc..b2cc84d 100644 --- a/backend/src/v1/admin_api/services/carousel_admin/carousel.service.js +++ b/backend/src/v1/admin_api/services/carousel_admin/carousel.service.js @@ -1,153 +1,153 @@ -const Carousel = require("../../../models/CarouselModel"); -const HELPER = require("../../../utils/helper"); -const CONSTANTS = require("../../../configs/constants"); -const STORAGE = require("../../../utils/storage"); -const { get, set } = require("../../../utils/limited_redis"); -const { - createCarousel, - editCarousel, - deleteCarousel, -} = require("./crud_carousel.service"); -module.exports = { - handleGetallCarousel: async () => { - try { - const carousel_user_redis = await get("carousel"); - if (carousel_user_redis) { - return { - status: 200, - success: true, - element: { - carousels: JSON.parse(carousel_user_redis), - }, - }; - } - const number_random = HELPER.randomNumber(); - - const carousels = await Carousel.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - - await set( - "carousel", - JSON.stringify(carousels), - CONSTANTS._1_DAYS_REDIS + number_random - ); - return { - status: 200, - success: true, - element: { - carousels, - }, - }; - } catch (err) { - return res.status(500).json({ msg: err.message }); - } - }, - handleCreateCarousel: async ({ heading, descriptions, image }) => { - try { - if (!image) - return { - status: 400, - success: false, - element: { - msg: "No image upload", - }, - }; - const checkExitCarousel = await STORAGE.checkCarouselExit(heading); - if (checkExitCarousel.length > 0) { - return { - status: 400, - success: false, - element: { msg: "Carousel Exit" }, - }; - } - await createCarousel(heading, descriptions, image); - return { - status: 200, - success: true, - element: { - msg: "Create carousel successfully!!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleEditCarousel: async ({ heading, descriptions, image, _id }) => { - try { - if (!image) - return { - status: 400, - success: false, - element: { - msg: "No image upload", - }, - }; - const checkExitCarousel = await STORAGE.checkCarouselExitExceptUserMain( - _id, - heading - ); - if (checkExitCarousel.length > 0) { - return { - status: 400, - success: false, - element: { msg: "Carousel Exit" }, - }; - } - await editCarousel(heading, descriptions, image, _id); - return { - status: 200, - success: true, - element: { - msg: "Edit carousel successfully!!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleDeleteCarousel: async ({ _id }) => { - try { - await deleteCarousel(_id); - return { - status: 200, - success: true, - element: { - msg: "Delete carousel successfully!!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, -}; +const Carousel = require("../../../models/CarouselModel"); +const HELPER = require("../../../utils/helper"); +const CONSTANTS = require("../../../configs/constants"); +const STORAGE = require("../../../utils/storage"); +const { get, set } = require("../../../utils/limited_redis"); +const { + createCarousel, + editCarousel, + deleteCarousel, +} = require("./crud_carousel.service"); +module.exports = { + handleGetallCarousel: async () => { + try { + const carousel_user_redis = await get("carousel"); + if (carousel_user_redis) { + return { + status: 200, + success: true, + element: { + carousels: JSON.parse(carousel_user_redis), + }, + }; + } + const number_random = HELPER.randomNumber(); + + const carousels = await Carousel.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + + await set( + "carousel", + JSON.stringify(carousels), + CONSTANTS._1_DAYS_REDIS + number_random + ); + return { + status: 200, + success: true, + element: { + carousels, + }, + }; + } catch (err) { + return res.status(500).json({ msg: err.message }); + } + }, + handleCreateCarousel: async ({ heading, descriptions, image }) => { + try { + if (!image) + return { + status: 400, + success: false, + element: { + msg: "No image upload", + }, + }; + const checkExitCarousel = await STORAGE.checkCarouselExit(heading); + if (checkExitCarousel.length > 0) { + return { + status: 400, + success: false, + element: { msg: "Carousel Exit" }, + }; + } + await createCarousel(heading, descriptions, image); + return { + status: 200, + success: true, + element: { + msg: "Create carousel successfully!!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleEditCarousel: async ({ heading, descriptions, image, _id }) => { + try { + if (!image) + return { + status: 400, + success: false, + element: { + msg: "No image upload", + }, + }; + const checkExitCarousel = await STORAGE.checkCarouselExitExceptUserMain( + _id, + heading + ); + if (checkExitCarousel.length > 0) { + return { + status: 400, + success: false, + element: { msg: "Carousel Exit" }, + }; + } + await editCarousel(heading, descriptions, image, _id); + return { + status: 200, + success: true, + element: { + msg: "Edit carousel successfully!!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleDeleteCarousel: async ({ _id }) => { + try { + await deleteCarousel(_id); + return { + status: 200, + success: true, + element: { + msg: "Delete carousel successfully!!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, +}; diff --git a/backend/src/v1/admin_api/services/carousel_admin/crud_carousel.service.js b/backend/src/v1/admin_api/services/carousel_admin/crud_carousel.service.js index 6b39b2d..ccb673e 100644 --- a/backend/src/v1/admin_api/services/carousel_admin/crud_carousel.service.js +++ b/backend/src/v1/admin_api/services/carousel_admin/crud_carousel.service.js @@ -1,50 +1,50 @@ -const { del, set } = require("../../../utils/limited_redis"); -const Carousel = require("../../../models/CarouselModel"); -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -module.exports = { - createCarousel: async (heading, descriptions, image) => { - ResetRedisCarousel(); - const newCarousel = new Carousel({ heading, descriptions, image }); - await newCarousel.save(); - return; - }, - editCarousel: async (heading, descriptions, image, _id) => { - ResetRedisCarousel(); - await Carousel.findOneAndUpdate( - { _id: _id }, - { heading, descriptions, image } - ); - return; - }, - deleteCarousel: async (_id) => { - ResetRedisCarousel(); - await Carousel.findByIdAndDelete(_id); - return; - }, -}; -const ResetRedisCarousel = async () => { - await del("carousel"); - const random_number = HELPER.randomNumber(); - - const carousel = await Carousel.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - await set( - "carousel", - JSON.stringify(carousel), - CONSTANTS._1_DAYS_REDIS + random_number - ); -}; +const { del, set } = require("../../../utils/limited_redis"); +const Carousel = require("../../../models/CarouselModel"); +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +module.exports = { + createCarousel: async (heading, descriptions, image) => { + ResetRedisCarousel(); + const newCarousel = new Carousel({ heading, descriptions, image }); + await newCarousel.save(); + return; + }, + editCarousel: async (heading, descriptions, image, _id) => { + ResetRedisCarousel(); + await Carousel.findOneAndUpdate( + { _id: _id }, + { heading, descriptions, image } + ); + return; + }, + deleteCarousel: async (_id) => { + ResetRedisCarousel(); + await Carousel.findByIdAndDelete(_id); + return; + }, +}; +const ResetRedisCarousel = async () => { + await del("carousel"); + const random_number = HELPER.randomNumber(); + + const carousel = await Carousel.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + await set( + "carousel", + JSON.stringify(carousel), + CONSTANTS._1_DAYS_REDIS + random_number + ); +}; diff --git a/backend/src/v1/admin_api/services/category_admin/Crudcategories.service.js b/backend/src/v1/admin_api/services/category_admin/Crudcategories.service.js index d12dd9c..823f809 100644 --- a/backend/src/v1/admin_api/services/category_admin/Crudcategories.service.js +++ b/backend/src/v1/admin_api/services/category_admin/Crudcategories.service.js @@ -1,100 +1,100 @@ -const { set, get, del } = require("../../../utils/limited_redis"); -const Category = require("../../../models/CategoryModel"); -const Products = require("../../../models/ProductModel"); -const STORAGE = require("../../../utils/storage"); -const HELPER = require("../../../utils/helper"); -const CONSTANTS = require("../../../configs/constants"); -module.exports = { - getAllCategory: async () => { - const number_random = HELPER.randomNumber(); - const categories = await get("categories"); - if (categories) { - return JSON.parse(categories); - } - const category = await Category.find(); - await set( - "categories", - JSON.stringify(category), - CONSTANTS._1_DAYS_REDIS + number_random - ); - return category; - }, - createCategory: async (name, image) => { - const category_exit = await STORAGE.checkCategoryExit(name); - if (category_exit) { - return { - status: 400, - success: false, - element: { - msg: "Category Exits !!!", - }, - }; - } - const newCategory = new Category({ name, image }); - await newCategory.save(); - await resetCreateEditRedis(); - return { - status: 200, - success: true, - element: { - msg: "Create Category Success !!!", - }, - }; - }, - editCategory: async (category_id, name, image) => { - const category_exit = await STORAGE.checkCategoryExitExceptUserMain( - category_id, - name - ); - if (category_exit.length > 0) { - return { - status: 400, - success: false, - element: { - msg: "Category Exits !!!", - }, - }; - } - await Category.findOneAndUpdate({ _id: category_id }, { name, image }); - await resetCreateEditRedis(); - return { - status: 200, - success: true, - element: { - msg: "Edit Category Success !!!", - }, - }; - }, - deleteCategory: async (category_id) => { - if (!category_id) { - return { - status: 404, - success: false, - element: { - msg: "Delete Not Found", - }, - }; - } - const products = await Products.findOne({ categories: category_id }); - if (products) - return res.json({ - status: 400, - success: false, - msg: "Please delete all products with a relationship.", - }); - await Category.findByIdAndDelete(category_id); - await resetCreateEditRedis(); - return { - status: 200, - success: true, - element: { - msg: "Delete Category Success !!!", - }, - }; - }, -}; -const resetCreateEditRedis = async () => { - await del("categories"); - const category = await Category.find(); - await set("categories", JSON.stringify(category)); -}; +const { set, get, del } = require("../../../utils/limited_redis"); +const Category = require("../../../models/CategoryModel"); +const Products = require("../../../models/ProductModel"); +const STORAGE = require("../../../utils/storage"); +const HELPER = require("../../../utils/helper"); +const CONSTANTS = require("../../../configs/constants"); +module.exports = { + getAllCategory: async () => { + const number_random = HELPER.randomNumber(); + const categories = await get("categories"); + if (categories) { + return JSON.parse(categories); + } + const category = await Category.find(); + await set( + "categories", + JSON.stringify(category), + CONSTANTS._1_DAYS_REDIS + number_random + ); + return category; + }, + createCategory: async (name, image) => { + const category_exit = await STORAGE.checkCategoryExit(name); + if (category_exit) { + return { + status: 400, + success: false, + element: { + msg: "Category Exits !!!", + }, + }; + } + const newCategory = new Category({ name, image }); + await newCategory.save(); + await resetCreateEditRedis(); + return { + status: 200, + success: true, + element: { + msg: "Create Category Success !!!", + }, + }; + }, + editCategory: async (category_id, name, image) => { + const category_exit = await STORAGE.checkCategoryExitExceptUserMain( + category_id, + name + ); + if (category_exit.length > 0) { + return { + status: 400, + success: false, + element: { + msg: "Category Exits !!!", + }, + }; + } + await Category.findOneAndUpdate({ _id: category_id }, { name, image }); + await resetCreateEditRedis(); + return { + status: 200, + success: true, + element: { + msg: "Edit Category Success !!!", + }, + }; + }, + deleteCategory: async (category_id) => { + if (!category_id) { + return { + status: 404, + success: false, + element: { + msg: "Delete Not Found", + }, + }; + } + const products = await Products.findOne({ categories: category_id }); + if (products) + return res.json({ + status: 400, + success: false, + msg: "Please delete all products with a relationship.", + }); + await Category.findByIdAndDelete(category_id); + await resetCreateEditRedis(); + return { + status: 200, + success: true, + element: { + msg: "Delete Category Success !!!", + }, + }; + }, +}; +const resetCreateEditRedis = async () => { + await del("categories"); + const category = await Category.find(); + await set("categories", JSON.stringify(category)); +}; diff --git a/backend/src/v1/admin_api/services/category_admin/category.service.js b/backend/src/v1/admin_api/services/category_admin/category.service.js index 2b8030e..bf2e148 100644 --- a/backend/src/v1/admin_api/services/category_admin/category.service.js +++ b/backend/src/v1/admin_api/services/category_admin/category.service.js @@ -1,44 +1,44 @@ -const { - getAllCategory, - createCategory, - editCategory, - deleteCategory, -} = require("./Crudcategories.service"); -module.exports = { - HandleGetCategory: async () => { - const category = await getAllCategory(); - return { - status: 200, - success: true, - element: category, - }; - }, - handleCreateCategory: async ({ name, image }) => { - const { status, success, element } = await createCategory(name, image); - return { - status, - success, - element, - }; - }, - handleEditCategory: async ({ category_id, name, image }) => { - const { status, success, element } = await editCategory( - category_id, - name, - image - ); - return { - status, - success, - element, - }; - }, - handleDeleteCategory: async ({ category_id }) => { - const { status, success, element } = await deleteCategory(category_id); - return { - status, - success, - element, - }; - }, -}; +const { + getAllCategory, + createCategory, + editCategory, + deleteCategory, +} = require("./Crudcategories.service"); +module.exports = { + HandleGetCategory: async () => { + const category = await getAllCategory(); + return { + status: 200, + success: true, + element: category, + }; + }, + handleCreateCategory: async ({ name, image }) => { + const { status, success, element } = await createCategory(name, image); + return { + status, + success, + element, + }; + }, + handleEditCategory: async ({ category_id, name, image }) => { + const { status, success, element } = await editCategory( + category_id, + name, + image + ); + return { + status, + success, + element, + }; + }, + handleDeleteCategory: async ({ category_id }) => { + const { status, success, element } = await deleteCategory(category_id); + return { + status, + success, + element, + }; + }, +}; diff --git a/backend/src/v1/admin_api/services/feedback_admin/feedback.service.js b/backend/src/v1/admin_api/services/feedback_admin/feedback.service.js index e294aa3..c42f782 100644 --- a/backend/src/v1/admin_api/services/feedback_admin/feedback.service.js +++ b/backend/src/v1/admin_api/services/feedback_admin/feedback.service.js @@ -1,139 +1,139 @@ -const { RedisPub } = require("../../../utils/limited_redis"); -const feedbacks = require("../../../models/feedBackModel"); -const HELPER = require("../../../utils/helper"); -module.exports = { - handleGetAllFeedback: async () => { - const list_feedback = await feedbacks.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - return { - status: 200, - success: true, - element: { - list_feedback, - }, - }; - }, - handleResponseFeedback: async ({ id, response_content }) => { - const feedback = await feedbacks.findById({ _id: id }); - if (!feedback) { - return { - status: 400, - success: false, - element: { - msg: "This feedback does not exist", - }, - }; - } - await RedisPub( - "admin_response_feedback", - JSON.stringify({ - feedback, - response_content, - }) - ); - return { - status: 200, - success: true, - element: { - msg: "Sent email response feedback successfully", - }, - }; - }, - handleReadFeedback: async ({ id }) => { - try { - if (!id) { - return { - status: 200, - success: true, - element: { - msg: "Sent email response feedback successfully", - }, - }; - } - let time_log_gmt7_string = HELPER.getCurrentTimeJP(); - await feedbacks.findOneAndUpdate( - { _id: id }, - { read_at: time_log_gmt7_string, checked: true } - ); - return { - status: 200, - success: true, - element: { - msg: "Read Email Successfully!!", - }, - }; - } catch (err) { - return { - status: 500, - success: false, - element: { - msg: "Server busy!", - }, - }; - } - }, - handleSearchFeedbackDate: async ({ checked }) => { - if (checked === "0") { - const list_feedback = await feedbacks.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - return { - status: 200, - success: true, - msg: "Get all feedbacks successfully", - element: { - list_feedback, - }, - }; - } else if (checked === "1") { - const list_feedback = await feedbacks - .find({ checked: true }) - .sort({ createdAt: -1 }); - return { - status: 200, - success: true, - msg: "Get all feedbacks successfully", - element: { - list_feedback, - }, - }; - } else if (checked === "2") { - const list_feedback = await feedbacks - .find({ checked: false }) - .sort({ createdAt: -1 }); - return { - status: 200, - success: true, - msg: "Get all feedbacks successfully", - element: { - list_feedback, - }, - }; - } - }, -}; +const { RedisPub } = require("../../../utils/limited_redis"); +const feedbacks = require("../../../models/feedBackModel"); +const HELPER = require("../../../utils/helper"); +module.exports = { + handleGetAllFeedback: async () => { + const list_feedback = await feedbacks.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + return { + status: 200, + success: true, + element: { + list_feedback, + }, + }; + }, + handleResponseFeedback: async ({ id, response_content }) => { + const feedback = await feedbacks.findById({ _id: id }); + if (!feedback) { + return { + status: 400, + success: false, + element: { + msg: "This feedback does not exist", + }, + }; + } + await RedisPub( + "admin_response_feedback", + JSON.stringify({ + feedback, + response_content, + }) + ); + return { + status: 200, + success: true, + element: { + msg: "Sent email response feedback successfully", + }, + }; + }, + handleReadFeedback: async ({ id }) => { + try { + if (!id) { + return { + status: 200, + success: true, + element: { + msg: "Sent email response feedback successfully", + }, + }; + } + let time_log_gmt7_string = HELPER.getCurrentTimeJP(); + await feedbacks.findOneAndUpdate( + { _id: id }, + { read_at: time_log_gmt7_string, checked: true } + ); + return { + status: 200, + success: true, + element: { + msg: "Read Email Successfully!!", + }, + }; + } catch (err) { + return { + status: 500, + success: false, + element: { + msg: "Server busy!", + }, + }; + } + }, + handleSearchFeedbackDate: async ({ checked }) => { + if (checked === "0") { + const list_feedback = await feedbacks.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + return { + status: 200, + success: true, + msg: "Get all feedbacks successfully", + element: { + list_feedback, + }, + }; + } else if (checked === "1") { + const list_feedback = await feedbacks + .find({ checked: true }) + .sort({ createdAt: -1 }); + return { + status: 200, + success: true, + msg: "Get all feedbacks successfully", + element: { + list_feedback, + }, + }; + } else if (checked === "2") { + const list_feedback = await feedbacks + .find({ checked: false }) + .sort({ createdAt: -1 }); + return { + status: 200, + success: true, + msg: "Get all feedbacks successfully", + element: { + list_feedback, + }, + }; + } + }, +}; diff --git a/backend/src/v1/admin_api/services/manager_users/curd_manager.service.js b/backend/src/v1/admin_api/services/manager_users/curd_manager.service.js index 2bebd61..8ebe1cd 100644 --- a/backend/src/v1/admin_api/services/manager_users/curd_manager.service.js +++ b/backend/src/v1/admin_api/services/manager_users/curd_manager.service.js @@ -1,97 +1,97 @@ -const { del } = require("../../../utils/limited_redis"); -const CONSTANTS = require("../../../configs/constants"); -const Users = require("../../../models/userModel"); -const getAllUser = async () => { - return await Users.find({ - role: 0, - verified: CONSTANTS.DELETED_ENABLE, - }).sort({ createdAt: -1 }); -}; -const getAllAdmin = async () => { - return await Users.find({ - role: 1, - verified: CONSTANTS.DELETED_ENABLE, - }).sort({ createdAt: -1 }); -}; -const getAllUserDelete = async () => { - Users.find({ - verified: CONSTANTS.DELETED_DISABLE, - role: 0, - }) - .select("-password") - .sort({ createdAt: -1 }); -}; -const uploadAccount = async ( - name, - image, - phone_number, - role, - sex, - date_of_birth, - user_id -) => { - await Users.findOneAndUpdate( - { _id: user_id }, - { - name, - image, - phone_number, - role, - sex, - date_of_birth, - } - ); - return { - success: true, - }; -}; -const getAllUserSort = async (year_now, monthly) => { - return await Users.aggregate([ - { - //giong select - $project: { - month: { $month: "$updatedAt" }, - year: { $year: "$updatedAt" }, - role: 1, - verified: 1, - }, - }, - { - //kiểm tra - $match: { - month: { $in: monthly }, - year: year_now, - role: 0, - verified: true, - }, - }, - { - //khai báo nhận giá trị tự đặt - $group: { - _id: "$month", - count: { $sum: 1 }, - }, - }, - { $sort: { _id: 1 } }, - ]); -}; -const deleteAccount = async (user_id) => { - await Users.findByIdAndDelete(user_id); - await del(`userId:${user_id}`); - await del(`cartUserId:${user_id}`); -}; -const GetDayNewUser = (d1, d2) => { - let value1 = d1.getTime(); - let value2 = d2.getTime(); - return Math.ceil((value2 - value1) / CONSTANTS._1_DAY); -}; - -module.exports = { - getAllUser, - getAllAdmin, - uploadAccount, - deleteAccount, - GetDayNewUser, - getAllUserDelete, - getAllUserSort, -}; +const { del } = require("../../../utils/limited_redis"); +const CONSTANTS = require("../../../configs/constants"); +const Users = require("../../../models/userModel"); +const getAllUser = async () => { + return await Users.find({ + role: 0, + verified: CONSTANTS.DELETED_ENABLE, + }).sort({ createdAt: -1 }); +}; +const getAllAdmin = async () => { + return await Users.find({ + role: 1, + verified: CONSTANTS.DELETED_ENABLE, + }).sort({ createdAt: -1 }); +}; +const getAllUserDelete = async () => { + Users.find({ + verified: CONSTANTS.DELETED_DISABLE, + role: 0, + }) + .select("-password") + .sort({ createdAt: -1 }); +}; +const uploadAccount = async ( + name, + image, + phone_number, + role, + sex, + date_of_birth, + user_id +) => { + await Users.findOneAndUpdate( + { _id: user_id }, + { + name, + image, + phone_number, + role, + sex, + date_of_birth, + } + ); + return { + success: true, + }; +}; +const getAllUserSort = async (year_now, monthly) => { + return await Users.aggregate([ + { + //giong select + $project: { + month: { $month: "$updatedAt" }, + year: { $year: "$updatedAt" }, + role: 1, + verified: 1, + }, + }, + { + //kiểm tra + $match: { + month: { $in: monthly }, + year: year_now, + role: 0, + verified: true, + }, + }, + { + //khai báo nhận giá trị tự đặt + $group: { + _id: "$month", + count: { $sum: 1 }, + }, + }, + { $sort: { _id: 1 } }, + ]); +}; +const deleteAccount = async (user_id) => { + await Users.findByIdAndDelete(user_id); + await del(`userId:${user_id}`); + await del(`cartUserId:${user_id}`); +}; +const GetDayNewUser = (d1, d2) => { + let value1 = d1.getTime(); + let value2 = d2.getTime(); + return Math.ceil((value2 - value1) / CONSTANTS._1_DAY); +}; + +module.exports = { + getAllUser, + getAllAdmin, + uploadAccount, + deleteAccount, + GetDayNewUser, + getAllUserDelete, + getAllUserSort, +}; diff --git a/backend/src/v1/admin_api/services/manager_users/manager_user.service.js b/backend/src/v1/admin_api/services/manager_users/manager_user.service.js index 94707bc..a8efeb2 100644 --- a/backend/src/v1/admin_api/services/manager_users/manager_user.service.js +++ b/backend/src/v1/admin_api/services/manager_users/manager_user.service.js @@ -1,264 +1,264 @@ -const { - getAllUser, - getAllAdmin, - uploadAccount, - deleteAccount, - GetDayNewUser, - getAllUserDelete, - getAllUserSort, -} = require("./curd_manager.service"); -const { - CheckUpdateProfile, -} = require("../../../user_api/services/user.service/checkAuthUser.service"); -const Products = require("../../../models/ProductModel"); -const Payments = require("../../../models/PaymentModel"); -module.exports = { - handleGetAllUsers: async () => { - try { - const user = await getAllUser(); - return { - status: 200, - success: true, - element: { - user, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleGetAllAdmin: async () => { - try { - const admin = await getAllAdmin(); - return { - status: 200, - success: true, - element: { - admin, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleUploadAccount: async ({ - name, - image, - phone_number, - role, - sex, - date_of_birth, - user_id, - }) => { - try { - if (!image) - return { - status: 400, - success: false, - element: { - msg: "No image upload", - }, - }; - const { status, success, element } = await CheckUpdateProfile({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }); - if (!success) { - return { - status, - success, - element, - }; - } - await uploadAccount( - name, - image, - phone_number, - role, - sex, - date_of_birth, - user_id - ); - - return { - status: 200, - success: true, - element: { - msg: "Updated Successfully !", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleDeleteAccount: async ({ user_id }) => { - try { - await deleteAccount(user_id); - const products = await Products.find({}); - for (var i = 0; i < products.length; i++) { - for (var j = 0; j < products[i].reviews.length; j++) { - if (products[i].reviews[j].user.toString() === user_id) { - const a = products[i].reviews.slice(0, j); - const b = products[i].reviews.slice( - j + 1, - products[i].reviews.length - ); - const c = a.concat(b); - products[i].reviews = c; - } - } - products[i].numReviews = products[i].reviews.length; - - if (products[i].reviews.length === 0) { - products[i].rating = 0; - } else { - products[i].rating = - products[i].reviews.reduce((acc, item) => item.rating + acc, 0) / - products[i].reviews.length; - } - await products[i].save(); - } - - await Payments.deleteMany({ - user_id: user_id, - }); - return { - status: 200, - success: true, - element: { - msg: "Deleted a Successfully !", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleListUserNews: async () => { - try { - let user = await getAllUser(); - var today = new Date(); - var result = []; - for (var i = 0; i < user.length; i++) { - var time = GetDayNewUser(user[i].createdAt, today); - if (time <= 3) { - result.push(user[i]); - } - } - if (result.length === 0) { - return { - status: 200, - success: true, - element: { - msg: "No Account New !!", - result, - }, - }; - } else { - return { - status: 200, - success: true, - element: { - msg: "Get New User Successfully !!", - result, - }, - }; - } - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleListUserDeleteOrders: async () => { - try { - const usersUncheck = await getAllUserDelete(); - return { - status: 200, - success: true, - element: { - user: usersUncheck, - }, - }; - } catch (error) { - return res.status(500).json({ msg: error.message }); - } - }, - handleListUsersMonthlyRegistered: async () => { - try { - const monthly = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - const year_now = new Date().getFullYear(); - let statistics = await getAllUserSort(year_now, monthly); - console.log(":::run"); - - for (let i = 0; i < statistics.length; i++) { - if (monthly.includes(statistics[i]._id)) { - var index = monthly.indexOf(statistics[i]._id); - monthly.splice(index, 1); - } - } - - var missing_statistics = []; - for (let i = 0; i < monthly.length; i++) { - missing_statistics.push({ - _id: monthly[i], - count: 0, - }); - } - - var data = statistics.concat(missing_statistics); - - data.sort((a, b) => { - return a._id - b._id; - }); - - return { - status: 200, - success: true, - element: { - msg: "Get monthly registered customers successfully", - data, - }, - }; - } catch (err) { - return res.status(400).json({ - status: 400, - success: false, - element: { - msg: "Failed to get monthly registered customers", - }, - }); - } - }, -}; +const { + getAllUser, + getAllAdmin, + uploadAccount, + deleteAccount, + GetDayNewUser, + getAllUserDelete, + getAllUserSort, +} = require("./curd_manager.service"); +const { + CheckUpdateProfile, +} = require("../../../user_api/services/user.service/checkAuthUser.service"); +const Products = require("../../../models/ProductModel"); +const Payments = require("../../../models/PaymentModel"); +module.exports = { + handleGetAllUsers: async () => { + try { + const user = await getAllUser(); + return { + status: 200, + success: true, + element: { + user, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleGetAllAdmin: async () => { + try { + const admin = await getAllAdmin(); + return { + status: 200, + success: true, + element: { + admin, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleUploadAccount: async ({ + name, + image, + phone_number, + role, + sex, + date_of_birth, + user_id, + }) => { + try { + if (!image) + return { + status: 400, + success: false, + element: { + msg: "No image upload", + }, + }; + const { status, success, element } = await CheckUpdateProfile({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }); + if (!success) { + return { + status, + success, + element, + }; + } + await uploadAccount( + name, + image, + phone_number, + role, + sex, + date_of_birth, + user_id + ); + + return { + status: 200, + success: true, + element: { + msg: "Updated Successfully !", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleDeleteAccount: async ({ user_id }) => { + try { + await deleteAccount(user_id); + const products = await Products.find({}); + for (var i = 0; i < products.length; i++) { + for (var j = 0; j < products[i].reviews.length; j++) { + if (products[i].reviews[j].user.toString() === user_id) { + const a = products[i].reviews.slice(0, j); + const b = products[i].reviews.slice( + j + 1, + products[i].reviews.length + ); + const c = a.concat(b); + products[i].reviews = c; + } + } + products[i].numReviews = products[i].reviews.length; + + if (products[i].reviews.length === 0) { + products[i].rating = 0; + } else { + products[i].rating = + products[i].reviews.reduce((acc, item) => item.rating + acc, 0) / + products[i].reviews.length; + } + await products[i].save(); + } + + await Payments.deleteMany({ + user_id: user_id, + }); + return { + status: 200, + success: true, + element: { + msg: "Deleted a Successfully !", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleListUserNews: async () => { + try { + let user = await getAllUser(); + var today = new Date(); + var result = []; + for (var i = 0; i < user.length; i++) { + var time = GetDayNewUser(user[i].createdAt, today); + if (time <= 3) { + result.push(user[i]); + } + } + if (result.length === 0) { + return { + status: 200, + success: true, + element: { + msg: "No Account New !!", + result, + }, + }; + } else { + return { + status: 200, + success: true, + element: { + msg: "Get New User Successfully !!", + result, + }, + }; + } + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleListUserDeleteOrders: async () => { + try { + const usersUncheck = await getAllUserDelete(); + return { + status: 200, + success: true, + element: { + user: usersUncheck, + }, + }; + } catch (error) { + return res.status(500).json({ msg: error.message }); + } + }, + handleListUsersMonthlyRegistered: async () => { + try { + const monthly = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + const year_now = new Date().getFullYear(); + let statistics = await getAllUserSort(year_now, monthly); + console.log(":::run"); + + for (let i = 0; i < statistics.length; i++) { + if (monthly.includes(statistics[i]._id)) { + var index = monthly.indexOf(statistics[i]._id); + monthly.splice(index, 1); + } + } + + var missing_statistics = []; + for (let i = 0; i < monthly.length; i++) { + missing_statistics.push({ + _id: monthly[i], + count: 0, + }); + } + + var data = statistics.concat(missing_statistics); + + data.sort((a, b) => { + return a._id - b._id; + }); + + return { + status: 200, + success: true, + element: { + msg: "Get monthly registered customers successfully", + data, + }, + }; + } catch (err) { + return res.status(400).json({ + status: 400, + success: false, + element: { + msg: "Failed to get monthly registered customers", + }, + }); + } + }, +}; diff --git a/backend/src/v1/admin_api/services/order_admin/curd_order.service.js b/backend/src/v1/admin_api/services/order_admin/curd_order.service.js index 852ad9a..6e60415 100644 --- a/backend/src/v1/admin_api/services/order_admin/curd_order.service.js +++ b/backend/src/v1/admin_api/services/order_admin/curd_order.service.js @@ -1,36 +1,36 @@ -const Payments = require("../../../models/PaymentModel"); -const CONSTANTS = require("../../../configs/constants"); -const updateOrderDelete = async (payment_id) => { - await Payments.findByIdAndUpdate( - { _id: payment_id }, - { - deleteAt: CONSTANTS.DELETED_DISABLE, - } - ); -}; -const getAllOrder = async () => { - return await Payments.find({ deleteAt: CONSTANTS.DELETED_DISABLE }) - .populate("user_id") - .sort({ createdAt: -1 }); -}; -const getAllOrderDelete = async () => { - return await Payments.find({ deleteAt: CONSTANTS.DELETED_ENABLE }) - .populate("user_id") - .sort({ createdAt: -1 }); -}; -const updateStatusOrder = async (order_status, id) => { - await Payments.findByIdAndUpdate( - { _id: id }, - { order_status, updatedAt: Date.now } - ); -}; -const getDetailOrder = async (order_id) => { - return await Payments.findById(order_id); -}; -module.exports = { - updateOrderDelete, - getAllOrder, - updateStatusOrder, - getDetailOrder, - getAllOrderDelete, -}; +const Payments = require("../../../models/PaymentModel"); +const CONSTANTS = require("../../../configs/constants"); +const updateOrderDelete = async (payment_id) => { + await Payments.findByIdAndUpdate( + { _id: payment_id }, + { + deleteAt: CONSTANTS.DELETED_DISABLE, + } + ); +}; +const getAllOrder = async () => { + return await Payments.find({ deleteAt: CONSTANTS.DELETED_DISABLE }) + .populate("user_id") + .sort({ createdAt: -1 }); +}; +const getAllOrderDelete = async () => { + return await Payments.find({ deleteAt: CONSTANTS.DELETED_ENABLE }) + .populate("user_id") + .sort({ createdAt: -1 }); +}; +const updateStatusOrder = async (order_status, id) => { + await Payments.findByIdAndUpdate( + { _id: id }, + { order_status, updatedAt: Date.now } + ); +}; +const getDetailOrder = async (order_id) => { + return await Payments.findById(order_id); +}; +module.exports = { + updateOrderDelete, + getAllOrder, + updateStatusOrder, + getDetailOrder, + getAllOrderDelete, +}; diff --git a/backend/src/v1/admin_api/services/order_admin/order.service.js b/backend/src/v1/admin_api/services/order_admin/order.service.js index 2d8130d..511e2b0 100644 --- a/backend/src/v1/admin_api/services/order_admin/order.service.js +++ b/backend/src/v1/admin_api/services/order_admin/order.service.js @@ -1,129 +1,129 @@ -const { - updateOrderDelete, - getAllOrder, - updateStatusOrder, - getDetailOrder, - getAllOrderDelete, -} = require("./curd_order.service"); - -module.exports = { - handleUpdateOrderDeleteUsers: async (payment_id) => { - try { - await updateOrderDelete(payment_id); - return { - status: 200, - success: true, - element: { - msg: "Undo Payment Successfully", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Fail !!", - }, - }; - } - }, - handleGetAllOrderUsers: async () => { - try { - const order = await getAllOrder(); - return { - status: 200, - success: true, - element: { - order, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Fail !!", - }, - }; - } - }, - handleGetAllOrderDeleteUsers: async () => { - try { - const order = await getAllOrderDelete(); - return { - status: 200, - success: true, - element: { - order, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Fail !!", - }, - }; - } - }, - handleUploadStatus: async ({ order_status, id }) => { - try { - if (order_status !== "On Delivery" && order_status !== "Delivered") { - return { - status: 400, - success: false, - element: { - msg: "Please choose order status", - }, - }; - } - await updateStatusOrder(order_status, id); - return { - status: 200, - success: true, - element: { - msg: "Update order status successfully", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Fail !!", - }, - }; - } - }, - handleGetDetail: async ({ order_id }) => { - try { - const Payment = await getDetailOrder(order_id); - if (!Payment) { - return n({ - status: 400, - success: false, - element: { - msg: "Payments not found !!!", - }, - }); - } - return { - status: 200, - success: true, - element: { - msg: "Get Payments Detail Successfully !", - Payment, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Fail !!", - }, - }; - } - }, -}; +const { + updateOrderDelete, + getAllOrder, + updateStatusOrder, + getDetailOrder, + getAllOrderDelete, +} = require("./curd_order.service"); + +module.exports = { + handleUpdateOrderDeleteUsers: async (payment_id) => { + try { + await updateOrderDelete(payment_id); + return { + status: 200, + success: true, + element: { + msg: "Undo Payment Successfully", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Fail !!", + }, + }; + } + }, + handleGetAllOrderUsers: async () => { + try { + const order = await getAllOrder(); + return { + status: 200, + success: true, + element: { + order, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Fail !!", + }, + }; + } + }, + handleGetAllOrderDeleteUsers: async () => { + try { + const order = await getAllOrderDelete(); + return { + status: 200, + success: true, + element: { + order, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Fail !!", + }, + }; + } + }, + handleUploadStatus: async ({ order_status, id }) => { + try { + if (order_status !== "On Delivery" && order_status !== "Delivered") { + return { + status: 400, + success: false, + element: { + msg: "Please choose order status", + }, + }; + } + await updateStatusOrder(order_status, id); + return { + status: 200, + success: true, + element: { + msg: "Update order status successfully", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Fail !!", + }, + }; + } + }, + handleGetDetail: async ({ order_id }) => { + try { + const Payment = await getDetailOrder(order_id); + if (!Payment) { + return n({ + status: 400, + success: false, + element: { + msg: "Payments not found !!!", + }, + }); + } + return { + status: 200, + success: true, + element: { + msg: "Get Payments Detail Successfully !", + Payment, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Fail !!", + }, + }; + } + }, +}; diff --git a/backend/src/v1/admin_api/services/product_admin/Curd_products.service.js b/backend/src/v1/admin_api/services/product_admin/Curd_products.service.js index eb5968f..68606be 100644 --- a/backend/src/v1/admin_api/services/product_admin/Curd_products.service.js +++ b/backend/src/v1/admin_api/services/product_admin/Curd_products.service.js @@ -1,103 +1,103 @@ -const CONSTANTS = require("../../../configs/constants"); -const Products = require("../../../models/ProductModel"); -const HELPER = require("../../../utils/helper"); -const { set, del } = require("../../../utils/limited_redis"); -//* Get Id product -const getProductId = async (product_id) => { - const product = await Products.findById(product_id).populate({ - path: "reviews", - populate: { - path: "user", - }, - }); - return product; -}; -//* create Product -const createProductNew = async ( - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories -) => { - const newProduct = new Products({ - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - }); - await newProduct.save(); - await resetCreateEditRedis(); - return; -}; -//* Edit Product -const editProductNew = async ( - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - product_id -) => { - await Products.findOneAndUpdate( - { _id: product_id }, - { - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - } - ); - await resetCreateEditRedis(); - return; -}; -//* Delete Product -const deleteProduct = async (product_id) => { - await Products.findByIdAndDelete(product_id); - await resetCreateEditRedis(); - return; -}; -const resetCreateEditRedis = async () => { - const random_number = HELPER.randomNumber(); - await del("product_user"); - const product_user = await Products.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - await set( - "product_user", - JSON.stringify(product_user), - CONSTANTS._1_DAY + random_number - ); -}; -module.exports = { - getProductId, - createProductNew, - editProductNew, - deleteProduct, -}; +const CONSTANTS = require("../../../configs/constants"); +const Products = require("../../../models/ProductModel"); +const HELPER = require("../../../utils/helper"); +const { set, del } = require("../../../utils/limited_redis"); +//* Get Id product +const getProductId = async (product_id) => { + const product = await Products.findById(product_id).populate({ + path: "reviews", + populate: { + path: "user", + }, + }); + return product; +}; +//* create Product +const createProductNew = async ( + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories +) => { + const newProduct = new Products({ + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + }); + await newProduct.save(); + await resetCreateEditRedis(); + return; +}; +//* Edit Product +const editProductNew = async ( + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + product_id +) => { + await Products.findOneAndUpdate( + { _id: product_id }, + { + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + } + ); + await resetCreateEditRedis(); + return; +}; +//* Delete Product +const deleteProduct = async (product_id) => { + await Products.findByIdAndDelete(product_id); + await resetCreateEditRedis(); + return; +}; +const resetCreateEditRedis = async () => { + const random_number = HELPER.randomNumber(); + await del("product_user"); + const product_user = await Products.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + await set( + "product_user", + JSON.stringify(product_user), + CONSTANTS._1_DAY + random_number + ); +}; +module.exports = { + getProductId, + createProductNew, + editProductNew, + deleteProduct, +}; diff --git a/backend/src/v1/admin_api/services/product_admin/products.service.js b/backend/src/v1/admin_api/services/product_admin/products.service.js index 5d6a4a3..993cd45 100644 --- a/backend/src/v1/admin_api/services/product_admin/products.service.js +++ b/backend/src/v1/admin_api/services/product_admin/products.service.js @@ -1,150 +1,150 @@ -const { - getProductId, - createProductNew, - editProductNew, - deleteProduct, -} = require("./Curd_products.service"); -const { - checkProductExitExceptUserMain, - checkProductExit, -} = require("../../../utils/storage"); -const APIfeatures = require("../../../strategy_pattern/APIfeatures"); -const Products = require("../../../models/ProductModel"); -module.exports = { - handleGetallProduct: async ({ req }) => { - const features = new APIfeatures(Products.find(), req.query) - .filtering() - .sorting(); - - const products = await features.query.populate("categories"); - return { - status: 200, - success: true, - element: products, - }; - }, - handleProductId: async ({ product_id }) => { - const products = await getProductId(product_id); - if (!products) { - return { - status: 400, - success: false, - element: { - msg: "Product Not Found", - }, - }; - } - return { - status: 200, - success: true, - element: products, - }; - }, - handleCreateProduct: async ({ - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - }) => { - const checkExitProduct = await checkProductExit(name); - if (!image) { - return { - status: 400, - success: false, - element: { msg: "No image upload" }, - }; - } - if (checkExitProduct.length > 0) { - return { - status: 400, - success: false, - element: { msg: "Product Exit" }, - }; - } - - await createProductNew( - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories - ); - - return { - status: 200, - success: true, - element: { msg: "Create Product Successfully" }, - }; - }, - handleEditProduct: async ({ - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - product_id, - }) => { - if (!image) { - return { - status: 400, - success: false, - element: { msg: "No image upload" }, - }; - } - const checkExitProduct = await checkProductExitExceptUserMain( - product_id, - name - ); - - if (checkExitProduct.length > 0) { - return { - status: 400, - success: false, - element: { msg: "Product Exit" }, - }; - } - await editProductNew( - name, - image, - description, - rating, - price, - countInStock, - numReviews, - categories, - product_id - ); - return { - status: 200, - success: true, - element: { msg: "Edit Product Successfully" }, - }; - }, - handleDeleteProduct: async ({ product_id }) => { - if (!product_id) { - return { - status: 400, - success: false, - element: { - msg: "Delete Product Fail", - }, - }; - } - await deleteProduct(product_id); - return { - status: 200, - success: true, - element: { msg: "delete Product Successfully" }, - }; - }, -}; +const { + getProductId, + createProductNew, + editProductNew, + deleteProduct, +} = require("./Curd_products.service"); +const { + checkProductExitExceptUserMain, + checkProductExit, +} = require("../../../utils/storage"); +const APIfeatures = require("../../../strategy_pattern/APIfeatures"); +const Products = require("../../../models/ProductModel"); +module.exports = { + handleGetallProduct: async ({ req }) => { + const features = new APIfeatures(Products.find(), req.query) + .filtering() + .sorting(); + + const products = await features.query.populate("categories"); + return { + status: 200, + success: true, + element: products, + }; + }, + handleProductId: async ({ product_id }) => { + const products = await getProductId(product_id); + if (!products) { + return { + status: 400, + success: false, + element: { + msg: "Product Not Found", + }, + }; + } + return { + status: 200, + success: true, + element: products, + }; + }, + handleCreateProduct: async ({ + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + }) => { + const checkExitProduct = await checkProductExit(name); + if (!image) { + return { + status: 400, + success: false, + element: { msg: "No image upload" }, + }; + } + if (checkExitProduct.length > 0) { + return { + status: 400, + success: false, + element: { msg: "Product Exit" }, + }; + } + + await createProductNew( + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories + ); + + return { + status: 200, + success: true, + element: { msg: "Create Product Successfully" }, + }; + }, + handleEditProduct: async ({ + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + product_id, + }) => { + if (!image) { + return { + status: 400, + success: false, + element: { msg: "No image upload" }, + }; + } + const checkExitProduct = await checkProductExitExceptUserMain( + product_id, + name + ); + + if (checkExitProduct.length > 0) { + return { + status: 400, + success: false, + element: { msg: "Product Exit" }, + }; + } + await editProductNew( + name, + image, + description, + rating, + price, + countInStock, + numReviews, + categories, + product_id + ); + return { + status: 200, + success: true, + element: { msg: "Edit Product Successfully" }, + }; + }, + handleDeleteProduct: async ({ product_id }) => { + if (!product_id) { + return { + status: 400, + success: false, + element: { + msg: "Delete Product Fail", + }, + }; + } + await deleteProduct(product_id); + return { + status: 200, + success: true, + element: { msg: "delete Product Successfully" }, + }; + }, +}; diff --git a/backend/src/v1/admin_api/services/tatistical_admin/statistical.service.js b/backend/src/v1/admin_api/services/tatistical_admin/statistical.service.js index e81025c..9d06f66 100644 --- a/backend/src/v1/admin_api/services/tatistical_admin/statistical.service.js +++ b/backend/src/v1/admin_api/services/tatistical_admin/statistical.service.js @@ -1,411 +1,411 @@ -const Payments = require("../../../models/PaymentModel"); -const CONSTANTS = require("../../../configs/constants"); -module.exports = { - handleGetSumInCome: async () => { - try { - const data = await Payments.aggregate([ - { - $group: { - _id: "sum_of_income", - total: { $sum: "$total" }, - }, - }, - ]); - - return { - status: 200, - success: true, - element: { - msg: "Get sum of income successfully", - data, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Get sum of income fail", - }, - }; - } - }, - handleGetUserBuy3days: async () => { - try { - let payments = await Payments.find({ - deleteAt: CONSTANTS.DELETED_DISABLE, - }) - .populate("user_id") - .sort({ createdAt: -1 }); - var today = new Date(); - var result = []; - for (var i = 0; i < payments.length; i++) { - var time = GetDayNewUserBuy(payments[i].createdAt, today); - if (time <= 3) { - result.push(payments[i]); - } - } - if (result.length === 0) { - return { - status: 200, - success: true, - element: { - msg: "No Account New !!", - result, - }, - }; - } else { - return { - status: 200, - success: true, - element: { - total: result.length, - msg: "Get New User Buy Successfully !!", - result, - }, - }; - } - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Get sum of income fail", - }, - }; - } - }, - handleMonthlyIncomeCustomerReceived: async () => { - const monthly = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; - const year_now = new Date().getFullYear(); - - try { - let statistics = await Payments.aggregate([ - { - $project: { - month: { $month: "$updatedAt" }, - year: { $year: "$updatedAt" }, - order_status: 1, - total: 1, - }, - }, - { - $match: { - month: { $in: monthly }, - year: year_now, - order_status: "Delivered", - }, - }, - { - $group: { - _id: "$month", - total_income: { $sum: "$total" }, - }, - }, - { $sort: { _id: 1 } }, - ]); - for (let i = 0; i < statistics.length; i++) { - if (monthly.includes(statistics[i]._id)) { - var index = monthly.indexOf(statistics[i]._id); - monthly.splice(index, 1); - } - } - - var missing_statistics = []; - for (let i = 0; i < monthly.length; i++) { - missing_statistics.push({ - _id: monthly[i], - total_income: 0, - }); - } - var data = statistics.concat(missing_statistics); - data.sort((a, b) => a._id - b._id); - - data.sort((a, b) => { - return a._id - b._id; - }); - - return { - status: 200, - success: true, - element: { - msg: "Get monthly income successfully", - data, - }, - }; - } catch (err) { - return res.status(400).json({ - status: 400, - success: false, - msg: "Failed to get monthly income", - }); - } - }, - handleIncomeCustomerReceivedThisAndLastMonth: async () => { - const thisMonth = new Date().getMonth() + 1; - const lastMonth = new Date().getMonth(); - - try { - let data = await Payments.aggregate([ - { - $project: { - month: { $month: "$updatedAt" }, - order_status: 1, - total: 1, - }, - }, - { - $match: { - month: { $in: [lastMonth, thisMonth] }, - order_status: "Delivered", - }, - }, - { - $group: { - _id: { - month: "$month", - }, - total_income: { $sum: "$total" }, - }, - }, - { $sort: { _id: -1 } }, - ]); - - if (data.length === 0) { - return { - status: 400, - success: false, - msg: "Not data to show", - }; - } else if (data.length === 1) { - if (data[0]._id.month === thisMonth) { - data = [ - { - _id: { - month: "This month", - }, - total_income: data[0].total_income, - }, - { - _id: { - month: "Last month", - }, - total_income: 0, - }, - { - compared: "Increased", - value: data[0].total_income * 100, - }, - ]; - - return { - status: 200, - success: true, - element: { - msg: "Get income of orders customer have received this and last month successfully", - data, - }, - }; - } else if (data[0]._id.month === lastMonth) { - data = [ - { - _id: { - month: "This month", - }, - total_income: 0, - }, - { - _id: { - month: "Last month", - }, - total_income: data[0].total_income, - }, - { - compared: "Decreased", - value: -100, - }, - ]; - return { - status: 200, - success: true, - element: { - msg: "Get income of orders customer have received this and last month successfully", - data, - }, - }; - } - } else if (data.length === 2) { - (data[0]._id.month = "This month"), (data[1]._id.month = "Last month"); - - const value = ( - ((data[0].total_income - data[1].total_income) / - data[1].total_income) * - 100 - ).toFixed(1); - - const compared = value >= 0 ? "Increased" : "Decreased"; - - const compareToLastMonth = { - compared, - value, - }; - - data.push(compareToLastMonth); - - return { - status: 200, - success: true, - element: { - msg: "Get income of orders customer have received this and last month successfully", - data, - }, - }; - } - } catch (error) { - return { - status: 400, - success: false, - element: { - msg: "Server busy!", - }, - }; - } - }, - handleIncomeCustomerNotReceivedThisAndLastMonth: async (req, res) => { - const thisMonth = new Date().getMonth() + 1; - const lastMonth = new Date().getMonth(); - - try { - let data = await Payments.aggregate([ - { - $project: { - month: { $month: "$updatedAt" }, - order_status: 1, - total: 1, - }, - }, - { - $match: { - month: { $in: [lastMonth, thisMonth] }, - order_status: { $in: ["Ordered", "On Delivery"] }, - }, - }, - { - $group: { - _id: { - month: "$month", - }, - total_income: { $sum: "$total" }, - }, - }, - { $sort: { _id: -1 } }, - ]); - - if (data.length === 0) { - return { - status: 400, - success: false, - element: { - msg: "Not data to show", - }, - }; - } else if (data.length === 1) { - if (data[0]._id.month === thisMonth) { - data = [ - { - _id: { - month: "This month", - }, - total_income: data[0].total_income, - }, - { - _id: { - month: "Last month", - }, - total_income: 0, - }, - { - compared: "Increased", - value: data[0].total_income * 100, - }, - ]; - - return { - status: 200, - success: true, - element: { - msg: "Get income of orders customer have not received this and last month successfully", - data, - }, - }; - } else if (data[0]._id.month === lastMonth) { - data = [ - { - _id: { - month: "This month", - }, - total_income: 0, - }, - { - _id: { - month: "Last month", - }, - total_income: data[0].total_income, - }, - { - compared: "Decreased", - value: -100, - }, - ]; - return { - status: 200, - success: true, - element: { - msg: "Get income of orders customer have not received this and last month successfully", - data, - }, - }; - } - } else if (data.length === 2) { - (data[0]._id.month = "This month"), (data[1]._id.month = "Last month"); - - const value = ( - ((data[0].total_income - data[1].total_income) / - data[1].total_income) * - 100 - ).toFixed(1); - - const compared = value >= 0 ? "Increased" : "Decreased"; - - const compareToLastMonth = { - compared, - value, - }; - - data.push(compareToLastMonth); - - return res.status(200).json({ - status: 200, - success: true, - element: { - msg: "Get income of orders customer have not received this and last month successfully", - data, - }, - }); - } - } catch (error) { - return { - status: 400, - success: false, - element: { - msg: "Server busy!", - }, - }; - } - }, -}; -const GetDayNewUserBuy = (d1, d2) => { - let value1 = d1.getTime(); - let value2 = d2.getTime(); - return Math.ceil((value2 - value1) / CONSTANTS._1_DAY); -}; +const Payments = require("../../../models/PaymentModel"); +const CONSTANTS = require("../../../configs/constants"); +module.exports = { + handleGetSumInCome: async () => { + try { + const data = await Payments.aggregate([ + { + $group: { + _id: "sum_of_income", + total: { $sum: "$total" }, + }, + }, + ]); + + return { + status: 200, + success: true, + element: { + msg: "Get sum of income successfully", + data, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Get sum of income fail", + }, + }; + } + }, + handleGetUserBuy3days: async () => { + try { + let payments = await Payments.find({ + deleteAt: CONSTANTS.DELETED_DISABLE, + }) + .populate("user_id") + .sort({ createdAt: -1 }); + var today = new Date(); + var result = []; + for (var i = 0; i < payments.length; i++) { + var time = GetDayNewUserBuy(payments[i].createdAt, today); + if (time <= 3) { + result.push(payments[i]); + } + } + if (result.length === 0) { + return { + status: 200, + success: true, + element: { + msg: "No Account New !!", + result, + }, + }; + } else { + return { + status: 200, + success: true, + element: { + total: result.length, + msg: "Get New User Buy Successfully !!", + result, + }, + }; + } + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Get sum of income fail", + }, + }; + } + }, + handleMonthlyIncomeCustomerReceived: async () => { + const monthly = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + const year_now = new Date().getFullYear(); + + try { + let statistics = await Payments.aggregate([ + { + $project: { + month: { $month: "$updatedAt" }, + year: { $year: "$updatedAt" }, + order_status: 1, + total: 1, + }, + }, + { + $match: { + month: { $in: monthly }, + year: year_now, + order_status: "Delivered", + }, + }, + { + $group: { + _id: "$month", + total_income: { $sum: "$total" }, + }, + }, + { $sort: { _id: 1 } }, + ]); + for (let i = 0; i < statistics.length; i++) { + if (monthly.includes(statistics[i]._id)) { + var index = monthly.indexOf(statistics[i]._id); + monthly.splice(index, 1); + } + } + + var missing_statistics = []; + for (let i = 0; i < monthly.length; i++) { + missing_statistics.push({ + _id: monthly[i], + total_income: 0, + }); + } + var data = statistics.concat(missing_statistics); + data.sort((a, b) => a._id - b._id); + + data.sort((a, b) => { + return a._id - b._id; + }); + + return { + status: 200, + success: true, + element: { + msg: "Get monthly income successfully", + data, + }, + }; + } catch (err) { + return res.status(400).json({ + status: 400, + success: false, + msg: "Failed to get monthly income", + }); + } + }, + handleIncomeCustomerReceivedThisAndLastMonth: async () => { + const thisMonth = new Date().getMonth() + 1; + const lastMonth = new Date().getMonth(); + + try { + let data = await Payments.aggregate([ + { + $project: { + month: { $month: "$updatedAt" }, + order_status: 1, + total: 1, + }, + }, + { + $match: { + month: { $in: [lastMonth, thisMonth] }, + order_status: "Delivered", + }, + }, + { + $group: { + _id: { + month: "$month", + }, + total_income: { $sum: "$total" }, + }, + }, + { $sort: { _id: -1 } }, + ]); + + if (data.length === 0) { + return { + status: 400, + success: false, + msg: "Not data to show", + }; + } else if (data.length === 1) { + if (data[0]._id.month === thisMonth) { + data = [ + { + _id: { + month: "This month", + }, + total_income: data[0].total_income, + }, + { + _id: { + month: "Last month", + }, + total_income: 0, + }, + { + compared: "Increased", + value: data[0].total_income * 100, + }, + ]; + + return { + status: 200, + success: true, + element: { + msg: "Get income of orders customer have received this and last month successfully", + data, + }, + }; + } else if (data[0]._id.month === lastMonth) { + data = [ + { + _id: { + month: "This month", + }, + total_income: 0, + }, + { + _id: { + month: "Last month", + }, + total_income: data[0].total_income, + }, + { + compared: "Decreased", + value: -100, + }, + ]; + return { + status: 200, + success: true, + element: { + msg: "Get income of orders customer have received this and last month successfully", + data, + }, + }; + } + } else if (data.length === 2) { + (data[0]._id.month = "This month"), (data[1]._id.month = "Last month"); + + const value = ( + ((data[0].total_income - data[1].total_income) / + data[1].total_income) * + 100 + ).toFixed(1); + + const compared = value >= 0 ? "Increased" : "Decreased"; + + const compareToLastMonth = { + compared, + value, + }; + + data.push(compareToLastMonth); + + return { + status: 200, + success: true, + element: { + msg: "Get income of orders customer have received this and last month successfully", + data, + }, + }; + } + } catch (error) { + return { + status: 400, + success: false, + element: { + msg: "Server busy!", + }, + }; + } + }, + handleIncomeCustomerNotReceivedThisAndLastMonth: async (req, res) => { + const thisMonth = new Date().getMonth() + 1; + const lastMonth = new Date().getMonth(); + + try { + let data = await Payments.aggregate([ + { + $project: { + month: { $month: "$updatedAt" }, + order_status: 1, + total: 1, + }, + }, + { + $match: { + month: { $in: [lastMonth, thisMonth] }, + order_status: { $in: ["Ordered", "On Delivery"] }, + }, + }, + { + $group: { + _id: { + month: "$month", + }, + total_income: { $sum: "$total" }, + }, + }, + { $sort: { _id: -1 } }, + ]); + + if (data.length === 0) { + return { + status: 400, + success: false, + element: { + msg: "Not data to show", + }, + }; + } else if (data.length === 1) { + if (data[0]._id.month === thisMonth) { + data = [ + { + _id: { + month: "This month", + }, + total_income: data[0].total_income, + }, + { + _id: { + month: "Last month", + }, + total_income: 0, + }, + { + compared: "Increased", + value: data[0].total_income * 100, + }, + ]; + + return { + status: 200, + success: true, + element: { + msg: "Get income of orders customer have not received this and last month successfully", + data, + }, + }; + } else if (data[0]._id.month === lastMonth) { + data = [ + { + _id: { + month: "This month", + }, + total_income: 0, + }, + { + _id: { + month: "Last month", + }, + total_income: data[0].total_income, + }, + { + compared: "Decreased", + value: -100, + }, + ]; + return { + status: 200, + success: true, + element: { + msg: "Get income of orders customer have not received this and last month successfully", + data, + }, + }; + } + } else if (data.length === 2) { + (data[0]._id.month = "This month"), (data[1]._id.month = "Last month"); + + const value = ( + ((data[0].total_income - data[1].total_income) / + data[1].total_income) * + 100 + ).toFixed(1); + + const compared = value >= 0 ? "Increased" : "Decreased"; + + const compareToLastMonth = { + compared, + value, + }; + + data.push(compareToLastMonth); + + return res.status(200).json({ + status: 200, + success: true, + element: { + msg: "Get income of orders customer have not received this and last month successfully", + data, + }, + }); + } + } catch (error) { + return { + status: 400, + success: false, + element: { + msg: "Server busy!", + }, + }; + } + }, +}; +const GetDayNewUserBuy = (d1, d2) => { + let value1 = d1.getTime(); + let value2 = d2.getTime(); + return Math.ceil((value2 - value1) / CONSTANTS._1_DAY); +}; diff --git a/backend/src/v1/admin_api/services/voucher_admin/curd_voucher.service.js b/backend/src/v1/admin_api/services/voucher_admin/curd_voucher.service.js index 7549840..7a13cd0 100644 --- a/backend/src/v1/admin_api/services/voucher_admin/curd_voucher.service.js +++ b/backend/src/v1/admin_api/services/voucher_admin/curd_voucher.service.js @@ -1,34 +1,34 @@ -const Vouchers = require("../../../models/VoucherModel"); -const getAllVoucher = async () => { - return await Vouchers.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); -}; -const createVoucher = async (title, value) => { - const newVoucher = new Vouchers({ title, value }); - await newVoucher.save(); -}; -const updateVoucher = async (voucher_id, title, value) => { - await Vouchers.findOneAndUpdate({ _id: voucher_id }, { title, value }); -}; -const delVoucher = async (voucher_id) => { - await Vouchers.findByIdAndDelete(voucher_id); -}; -module.exports = { - getAllVoucher, - createVoucher, - updateVoucher, - delVoucher, -}; +const Vouchers = require("../../../models/VoucherModel"); +const getAllVoucher = async () => { + return await Vouchers.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); +}; +const createVoucher = async (title, value) => { + const newVoucher = new Vouchers({ title, value }); + await newVoucher.save(); +}; +const updateVoucher = async (voucher_id, title, value) => { + await Vouchers.findOneAndUpdate({ _id: voucher_id }, { title, value }); +}; +const delVoucher = async (voucher_id) => { + await Vouchers.findByIdAndDelete(voucher_id); +}; +module.exports = { + getAllVoucher, + createVoucher, + updateVoucher, + delVoucher, +}; diff --git a/backend/src/v1/admin_api/services/voucher_admin/voucher.service.js b/backend/src/v1/admin_api/services/voucher_admin/voucher.service.js index b9b0f3d..2af998b 100644 --- a/backend/src/v1/admin_api/services/voucher_admin/voucher.service.js +++ b/backend/src/v1/admin_api/services/voucher_admin/voucher.service.js @@ -1,130 +1,130 @@ -const { - getAllVoucher, - createVoucher, - updateVoucher, - delVoucher, -} = require("./curd_voucher.service"); -const STORAGE = require("../../../utils/storage"); -module.exports = { - handleGetallVoucher: async () => { - try { - const voucher = await getAllVoucher(); - if (voucher.length === 0) { - return { - status: 200, - success: true, - element: { - msg: "Voucher Empty !!", - }, - }; - } - return { - status: 200, - success: true, - element: { - voucher, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Busy", - }, - }; - } - }, - handleCreateVoucher: async ({ title, value }) => { - try { - const check_exit = await STORAGE.checkVoucherExit(title); - if (check_exit.length > 0) { - return { - status: 400, - success: false, - element: { - msg: "Voucher Exit !!", - }, - }; - } - await createVoucher(title, value); - return { - status: 200, - success: true, - element: { - msg: "Voucher create Success !!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Busy", - }, - }; - } - }, - handleUpdateVoucher: async ({ voucher_id, title, value }) => { - try { - const check_exit = await STORAGE.checkVoucherExitExceptUserMain( - voucher_id, - title - ); - if (check_exit.length > 0) { - return { - status: 400, - success: false, - element: { - msg: "Voucher Exit !!", - }, - }; - } - await updateVoucher(voucher_id, title, value); - return { - status: 200, - success: true, - element: { - msg: "Voucher update Success !!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Busy", - }, - }; - } - }, - handleDeleteVoucher: async ({ voucher_id }) => { - try { - if (!voucher_id) { - return { - status: 400, - success: false, - element: { - msg: "server Fail !!", - }, - }; - } - await delVoucher(voucher_id); - return { - status: 200, - success: true, - element: { - msg: "Voucher Delete Success !!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server Busy", - }, - }; - } - }, -}; +const { + getAllVoucher, + createVoucher, + updateVoucher, + delVoucher, +} = require("./curd_voucher.service"); +const STORAGE = require("../../../utils/storage"); +module.exports = { + handleGetallVoucher: async () => { + try { + const voucher = await getAllVoucher(); + if (voucher.length === 0) { + return { + status: 200, + success: true, + element: { + msg: "Voucher Empty !!", + }, + }; + } + return { + status: 200, + success: true, + element: { + voucher, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Busy", + }, + }; + } + }, + handleCreateVoucher: async ({ title, value }) => { + try { + const check_exit = await STORAGE.checkVoucherExit(title); + if (check_exit.length > 0) { + return { + status: 400, + success: false, + element: { + msg: "Voucher Exit !!", + }, + }; + } + await createVoucher(title, value); + return { + status: 200, + success: true, + element: { + msg: "Voucher create Success !!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Busy", + }, + }; + } + }, + handleUpdateVoucher: async ({ voucher_id, title, value }) => { + try { + const check_exit = await STORAGE.checkVoucherExitExceptUserMain( + voucher_id, + title + ); + if (check_exit.length > 0) { + return { + status: 400, + success: false, + element: { + msg: "Voucher Exit !!", + }, + }; + } + await updateVoucher(voucher_id, title, value); + return { + status: 200, + success: true, + element: { + msg: "Voucher update Success !!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Busy", + }, + }; + } + }, + handleDeleteVoucher: async ({ voucher_id }) => { + try { + if (!voucher_id) { + return { + status: 400, + success: false, + element: { + msg: "server Fail !!", + }, + }; + } + await delVoucher(voucher_id); + return { + status: 200, + success: true, + element: { + msg: "Voucher Delete Success !!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server Busy", + }, + }; + } + }, +}; diff --git a/backend/src/v1/configs/config.js b/backend/src/v1/configs/config.js index a202fde..ed3d27d 100644 --- a/backend/src/v1/configs/config.js +++ b/backend/src/v1/configs/config.js @@ -1,81 +1,81 @@ -module.exports = { - /** - * * Environment Settings - */ - NODE_ENV: process.env.NODE_ENV, - PORT_FRONTEND_ENV: process.env.FRONTEND_URL, - /** - * * SMTP Settings - */ - SMTP_HOST: process.env.SMPT_HOST, - SMTP_PORT: process.env.SMPT_PORT, - SMTP_SERVICE: process.env.SMPT_SERVICE, - SMTP_MAIL: process.env.SMPT_MAIL, - SMTP_PASSWORD: process.env.SMPT_PASSWORD, - - /** - * * JWT Settings - */ - JWT_SECRET: process.env.JWT_SECRET, - JWT_EXPIRE: process.env.JWT_EXPIRE, - JWT_KEY: process.env.JWT_KEY, - - /** - * * DATABASE Settings - */ - MONGO_DB: process.env.MONGODB_URL, - - /** - * * Redis caching Settings - */ - REDIS_PORT: process.env.REDIS_PORT, - REDIS_HOST: process.env.REDIS_HOST, - REDIS_USER: process.env.REDIS_USER, - REDIS_PASSWORD: process.env.REDIS_PASSWORD, - /** - * * rabbit_mq caching Settings - */ - RABBIT_MQ: process.env.RABBIT_MQ, - - /** - * * Cloudinary settings - */ - CLOUD_API_KEY: process.env.CLOUD_API_KEY, - CLOUD_API_SECRET: process.env.CLOUD_API_SECRET, - CLOUD_NAME: process.env.CLOUD_NAME, - - /** - * * Key token Settings - */ - REFRESH_TOKEN_SECRET: process.env.REFRESH_TOKEN_SECRET, - ACCESS_TOKEN_SECRET: process.env.ACCESS_TOKEN_SECRET, - - /** - * * Recaptcha Settings - */ - RECAPTCHA_SECRET_KEY: process.env.RECAPTCHA_SECRET_KEY, - - /** - * * Stripe Settings - */ - STRIPE_KEY: process.env.STRIPE_KEY, - STRIPE_PUBLIC: process.env.STRIPE_PUBLIC, - - /** - * * Stripe Settings - */ - GOOGLE_CLIENT_IDS: process.env.GOOGLE_CLIENT_IDS, - - /** - * * Setup rate limit - */ - IPA_API_RATE_LIMIT_DURATION: process.env.IPA_API_RATE_LIMIT_DURATION, - IPA_API_RATE_LIMIT: process.env.IPA_API_RATE_LIMIT, - - /** - * * Algolia setting - */ - APP_ID_ALGOLIA: process.env.APP_ID_ALGOLIA, - ADMIN_KEY_ALGOLIA: process.env.ADMIN_KEY_ALGOLIA, - USER_KEY_ALGOLIA: process.env.USER_KEY_ALGOLIA -}; +module.exports = { + /** + * * Environment Settings + */ + NODE_ENV: process.env.NODE_ENV, + PORT_FRONTEND_ENV: process.env.FRONTEND_URL, + /** + * * SMTP Settings + */ + SMTP_HOST: process.env.SMPT_HOST, + SMTP_PORT: process.env.SMPT_PORT, + SMTP_SERVICE: process.env.SMPT_SERVICE, + SMTP_MAIL: process.env.SMPT_MAIL, + SMTP_PASSWORD: process.env.SMPT_PASSWORD, + + /** + * * JWT Settings + */ + JWT_SECRET: process.env.JWT_SECRET, + JWT_EXPIRE: process.env.JWT_EXPIRE, + JWT_KEY: process.env.JWT_KEY, + + /** + * * DATABASE Settings + */ + MONGO_DB: process.env.MONGODB_URL, + + /** + * * Redis caching Settings + */ + REDIS_PORT: process.env.REDIS_PORT, + REDIS_HOST: process.env.REDIS_HOST, + REDIS_USER: process.env.REDIS_USER, + REDIS_PASSWORD: process.env.REDIS_PASSWORD, + /** + * * rabbit_mq caching Settings + */ + RABBIT_MQ: process.env.RABBIT_MQ, + + /** + * * Cloudinary settings + */ + CLOUD_API_KEY: process.env.CLOUD_API_KEY, + CLOUD_API_SECRET: process.env.CLOUD_API_SECRET, + CLOUD_NAME: process.env.CLOUD_NAME, + + /** + * * Key token Settings + */ + REFRESH_TOKEN_SECRET: process.env.REFRESH_TOKEN_SECRET, + ACCESS_TOKEN_SECRET: process.env.ACCESS_TOKEN_SECRET, + + /** + * * Recaptcha Settings + */ + RECAPTCHA_SECRET_KEY: process.env.RECAPTCHA_SECRET_KEY, + + /** + * * Stripe Settings + */ + STRIPE_KEY: process.env.STRIPE_KEY, + STRIPE_PUBLIC: process.env.STRIPE_PUBLIC, + + /** + * * Stripe Settings + */ + GOOGLE_CLIENT_IDS: process.env.GOOGLE_CLIENT_IDS, + + /** + * * Setup rate limit + */ + IPA_API_RATE_LIMIT_DURATION: process.env.IPA_API_RATE_LIMIT_DURATION, + IPA_API_RATE_LIMIT: process.env.IPA_API_RATE_LIMIT, + + /** + * * Algolia setting + */ + APP_ID_ALGOLIA: process.env.APP_ID_ALGOLIA, + ADMIN_KEY_ALGOLIA: process.env.ADMIN_KEY_ALGOLIA, + USER_KEY_ALGOLIA: process.env.USER_KEY_ALGOLIA +}; diff --git a/backend/src/v1/configs/constants.js b/backend/src/v1/configs/constants.js index 0fa737e..8f25b70 100644 --- a/backend/src/v1/configs/constants.js +++ b/backend/src/v1/configs/constants.js @@ -1,77 +1,77 @@ -module.exports = { - //! milisecond / second - _30_MILLISECOND: 30 * 1000, - _1_MINUTES: 60 * 1000, - _5_MINUTES: 5 * 60 * 1000, - _15_MINUTES: 15 * 60 * 1000, - _45_MINUTES: 45 * 60 * 1000, - _1_DAY: 24 * 60 * 60 * 1000, - _7_DAY: 7 * 24 * 60 * 60 * 1000, - _1_DAY_S: 24 * 60 * 60, - _1_HOURS_S: 60 * 60, - _1_YEAR: 365 * 24 * 60 * 60 * 1000, - - //! Time Redis - _1_MINUTES_REDIS: 100, - _15_MINUTES_REDIS: 100 * 15, - _1_HOURS_REDIS: 4500, - _1_DAYS_REDIS: 108000, - _7_DAYS_REDIS: 6 * 108000, - - _DEFAULT_CACHE_TIME: 15, - - //!Delete Flag - DELETED_ENABLE: true, - DELETED_DISABLE: false, - - //! Role Number - ACCOUNT_USER: 0, - ACCOUNT_ADMIN: 1, - - //! Bcrypt setting - SALT_ROUNDS: 10, - - //! Reset Token - CRYPTO_TOKEN: 20, - - //! EXPIRES_TOKEN - EXPIRES_ACCESS_TOKEN: process.env.EXPIRES_ACCESS_TOKEN, - EXPIRES_REFRESH_TOKEN: process.env.EXPIRES_REFRESH_TOKEN, - - //! KEY_SESSION - KEY_SESSION: process.env.KEY_SESSION, - - //! Algolia - NAME_INDEX_ALGOLIA: 'product_search', - - //! STATUS_CODE - STATUS_CODE_100: "Continue", - STATUS_CODE_101: "Switching Protocols", - STATUS_CODE_102: "Processing", - STATUS_CODE_103: "Early Hints", - STATUS_CODE_200: "Success", - STATUS_CODE_201: "Created Success", - STATUS_CODE_202: "Accepted", - STATUS_CODE_203: "Non-Authoritative Information", - STATUS_CODE_204: "No Content", - STATUS_CODE_302: "Phone is empty", - STATUS_CODE_305: "User not found", - STATUS_CODE_306: "Phone is not exists", - STATUS_CODE_307: "Email is not exists", - STATUS_CODE_308: "Invalid is empty", - STATUS_CODE_400: "Request not valid NotFound ", - STATUS_CODE_401: "Unauthorized Correct", - STATUS_CODE_403: "Wrong password", - STATUS_CODE_404: "Not Found", - STATUS_CODE_503: "Server Busy", - STATUS_CODE_DEFAULT: "No Code", - - //! Status account - STATUS_LOGIN_GOOGLE: "google", - STATUS_LOGIN_FACEBOOK: "facebook", - STATUS_LOGIN_PHONE: "phone", - STATUS_LOGIN_EMAIL: "email", - //! Connect Take Data - STORAGE_GRAPH_FACEBOOK: - "https://graph.facebook.com/v13.0/${userID}/?fields=picture.width(300).height(300),id,name,email&access_token=${accessToken}", -}; +module.exports = { + //! milisecond / second + _30_MILLISECOND: 30 * 1000, + _1_MINUTES: 60 * 1000, + _5_MINUTES: 5 * 60 * 1000, + _15_MINUTES: 15 * 60 * 1000, + _45_MINUTES: 45 * 60 * 1000, + _1_DAY: 24 * 60 * 60 * 1000, + _7_DAY: 7 * 24 * 60 * 60 * 1000, + _1_DAY_S: 24 * 60 * 60, + _1_HOURS_S: 60 * 60, + _1_YEAR: 365 * 24 * 60 * 60 * 1000, + + //! Time Redis + _1_MINUTES_REDIS: 100, + _15_MINUTES_REDIS: 100 * 15, + _1_HOURS_REDIS: 4500, + _1_DAYS_REDIS: 108000, + _7_DAYS_REDIS: 6 * 108000, + + _DEFAULT_CACHE_TIME: 15, + + //!Delete Flag + DELETED_ENABLE: true, + DELETED_DISABLE: false, + + //! Role Number + ACCOUNT_USER: 0, + ACCOUNT_ADMIN: 1, + + //! Bcrypt setting + SALT_ROUNDS: 10, + + //! Reset Token + CRYPTO_TOKEN: 20, + + //! EXPIRES_TOKEN + EXPIRES_ACCESS_TOKEN: process.env.EXPIRES_ACCESS_TOKEN, + EXPIRES_REFRESH_TOKEN: process.env.EXPIRES_REFRESH_TOKEN, + + //! KEY_SESSION + KEY_SESSION: process.env.KEY_SESSION, + + //! Algolia + NAME_INDEX_ALGOLIA: 'product_search', + + //! STATUS_CODE + STATUS_CODE_100: "Continue", + STATUS_CODE_101: "Switching Protocols", + STATUS_CODE_102: "Processing", + STATUS_CODE_103: "Early Hints", + STATUS_CODE_200: "Success", + STATUS_CODE_201: "Created Success", + STATUS_CODE_202: "Accepted", + STATUS_CODE_203: "Non-Authoritative Information", + STATUS_CODE_204: "No Content", + STATUS_CODE_302: "Phone is empty", + STATUS_CODE_305: "User not found", + STATUS_CODE_306: "Phone is not exists", + STATUS_CODE_307: "Email is not exists", + STATUS_CODE_308: "Invalid is empty", + STATUS_CODE_400: "Request not valid NotFound ", + STATUS_CODE_401: "Unauthorized Correct", + STATUS_CODE_403: "Wrong password", + STATUS_CODE_404: "Not Found", + STATUS_CODE_503: "Server Busy", + STATUS_CODE_DEFAULT: "No Code", + + //! Status account + STATUS_LOGIN_GOOGLE: "google", + STATUS_LOGIN_FACEBOOK: "facebook", + STATUS_LOGIN_PHONE: "phone", + STATUS_LOGIN_EMAIL: "email", + //! Connect Take Data + STORAGE_GRAPH_FACEBOOK: + "https://graph.facebook.com/v13.0/${userID}/?fields=picture.width(300).height(300),id,name,email&access_token=${accessToken}", +}; diff --git a/backend/src/v1/db/algolia_search.js b/backend/src/v1/db/algolia_search.js index 50cc8ce..4b96296 100644 --- a/backend/src/v1/db/algolia_search.js +++ b/backend/src/v1/db/algolia_search.js @@ -1,17 +1,17 @@ -const CONFIGS = require("../configs/config"); -const CONSTANTS = require("../configs/constants") -const db_algolia = { - appId: CONFIGS.APP_ID_ALGOLIA, - apiKey: CONFIGS.ADMIN_KEY_ALGOLIA, - indexName: CONSTANTS.NAME_INDEX_ALGOLIA, - selector: "-rating -_id", - populate: { - path: 'categories', - select: 'name -_id', - }, - filter: function(doc) { - return !doc.softdelete - }, -}; - +const CONFIGS = require("../configs/config"); +const CONSTANTS = require("../configs/constants") +const db_algolia = { + appId: CONFIGS.APP_ID_ALGOLIA, + apiKey: CONFIGS.ADMIN_KEY_ALGOLIA, + indexName: CONSTANTS.NAME_INDEX_ALGOLIA, + selector: "-rating -_id", + populate: { + path: 'categories', + select: 'name -_id', + }, + filter: function(doc) { + return !doc.softdelete + }, +}; + module.exports = db_algolia; \ No newline at end of file diff --git a/backend/src/v1/db/cloudinary_db.js b/backend/src/v1/db/cloudinary_db.js index 9063331..55953ee 100644 --- a/backend/src/v1/db/cloudinary_db.js +++ b/backend/src/v1/db/cloudinary_db.js @@ -1,8 +1,8 @@ -const cloudinary = require("cloudinary"); -const CONFIGS = require("../configs/config"); -cloudinary.config({ - cloud_name: CONFIGS.CLOUD_NAME, - api_key: CONFIGS.CLOUD_API_KEY, - api_secret: CONFIGS.CLOUD_API_SECRET, -}); -module.exports = cloudinary; +const cloudinary = require("cloudinary"); +const CONFIGS = require("../configs/config"); +cloudinary.config({ + cloud_name: CONFIGS.CLOUD_NAME, + api_key: CONFIGS.CLOUD_API_KEY, + api_secret: CONFIGS.CLOUD_API_SECRET, +}); +module.exports = cloudinary; diff --git a/backend/src/v1/db/mongo_db.js b/backend/src/v1/db/mongo_db.js index 68c7183..6326e90 100644 --- a/backend/src/v1/db/mongo_db.js +++ b/backend/src/v1/db/mongo_db.js @@ -1,17 +1,17 @@ -require("dotenv").config({ path: __dirname + "../../../../../.env" }); -const mongoose = require("mongoose"); -const CONFIGS = require("../configs/config"); -const connectDB = async () => { - try { - await mongoose.connect(CONFIGS.MONGO_DB, { - useNewUrlParser: true, - useUnifiedTopology: true, - }); - console.log("MongoDB connection SUCCESS"); - } catch (error) { - console.log(error); - console.error("MongoDB connection FAIL"); - process.exit(1); - } -}; -module.exports = connectDB; +require("dotenv").config({ path: __dirname + "../../../../../.env" }); +const mongoose = require("mongoose"); +const CONFIGS = require("../configs/config"); +const connectDB = async () => { + try { + await mongoose.connect(CONFIGS.MONGO_DB, { + useNewUrlParser: true, + useUnifiedTopology: true, + }); + console.log("MongoDB connection SUCCESS"); + } catch (error) { + console.log(error); + console.error("MongoDB connection FAIL"); + process.exit(1); + } +}; +module.exports = connectDB; diff --git a/backend/src/v1/db/rabbitmq.js b/backend/src/v1/db/rabbitmq.js index 53cbad9..0767141 100644 --- a/backend/src/v1/db/rabbitmq.js +++ b/backend/src/v1/db/rabbitmq.js @@ -1,19 +1,19 @@ -// var amqp = require("amqplib"); -// require("dotenv").config({ path: __dirname + "../../../../../.env" }); -// const CONFIGS = require("../configs/config"); -// var connection, channel; - -// const connect_amqp = async () => { -// connection = await amqp.connect(CONFIGS.RABBIT_MQ); -// channel = await connection.createChannel(); -// await channel.assertQueue("BUY_PRODUCT"); -// }; -// connect_amqp().then(() => { -// channel.consume("ORDER_PRODUCT", (data) => { -// console.log( -// "Co nguoi mua hang roi anh em:::", -// JSON.stringify(data.content) -// ); -// }); -// }); -// module.exports = connect_amqp; +// var amqp = require("amqplib"); +// require("dotenv").config({ path: __dirname + "../../../../../.env" }); +// const CONFIGS = require("../configs/config"); +// var connection, channel; + +// const connect_amqp = async () => { +// connection = await amqp.connect(CONFIGS.RABBIT_MQ); +// channel = await connection.createChannel(); +// await channel.assertQueue("BUY_PRODUCT"); +// }; +// connect_amqp().then(() => { +// channel.consume("ORDER_PRODUCT", (data) => { +// console.log( +// "Co nguoi mua hang roi anh em:::", +// JSON.stringify(data.content) +// ); +// }); +// }); +// module.exports = connect_amqp; diff --git a/backend/src/v1/db/redis_db.js b/backend/src/v1/db/redis_db.js index 46e9049..50daa28 100644 --- a/backend/src/v1/db/redis_db.js +++ b/backend/src/v1/db/redis_db.js @@ -1,32 +1,32 @@ -const IOREDIS = require("ioredis"); -require("dotenv").config({ path: __dirname + "../../../../../.env" }); -const CONFIGS = require("../configs/config"); -// const REDIS = new IOREDIS({ -// port: CONFIGS.REDIS_PORT, -// host: CONFIGS.REDIS_HOST, -// }); -const REDIS = new IOREDIS({ - port: CONFIGS.REDIS_PORT, - host: CONFIGS.REDIS_HOST, - user: CONFIGS.REDIS_USER, - password: CONFIGS.REDIS_PASSWORD, -}); - -REDIS.on("connect", () => { - // console.log("----------", CONFIGS); - console.log("Client connected to redis Push..."); -}); -REDIS.on("ready", () => { - console.log("Client connected to redis push and ready to use..."); -}); -REDIS.on("error", (error) => { - console.log("fail"); -}); -REDIS.on("end", () => { - console.log("Client disconnected from redis push"); -}); -REDIS.on("SIGINT", () => { - REDIS.quit(); -}); - -module.exports = REDIS; +const IOREDIS = require("ioredis"); +require("dotenv").config({ path: __dirname + "../../../../../.env" }); +const CONFIGS = require("../configs/config"); +// const REDIS = new IOREDIS({ +// port: CONFIGS.REDIS_PORT, +// host: CONFIGS.REDIS_HOST, +// }); +const REDIS = new IOREDIS({ + port: CONFIGS.REDIS_PORT, + host: CONFIGS.REDIS_HOST, + user: CONFIGS.REDIS_USER, + password: CONFIGS.REDIS_PASSWORD, +}); + +REDIS.on("connect", () => { + // console.log("----------", CONFIGS); + console.log("Client connected to redis Push..."); +}); +REDIS.on("ready", () => { + console.log("Client connected to redis push and ready to use..."); +}); +REDIS.on("error", (error) => { + console.log("fail"); +}); +REDIS.on("end", () => { + console.log("Client disconnected from redis push"); +}); +REDIS.on("SIGINT", () => { + REDIS.quit(); +}); + +module.exports = REDIS; diff --git a/backend/src/v1/middlewares/VerificationAdmin.js b/backend/src/v1/middlewares/VerificationAdmin.js index 59fc6c3..5f11fa0 100644 --- a/backend/src/v1/middlewares/VerificationAdmin.js +++ b/backend/src/v1/middlewares/VerificationAdmin.js @@ -1,28 +1,28 @@ -const Users = require("../models/userModel"); -const authAdmin = async (req, res, next) => { - try { - const user = await Users.findOne({ - _id: req.user.id, - }); - if (user.role === 0) { - return res.status(401).json({ - status: 401, - success: false, - element: { - msg: "Admin resources access denied", - }, - }); - } - next(); - } catch (err) { - return res.status(503).json({ - status: 401, - success: false, - element: { - msg: "Your session is not valid.", - }, - }); - } -}; - -module.exports = authAdmin; +const Users = require("../models/userModel"); +const authAdmin = async (req, res, next) => { + try { + const user = await Users.findOne({ + _id: req.user.id, + }); + if (user.role === 0) { + return res.status(401).json({ + status: 401, + success: false, + element: { + msg: "Admin resources access denied", + }, + }); + } + next(); + } catch (err) { + return res.status(503).json({ + status: 401, + success: false, + element: { + msg: "Your session is not valid.", + }, + }); + } +}; + +module.exports = authAdmin; diff --git a/backend/src/v1/middlewares/VerifyAcceptToken.middleware.js b/backend/src/v1/middlewares/VerifyAcceptToken.middleware.js index d5221d8..226b18b 100644 --- a/backend/src/v1/middlewares/VerifyAcceptToken.middleware.js +++ b/backend/src/v1/middlewares/VerifyAcceptToken.middleware.js @@ -1,29 +1,29 @@ -const HELPER = require("../utils/helper"); -const VerifyAcceptToken = async (req, res, next) => { - try { - const token = req.headers.authorization.split(" ")[1]; - let now = new Date(); - const decoded = HELPER.VerifyAccToken(token); - if (decoded.exp < now.getTime() / 1000) { - return res.status(401).json({ - status: 401, - success: false, - element: { - msg: "Expired Token", - }, - }); - } - req.user = decoded; - req.token = token; - next(); - } catch (error) { - return res.status(401).json({ - status: 401, - success: false, - element: { - message: "Your session is not valid.", - }, - }); - } -}; -module.exports = VerifyAcceptToken; +const HELPER = require("../utils/helper"); +const VerifyAcceptToken = async (req, res, next) => { + try { + const token = req.headers.authorization.split(" ")[1]; + let now = new Date(); + const decoded = HELPER.VerifyAccToken(token); + if (decoded.exp < now.getTime() / 1000) { + return res.status(401).json({ + status: 401, + success: false, + element: { + msg: "Expired Token", + }, + }); + } + req.user = decoded; + req.token = token; + next(); + } catch (error) { + return res.status(401).json({ + status: 401, + success: false, + element: { + message: "Your session is not valid.", + }, + }); + } +}; +module.exports = VerifyAcceptToken; diff --git a/backend/src/v1/middlewares/VerifyRefreshToken.middleware.js b/backend/src/v1/middlewares/VerifyRefreshToken.middleware.js index ecda899..5ace8a6 100644 --- a/backend/src/v1/middlewares/VerifyRefreshToken.middleware.js +++ b/backend/src/v1/middlewares/VerifyRefreshToken.middleware.js @@ -1,42 +1,42 @@ -const HELPER = require("../utils/helper"); -const { get } = require("../utils/limited_redis"); -const VerifyRefreshToken = async (req, res, next) => { - const token = req.cookies.refreshtoken; - if (!token) { - return res.status(401).json({ status: false, message: "Invalid request." }); - } - try { - var decoded = HELPER.VerifyRefreshToken(token); - req.user = decoded; - const refetch_user = await get(decoded.id); - if (refetch_user === null) { - return res.status(401).json({ - success: false, - status: false, - element: { - message: "Invalid request. Token is not in store.", - }, - }); - } - if (refetch_user != token) { - return res.status(401).json({ - status: 401, - success: false, - element: { - message: "Invalid request. Token is not same in store.", - }, - }); - } - next(); - } catch (error) { - return res.status(401).json({ - status: 401, - success: false, - element: { - message: "Your session is not valid.", - }, - }); - } -}; - -module.exports = VerifyRefreshToken; +const HELPER = require("../utils/helper"); +const { get } = require("../utils/limited_redis"); +const VerifyRefreshToken = async (req, res, next) => { + const token = req.cookies.refreshtoken; + if (!token) { + return res.status(401).json({ status: false, message: "Invalid request." }); + } + try { + var decoded = HELPER.VerifyRefreshToken(token); + req.user = decoded; + const refetch_user = await get(decoded.id); + if (refetch_user === null) { + return res.status(401).json({ + success: false, + status: false, + element: { + message: "Invalid request. Token is not in store.", + }, + }); + } + if (refetch_user != token) { + return res.status(401).json({ + status: 401, + success: false, + element: { + message: "Invalid request. Token is not same in store.", + }, + }); + } + next(); + } catch (error) { + return res.status(401).json({ + status: 401, + success: false, + element: { + message: "Your session is not valid.", + }, + }); + } +}; + +module.exports = VerifyRefreshToken; diff --git a/backend/src/v1/middlewares/handleError.js b/backend/src/v1/middlewares/handleError.js index 07e675e..ff99cec 100644 --- a/backend/src/v1/middlewares/handleError.js +++ b/backend/src/v1/middlewares/handleError.js @@ -1,6 +1,6 @@ -const { reasonPhraseCodeProNewMap } = require("../utils/storage"); -module.exports = { - returnReasons: (code) => { - return reasonPhraseCodeProNewMap().get(code); - }, -}; +const { reasonPhraseCodeProNewMap } = require("../utils/storage"); +module.exports = { + returnReasons: (code) => { + return reasonPhraseCodeProNewMap().get(code); + }, +}; diff --git a/backend/src/v1/middlewares/ratelimit.middleware.js b/backend/src/v1/middlewares/ratelimit.middleware.js index 14e19a3..9f3bd32 100644 --- a/backend/src/v1/middlewares/ratelimit.middleware.js +++ b/backend/src/v1/middlewares/ratelimit.middleware.js @@ -1,16 +1,16 @@ -const rateLimit = require('express-rate-limit') -const CONFIG = require('../configs/config') - -module.exports = rateLimit( - { - windowMs: CONFIG.IPA_API_RATE_LIMIT_DURATION * 1000, //in milliseconds - max: CONFIG.IPA_API_RATE_LIMIT, - message: { - status: 503, - success: false, - element: { - msg: 'You sent too many requests. Please wait a while then try again', - }, - }, - standardHeaders: true, +const rateLimit = require('express-rate-limit') +const CONFIG = require('../configs/config') + +module.exports = rateLimit( + { + windowMs: CONFIG.IPA_API_RATE_LIMIT_DURATION * 1000, //in milliseconds + max: CONFIG.IPA_API_RATE_LIMIT, + message: { + status: 503, + success: false, + element: { + msg: 'You sent too many requests. Please wait a while then try again', + }, + }, + standardHeaders: true, }) \ No newline at end of file diff --git a/backend/src/v1/models/CarouselModel.js b/backend/src/v1/models/CarouselModel.js index d6aa480..6194dd5 100644 --- a/backend/src/v1/models/CarouselModel.js +++ b/backend/src/v1/models/CarouselModel.js @@ -1,23 +1,23 @@ -const mongoose = require("mongoose"); - -const carouselSchema = new mongoose.Schema( - { - heading: { - type: String, - required: true, - }, - descriptions: { - type: String, - required: true, - }, - image: { - type: Object, - required: true, - }, - }, - { - timestamps: true, - } -); - -module.exports = mongoose.model("Carousel", carouselSchema); +const mongoose = require("mongoose"); + +const carouselSchema = new mongoose.Schema( + { + heading: { + type: String, + required: true, + }, + descriptions: { + type: String, + required: true, + }, + image: { + type: Object, + required: true, + }, + }, + { + timestamps: true, + } +); + +module.exports = mongoose.model("Carousel", carouselSchema); diff --git a/backend/src/v1/models/CategoryModel.js b/backend/src/v1/models/CategoryModel.js index 8257a55..9cd6c10 100644 --- a/backend/src/v1/models/CategoryModel.js +++ b/backend/src/v1/models/CategoryModel.js @@ -1,21 +1,21 @@ -const mongoose = require("mongoose"); - -const categorySchema = new mongoose.Schema( - { - name: { - type: String, - required: true, - trim: true, - unique: true, - }, - image: { - type: Object, - required: true, - }, - }, - { - timestamps: true, - } -); - -module.exports = mongoose.model("Category", categorySchema); +const mongoose = require("mongoose"); + +const categorySchema = new mongoose.Schema( + { + name: { + type: String, + required: true, + trim: true, + unique: true, + }, + image: { + type: Object, + required: true, + }, + }, + { + timestamps: true, + } +); + +module.exports = mongoose.model("Category", categorySchema); diff --git a/backend/src/v1/models/Otp.model.js b/backend/src/v1/models/Otp.model.js index 8bdcd31..c69252b 100644 --- a/backend/src/v1/models/Otp.model.js +++ b/backend/src/v1/models/Otp.model.js @@ -1,22 +1,22 @@ -const { Schema, model } = require("mongoose"); -const CONSTANTS = require("../configs/constants"); -const otpSchema = new Schema( - { - email: String, - otp: String, - //! 20 seconds expire - time: { - type: Date, - default: new Date(), - index: { expires: CONSTANTS._15_MINUTES }, - }, - }, - { - collection: "otp", - timestamps: true, - } -); - -module.exports = { - _Otp: model("otp", otpSchema), -}; +const { Schema, model } = require("mongoose"); +const CONSTANTS = require("../configs/constants"); +const otpSchema = new Schema( + { + email: String, + otp: String, + //! 20 seconds expire + time: { + type: Date, + default: new Date(), + index: { expires: CONSTANTS._15_MINUTES }, + }, + }, + { + collection: "otp", + timestamps: true, + } +); + +module.exports = { + _Otp: model("otp", otpSchema), +}; diff --git a/backend/src/v1/models/PaymentModel.js b/backend/src/v1/models/PaymentModel.js index 03ba1ce..c99661f 100644 --- a/backend/src/v1/models/PaymentModel.js +++ b/backend/src/v1/models/PaymentModel.js @@ -1,65 +1,65 @@ -const mongoose = require("mongoose"); - -const paymentSchema = new mongoose.Schema( - { - user_id: { - type: String, - ref: "User", - required: true, - }, - name: { - type: String, - required: true, - }, - email: { - type: String, - required: true, - }, - paymentID: { - type: String, - required: true, - }, - address: { - type: Object, - required: true, - }, - cart: { - type: Array, - default: [], - }, - cost: { - type: Number, - required: true, - }, - voucher: { - type: Number, - required: true, - }, - discount: { - type: Number, - required: true, - }, - total: { - type: Number, - required: true, - }, - status: { - type: Boolean, - default: false, - }, - order_status: { - type: String, - enum: ["Ordered", "On Delivery", "Delivered"], - default: "Ordered", - }, - deleteAt: { - type: Boolean, - default: false, - }, - }, - { - timestamps: true, - } -); - -module.exports = mongoose.model("Payments", paymentSchema); +const mongoose = require("mongoose"); + +const paymentSchema = new mongoose.Schema( + { + user_id: { + type: String, + ref: "User", + required: true, + }, + name: { + type: String, + required: true, + }, + email: { + type: String, + required: true, + }, + paymentID: { + type: String, + required: true, + }, + address: { + type: Object, + required: true, + }, + cart: { + type: Array, + default: [], + }, + cost: { + type: Number, + required: true, + }, + voucher: { + type: Number, + required: true, + }, + discount: { + type: Number, + required: true, + }, + total: { + type: Number, + required: true, + }, + status: { + type: Boolean, + default: false, + }, + order_status: { + type: String, + enum: ["Ordered", "On Delivery", "Delivered"], + default: "Ordered", + }, + deleteAt: { + type: Boolean, + default: false, + }, + }, + { + timestamps: true, + } +); + +module.exports = mongoose.model("Payments", paymentSchema); diff --git a/backend/src/v1/models/ProductModel.js b/backend/src/v1/models/ProductModel.js index 354d14a..f7c3dd8 100644 --- a/backend/src/v1/models/ProductModel.js +++ b/backend/src/v1/models/ProductModel.js @@ -1,86 +1,86 @@ -const mongoose = require("mongoose"); -const mongooseAlgolia = require('mongoose-algolia') -const db_algolia = require('../db/algolia_search') -const reviewSchema = mongoose.Schema( - { - rating: { type: Number, required: true }, - comment: { type: String, required: true }, - user: { - type: mongoose.Schema.Types.ObjectId, - required: true, - ref: "User", - }, - }, - { - timestamps: true, - } -); -const productSchema = new mongoose.Schema( - { - name: { - type: String, - required: true, - }, - image: { - type: Object, - required: true, - }, - description: { - type: String, - required: true, - }, - reviews: [reviewSchema], - rating: { - type: Number, - required: true, - default: 0, - }, - numReviews: { - type: Number, - required: true, - default: 0, - }, - price: { - type: Number, - required: true, - default: 0, - }, - countInStock: { - type: Number, - required: true, - default: 0, - }, - sold: { - type: Number, - default: 0, - }, - checked: { - type: Boolean, - default: false, - }, - categories: { - type: mongoose.Schema.Types.ObjectId, - ref: "Category", - required: true, - }, - createdAt: { - type: Date, - default: Date.now, - }, - updatedAt: { - type: Date, - default: Date.now, - }, - }, - { - timestamps: true, - } -); - -productSchema.plugin(mongooseAlgolia, db_algolia); -let productSchemas = mongoose.model("Product", productSchema); -productSchemas.SyncToAlgolia() -productSchemas.SetAlgoliaSettings({ - searchableAttributes: ['name', 'categories', 'price'] -}) -module.exports = productSchemas; +const mongoose = require("mongoose"); +const mongooseAlgolia = require('mongoose-algolia') +const db_algolia = require('../db/algolia_search') +const reviewSchema = mongoose.Schema( + { + rating: { type: Number, required: true }, + comment: { type: String, required: true }, + user: { + type: mongoose.Schema.Types.ObjectId, + required: true, + ref: "User", + }, + }, + { + timestamps: true, + } +); +const productSchema = new mongoose.Schema( + { + name: { + type: String, + required: true, + }, + image: { + type: Object, + required: true, + }, + description: { + type: String, + required: true, + }, + reviews: [reviewSchema], + rating: { + type: Number, + required: true, + default: 0, + }, + numReviews: { + type: Number, + required: true, + default: 0, + }, + price: { + type: Number, + required: true, + default: 0, + }, + countInStock: { + type: Number, + required: true, + default: 0, + }, + sold: { + type: Number, + default: 0, + }, + checked: { + type: Boolean, + default: false, + }, + categories: { + type: mongoose.Schema.Types.ObjectId, + ref: "Category", + required: true, + }, + createdAt: { + type: Date, + default: Date.now, + }, + updatedAt: { + type: Date, + default: Date.now, + }, + }, + { + timestamps: true, + } +); + +productSchema.plugin(mongooseAlgolia, db_algolia); +let productSchemas = mongoose.model("Product", productSchema); +productSchemas.SyncToAlgolia() +productSchemas.SetAlgoliaSettings({ + searchableAttributes: ['name', 'categories', 'price'] +}) +module.exports = productSchemas; diff --git a/backend/src/v1/models/VoucherModel.js b/backend/src/v1/models/VoucherModel.js index c724638..af978f0 100644 --- a/backend/src/v1/models/VoucherModel.js +++ b/backend/src/v1/models/VoucherModel.js @@ -1,20 +1,20 @@ -const mongoose = require("mongoose"); - -const voucherSchema = new mongoose.Schema( - { - title: { - type: String, - required: true, - unique: true, - }, - value: { - type: Number, - required: true, - }, - }, - { - timestamps: true, - } -); - -module.exports = mongoose.model("Voucher", voucherSchema); +const mongoose = require("mongoose"); + +const voucherSchema = new mongoose.Schema( + { + title: { + type: String, + required: true, + unique: true, + }, + value: { + type: Number, + required: true, + }, + }, + { + timestamps: true, + } +); + +module.exports = mongoose.model("Voucher", voucherSchema); diff --git a/backend/src/v1/models/feedBackModel.js b/backend/src/v1/models/feedBackModel.js index a9942d7..49e3e1d 100644 --- a/backend/src/v1/models/feedBackModel.js +++ b/backend/src/v1/models/feedBackModel.js @@ -1,46 +1,46 @@ -const mongoose = require("mongoose"); - -const FeedbackSchema = mongoose.Schema({ - fullname: { - type: String, - required: true, - trim: true, - }, - email: { - type: String, - required: true, - trim: true, - }, - subject: { - type: String, - required: true, - trim: true, - }, - content: { - type: String, - required: true, - trim: true, - }, - send_at: { - type: Date, - required: true, - }, - read_at: { - type: Date, - default: null, - }, - checked: { - type: Boolean, - default: false, - }, - createdAt: { - type: Date, - default: Date.now, - }, - updatedAt: { - type: Date, - default: Date.now, - }, -}); -FeedbackSchema.index({ fullname: "text", subject: "text", email: "text" }); -module.exports = mongoose.model("Feedback", FeedbackSchema); +const mongoose = require("mongoose"); + +const FeedbackSchema = mongoose.Schema({ + fullname: { + type: String, + required: true, + trim: true, + }, + email: { + type: String, + required: true, + trim: true, + }, + subject: { + type: String, + required: true, + trim: true, + }, + content: { + type: String, + required: true, + trim: true, + }, + send_at: { + type: Date, + required: true, + }, + read_at: { + type: Date, + default: null, + }, + checked: { + type: Boolean, + default: false, + }, + createdAt: { + type: Date, + default: Date.now, + }, + updatedAt: { + type: Date, + default: Date.now, + }, +}); +FeedbackSchema.index({ fullname: "text", subject: "text", email: "text" }); +module.exports = mongoose.model("Feedback", FeedbackSchema); diff --git a/backend/src/v1/models/userModel.js b/backend/src/v1/models/userModel.js index ea1686a..1cf285b 100644 --- a/backend/src/v1/models/userModel.js +++ b/backend/src/v1/models/userModel.js @@ -1,103 +1,103 @@ -const mongoose = require("mongoose"); -const crypto = require("crypto"); -const CONSTANTS = require("../configs/constants"); -const HELPER = require("../utils/helper"); -const UserSchema = new mongoose.Schema( - { - name: { - type: String, - required: false, - trim: true, - }, - email: { - type: String, - required: true, - unique: true, - }, - password: { - type: String, - required: true, - }, - role: { - type: Number, - default: 0, - }, - image: { - type: Object, - default: { - public_id: "2252005469", - url: "https://res.cloudinary.com/devatchannel/image/upload/v1602752402/avatar/avatar_cugq40.png", - }, - }, - cart: { - type: Array, - default: [], - }, - total_cart: { - type: Number, - default: 0, - }, - voucher: { - type: Number, - default: 0, - }, - discount: { - type: Number, - default: 0, - }, - phone_number: { - type: String, - default: "", - required: false, - trim: true, - }, - sex: { - type: Number, - required: false, - trim: true, - }, - checked: { - type: Boolean, - default: false, - }, - checkLogin: { - type: Boolean, - default: false, - }, - date_of_birth: { - type: String, - default: "", - required: false, - trim: true, - }, - verified: { - type: Boolean, - default: false, - }, - createdAt: { - type: Date, - default: Date.now, - }, - updatedAt: { - type: Date, - default: Date.now, - }, - resetPasswordToken: String, - resetPasswordExpire: Date, - }, - - { timestamps: true } -); -UserSchema.methods.getResetPasswordToken = function () { - //! tạo mã thông báo - const resetToken = HELPER.resetTokens(); - - //! Thêm resetPasswordToken vào userSchema - this.resetPasswordToken = HELPER.resetPasswordToken(resetToken); - - this.resetPasswordExpire = Date.now() + CONSTANTS._15_MINUTES; - - return resetToken; -}; - -module.exports = mongoose.model("User", UserSchema); +const mongoose = require("mongoose"); +const crypto = require("crypto"); +const CONSTANTS = require("../configs/constants"); +const HELPER = require("../utils/helper"); +const UserSchema = new mongoose.Schema( + { + name: { + type: String, + required: false, + trim: true, + }, + email: { + type: String, + required: true, + unique: true, + }, + password: { + type: String, + required: true, + }, + role: { + type: Number, + default: 0, + }, + image: { + type: Object, + default: { + public_id: "2252005469", + url: "https://res.cloudinary.com/devatchannel/image/upload/v1602752402/avatar/avatar_cugq40.png", + }, + }, + cart: { + type: Array, + default: [], + }, + total_cart: { + type: Number, + default: 0, + }, + voucher: { + type: Number, + default: 0, + }, + discount: { + type: Number, + default: 0, + }, + phone_number: { + type: String, + default: "", + required: false, + trim: true, + }, + sex: { + type: Number, + required: false, + trim: true, + }, + checked: { + type: Boolean, + default: false, + }, + checkLogin: { + type: Boolean, + default: false, + }, + date_of_birth: { + type: String, + default: "", + required: false, + trim: true, + }, + verified: { + type: Boolean, + default: false, + }, + createdAt: { + type: Date, + default: Date.now, + }, + updatedAt: { + type: Date, + default: Date.now, + }, + resetPasswordToken: String, + resetPasswordExpire: Date, + }, + + { timestamps: true } +); +UserSchema.methods.getResetPasswordToken = function () { + //! tạo mã thông báo + const resetToken = HELPER.resetTokens(); + + //! Thêm resetPasswordToken vào userSchema + this.resetPasswordToken = HELPER.resetPasswordToken(resetToken); + + this.resetPasswordExpire = Date.now() + CONSTANTS._15_MINUTES; + + return resetToken; +}; + +module.exports = mongoose.model("User", UserSchema); diff --git a/backend/src/v1/models/userVerificationModel.js b/backend/src/v1/models/userVerificationModel.js index a4b85b7..35e78fc 100644 --- a/backend/src/v1/models/userVerificationModel.js +++ b/backend/src/v1/models/userVerificationModel.js @@ -1,10 +1,10 @@ -const mongoose = require("mongoose"); - -const UserVertificationSchema = new mongoose.Schema({ - userId: String, - uniqueString: String, - createdAt: Date, - expiresAt: Date, -}); - -module.exports = mongoose.model("UserVerification", UserVertificationSchema); +const mongoose = require("mongoose"); + +const UserVertificationSchema = new mongoose.Schema({ + userId: String, + uniqueString: String, + createdAt: Date, + expiresAt: Date, +}); + +module.exports = mongoose.model("UserVerification", UserVertificationSchema); diff --git a/backend/src/v1/strategy_pattern/APIfeatures.js b/backend/src/v1/strategy_pattern/APIfeatures.js index a470b50..a6c0859 100644 --- a/backend/src/v1/strategy_pattern/APIfeatures.js +++ b/backend/src/v1/strategy_pattern/APIfeatures.js @@ -1,37 +1,37 @@ -module.exports = class APIfeatures { - constructor(query, queryString) { - this.query = query; - this.queryString = queryString; - } - filtering() { - const queryObj = { ...this.queryString }; //queryString = req.query - - const excludedFields = ["page", "sort", "limit"]; - excludedFields.forEach((el) => delete queryObj[el]); - - let queryStr = JSON.stringify(queryObj); - queryStr = queryStr.replace( - /\b(gte|gt|lt|lte|regex)\b/g, - (match) => "$" + match - ); - - // gte = greater than or equal - // lte = lesser than or equal - // lt = lesser than - // gt = greater than - this.query.find(JSON.parse(queryStr)); - - return this; - } - - sorting() { - if (this.queryString.sort) { - const sortBy = this.queryString.sort.split(",").join(" "); - this.query = this.query.sort(sortBy); - } else { - this.query = this.query.sort("-createdAt"); - } - - return this; - } -}; +module.exports = class APIfeatures { + constructor(query, queryString) { + this.query = query; + this.queryString = queryString; + } + filtering() { + const queryObj = { ...this.queryString }; //queryString = req.query + + const excludedFields = ["page", "sort", "limit"]; + excludedFields.forEach((el) => delete queryObj[el]); + + let queryStr = JSON.stringify(queryObj); + queryStr = queryStr.replace( + /\b(gte|gt|lt|lte|regex)\b/g, + (match) => "$" + match + ); + + // gte = greater than or equal + // lte = lesser than or equal + // lt = lesser than + // gt = greater than + this.query.find(JSON.parse(queryStr)); + + return this; + } + + sorting() { + if (this.queryString.sort) { + const sortBy = this.queryString.sort.split(",").join(" "); + this.query = this.query.sort(sortBy); + } else { + this.query = this.query.sort("-createdAt"); + } + + return this; + } +}; diff --git a/backend/src/v1/upload_cloudinary/controllers/upload.controllers.js b/backend/src/v1/upload_cloudinary/controllers/upload.controllers.js index 0df6b95..f135d98 100644 --- a/backend/src/v1/upload_cloudinary/controllers/upload.controllers.js +++ b/backend/src/v1/upload_cloudinary/controllers/upload.controllers.js @@ -1,41 +1,41 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { handleUpload, handleDestroy } = require("../services/upload.service"); -const uploadCtrl = { - uploadCloudinary: async (req, res, next) => { - try { - let file = req.files; - const { status, success, element } = await handleUpload({ file }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - destroyCloudinary: async (req, res, next) => { - try { - const { public_id } = req.body; - const { status, success, element } = await handleDestroy(public_id); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = uploadCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { handleUpload, handleDestroy } = require("../services/upload.service"); +const uploadCtrl = { + uploadCloudinary: async (req, res, next) => { + try { + let file = req.files; + const { status, success, element } = await handleUpload({ file }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + destroyCloudinary: async (req, res, next) => { + try { + const { public_id } = req.body; + const { status, success, element } = await handleDestroy(public_id); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = uploadCtrl; diff --git a/backend/src/v1/upload_cloudinary/routes/upload.routes.js b/backend/src/v1/upload_cloudinary/routes/upload.routes.js index 379c3b1..d52061f 100644 --- a/backend/src/v1/upload_cloudinary/routes/upload.routes.js +++ b/backend/src/v1/upload_cloudinary/routes/upload.routes.js @@ -1,11 +1,11 @@ -const router = require("express").Router(); -const uploadCtrl = require("../controllers/upload.controllers"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const RateLimitMiddleware = require("../../middlewares/ratelimit.middleware") - -//* upload -router.post("/upload", VerifyAcceptToken, RateLimitMiddleware, uploadCtrl.uploadCloudinary); - -//* destroy -router.post("/destroy", VerifyAcceptToken, RateLimitMiddleware, uploadCtrl.destroyCloudinary); -module.exports = router; +const router = require("express").Router(); +const uploadCtrl = require("../controllers/upload.controllers"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const RateLimitMiddleware = require("../../middlewares/ratelimit.middleware") + +//* upload +router.post("/upload", VerifyAcceptToken, RateLimitMiddleware, uploadCtrl.uploadCloudinary); + +//* destroy +router.post("/destroy", VerifyAcceptToken, RateLimitMiddleware, uploadCtrl.destroyCloudinary); +module.exports = router; diff --git a/backend/src/v1/upload_cloudinary/services/upload.service.js b/backend/src/v1/upload_cloudinary/services/upload.service.js index 6f432f1..cbebaa1 100644 --- a/backend/src/v1/upload_cloudinary/services/upload.service.js +++ b/backend/src/v1/upload_cloudinary/services/upload.service.js @@ -1,83 +1,83 @@ -const { - uploadStorage, - removeTmp, - destroyStorage, -} = require("./uploadStorage.service"); -const STORAGE = require("../../utils/storage"); -module.exports = { - handleUpload: async ({ file }) => { - try { - if (!file || Object.keys(file).length === 0) { - return { - status: 400, - success: false, - element: { - msg: "No files were uploaded !!", - }, - }; - } - - const file_upload = file.file; - if (file_upload.size > 1024 * 1024) { - removeTmp(file_upload.tempFilePath); - return { - status: 400, - success: false, - element: { - msg: "Size too large !!", - }, - }; - } - const type = STORAGE.detectedFileType(file_upload.mimetype); - if (type !== "image") { - removeTmp(file_upload.tempFilePath); - return { - status: 400, - success: false, - element: { - msg: "File format is incorrect !", - }, - }; - } - - const result = await uploadStorage(file_upload); - return { - status: 200, - success: true, - element: { - public_id: result.public_id, - url: result.secure_url, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { msg: "Server Busy !!" }, - }; - } - }, - handleDestroy: async (public_id) => { - try { - if (!public_id) { - return { - status: 400, - success: false, - element: { msg: "No images Selected" }, - }; - } - const results = await destroyStorage(public_id); - return { - status: 200, - success: true, - element: { results }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { msg: "Server Busy !!" }, - }; - } - }, -}; +const { + uploadStorage, + removeTmp, + destroyStorage, +} = require("./uploadStorage.service"); +const STORAGE = require("../../utils/storage"); +module.exports = { + handleUpload: async ({ file }) => { + try { + if (!file || Object.keys(file).length === 0) { + return { + status: 400, + success: false, + element: { + msg: "No files were uploaded !!", + }, + }; + } + + const file_upload = file.file; + if (file_upload.size > 1024 * 1024) { + removeTmp(file_upload.tempFilePath); + return { + status: 400, + success: false, + element: { + msg: "Size too large !!", + }, + }; + } + const type = STORAGE.detectedFileType(file_upload.mimetype); + if (type !== "image") { + removeTmp(file_upload.tempFilePath); + return { + status: 400, + success: false, + element: { + msg: "File format is incorrect !", + }, + }; + } + + const result = await uploadStorage(file_upload); + return { + status: 200, + success: true, + element: { + public_id: result.public_id, + url: result.secure_url, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { msg: "Server Busy !!" }, + }; + } + }, + handleDestroy: async (public_id) => { + try { + if (!public_id) { + return { + status: 400, + success: false, + element: { msg: "No images Selected" }, + }; + } + const results = await destroyStorage(public_id); + return { + status: 200, + success: true, + element: { results }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { msg: "Server Busy !!" }, + }; + } + }, +}; diff --git a/backend/src/v1/upload_cloudinary/services/uploadStorage.service.js b/backend/src/v1/upload_cloudinary/services/uploadStorage.service.js index b43a1ea..f0a760e 100644 --- a/backend/src/v1/upload_cloudinary/services/uploadStorage.service.js +++ b/backend/src/v1/upload_cloudinary/services/uploadStorage.service.js @@ -1,34 +1,34 @@ -const fs = require("fs"); -const cloudinary = require("../../db/cloudinary_db"); -const uploadStorage = async (file_upload) => { - let data = null; - await cloudinary.v2.uploader.upload( - file_upload.tempFilePath, - { folder: "user" }, - async (err, result) => { - if (err) throw (data = err); - removeTmp(file_upload.tempFilePath); - return (data = result); - } - ); - return data; -}; -const destroyStorage = async (public_id) => { - console.log(public_id); - let results = null; - await cloudinary.v2.uploader.destroy(public_id, async (err, result) => { - if (err) throw (results = err); - results = result; - }); - return results; -}; -const removeTmp = (path) => { - fs.unlink(path, (err) => { - if (err) throw err; - }); -}; -module.exports = { - uploadStorage, - destroyStorage, - removeTmp, -}; +const fs = require("fs"); +const cloudinary = require("../../db/cloudinary_db"); +const uploadStorage = async (file_upload) => { + let data = null; + await cloudinary.v2.uploader.upload( + file_upload.tempFilePath, + { folder: "user" }, + async (err, result) => { + if (err) throw (data = err); + removeTmp(file_upload.tempFilePath); + return (data = result); + } + ); + return data; +}; +const destroyStorage = async (public_id) => { + console.log(public_id); + let results = null; + await cloudinary.v2.uploader.destroy(public_id, async (err, result) => { + if (err) throw (results = err); + results = result; + }); + return results; +}; +const removeTmp = (path) => { + fs.unlink(path, (err) => { + if (err) throw err; + }); +}; +module.exports = { + uploadStorage, + destroyStorage, + removeTmp, +}; diff --git a/backend/src/v1/user_api/controllers/carousel.controller.js b/backend/src/v1/user_api/controllers/carousel.controller.js index 1951b07..77cb3bb 100644 --- a/backend/src/v1/user_api/controllers/carousel.controller.js +++ b/backend/src/v1/user_api/controllers/carousel.controller.js @@ -1,24 +1,24 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleGetallCarousel, -} = require("../services/carousel.service/carousel.service"); -const carouselCtrl = { - getallCarousel: async (req, res) => { - try { - const { status, success, element } = await handleGetallCarousel(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = carouselCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleGetallCarousel, +} = require("../services/carousel.service/carousel.service"); +const carouselCtrl = { + getallCarousel: async (req, res) => { + try { + const { status, success, element } = await handleGetallCarousel(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = carouselCtrl; diff --git a/backend/src/v1/user_api/controllers/categories.controllers.js b/backend/src/v1/user_api/controllers/categories.controllers.js index 3506e54..6f3f4ae 100644 --- a/backend/src/v1/user_api/controllers/categories.controllers.js +++ b/backend/src/v1/user_api/controllers/categories.controllers.js @@ -1,26 +1,26 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - HandleGetCategory, -} = require("../services/category.service/category.service"); - -const categoriesCtrl = { - //* Get All Category - getCategory: async (req, res) => { - try { - const { status, success, element } = await HandleGetCategory(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = categoriesCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + HandleGetCategory, +} = require("../services/category.service/category.service"); + +const categoriesCtrl = { + //* Get All Category + getCategory: async (req, res) => { + try { + const { status, success, element } = await HandleGetCategory(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = categoriesCtrl; diff --git a/backend/src/v1/user_api/controllers/feedbacks.controllers.js b/backend/src/v1/user_api/controllers/feedbacks.controllers.js index 60764ce..331f37d 100644 --- a/backend/src/v1/user_api/controllers/feedbacks.controllers.js +++ b/backend/src/v1/user_api/controllers/feedbacks.controllers.js @@ -1,34 +1,34 @@ -const { - handleSendFeedback, -} = require("../services/feedback.service/feedback.service"); -const { returnReasons } = require("../../middlewares/handleError"); -const HELPER = require("../../utils/helper"); -const feedbackCtrl = { - sendFeedBackUsers: async (req, res) => { - try { - const { fullname, email, subject, content, read_at } = req.body; - let time_log_gmt7_string = HELPER.getCurrentTimeJP(); - const { status, success, element } = await handleSendFeedback({ - fullname, - email, - subject, - content, - read_at, - time_log_gmt7_string, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = feedbackCtrl; +const { + handleSendFeedback, +} = require("../services/feedback.service/feedback.service"); +const { returnReasons } = require("../../middlewares/handleError"); +const HELPER = require("../../utils/helper"); +const feedbackCtrl = { + sendFeedBackUsers: async (req, res) => { + try { + const { fullname, email, subject, content, read_at } = req.body; + let time_log_gmt7_string = HELPER.getCurrentTimeJP(); + const { status, success, element } = await handleSendFeedback({ + fullname, + email, + subject, + content, + read_at, + time_log_gmt7_string, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = feedbackCtrl; diff --git a/backend/src/v1/user_api/controllers/order.controllers.js b/backend/src/v1/user_api/controllers/order.controllers.js index 2d68e83..9062446 100644 --- a/backend/src/v1/user_api/controllers/order.controllers.js +++ b/backend/src/v1/user_api/controllers/order.controllers.js @@ -1,73 +1,73 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleHistoryOrder, - handleDeleteFlagOrders, - handleDetailOrders, -} = require("../services/order.service.js/history.service"); -const paymentCtrl = { - historyOrders: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleHistoryOrder({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - deleteFlagOrders: async (req, res) => { - try { - const { password } = req.body; - let order_id = req.params.id; - let user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleDeleteFlagOrders({ - order_id, - password, - user_id - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - getDetailOrders: async (req, res) => { - try { - let order_id = req.params.id; - const { status, success, element } = await handleDetailOrders({ - order_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - } -}; -module.exports = paymentCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleHistoryOrder, + handleDeleteFlagOrders, + handleDetailOrders, +} = require("../services/order.service.js/history.service"); +const paymentCtrl = { + historyOrders: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleHistoryOrder({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + deleteFlagOrders: async (req, res) => { + try { + const { password } = req.body; + let order_id = req.params.id; + let user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleDeleteFlagOrders({ + order_id, + password, + user_id + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + getDetailOrders: async (req, res) => { + try { + let order_id = req.params.id; + const { status, success, element } = await handleDetailOrders({ + order_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + } +}; +module.exports = paymentCtrl; diff --git a/backend/src/v1/user_api/controllers/payment.controllers.js b/backend/src/v1/user_api/controllers/payment.controllers.js index 339432b..0b1f7a6 100644 --- a/backend/src/v1/user_api/controllers/payment.controllers.js +++ b/backend/src/v1/user_api/controllers/payment.controllers.js @@ -1,137 +1,137 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handlePaymentTotal, - handleCheckInStock, - handlePaymentPaypal, - handlePaymentStripe, - handlePaymentStripeSuccess, - handlePaymentStripeCancel -} = require("../services/payment.service/payment.service"); -const paymentCtrl = { - totalPayment: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handlePaymentTotal({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - countInStock: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleCheckInStock({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - paymentPaypal: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { paymentID, address } = req.body; - const { status, success, element } = await handlePaymentPaypal({ - user_id, - paymentID, - address, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - paymentStripe: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handlePaymentStripe({ - user_id, - req - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - paymentStripeSuccess: async (req, res) => { - try { - let payment_id = req.params.id; - let user_id = req.user.id || req.user.user_id; - - const { status, success, element } = await handlePaymentStripeSuccess({ - payment_id, - user_id - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - paymentStripeCancel: async (req, res) => { - try { - - const { status, success, element } = await handlePaymentStripeCancel(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = paymentCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handlePaymentTotal, + handleCheckInStock, + handlePaymentPaypal, + handlePaymentStripe, + handlePaymentStripeSuccess, + handlePaymentStripeCancel +} = require("../services/payment.service/payment.service"); +const paymentCtrl = { + totalPayment: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handlePaymentTotal({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + countInStock: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleCheckInStock({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + paymentPaypal: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { paymentID, address } = req.body; + const { status, success, element } = await handlePaymentPaypal({ + user_id, + paymentID, + address, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + paymentStripe: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handlePaymentStripe({ + user_id, + req + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + paymentStripeSuccess: async (req, res) => { + try { + let payment_id = req.params.id; + let user_id = req.user.id || req.user.user_id; + + const { status, success, element } = await handlePaymentStripeSuccess({ + payment_id, + user_id + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + paymentStripeCancel: async (req, res) => { + try { + + const { status, success, element } = await handlePaymentStripeCancel(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = paymentCtrl; diff --git a/backend/src/v1/user_api/controllers/product.controllers.js b/backend/src/v1/user_api/controllers/product.controllers.js index a991b86..1a1d1db 100644 --- a/backend/src/v1/user_api/controllers/product.controllers.js +++ b/backend/src/v1/user_api/controllers/product.controllers.js @@ -1,168 +1,168 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - HandleGetProduct, - HandleGetProductDetail, - handleAddToCart, - handleDelCart, - handleGetAddToCart, - handleIncrementCart, - handleDecrementCart, -} = require("../services/product.service/product.service"); - -const productCtrl = { - //* Get All Product - getProducts: async (req, res) => { - try { - const { status, success, element } = await HandleGetProduct(); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Get Product Detail - getProductDetail: async (req, res) => { - try { - let product_id = req.params.id; - const { status, success, element } = await HandleGetProductDetail({ - product_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Add To cart - addToCartProduct: async (req, res) => { - try { - const { product_id, quantity } = req.body; - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleAddToCart({ - user_id, - product_id, - quantity, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Increase quantity: - incrementQuantityCartProduct: async (req, res) => { - try { - const { product_id, quantity } = req.body; - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleIncrementCart({ - user_id, - product_id, - quantity, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //** Decrease quantity */ - decrementQuantityCartProduct: async (req, res) => { - try { - const { product_id, quantity } = req.body; - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleDecrementCart({ - user_id, - product_id, - quantity, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Del cart - delCartProduct: async (req, res) => { - try { - const { product_id } = req.body; - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleDelCart({ - user_id, - product_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - getAddToCart: async (req, res) => { - try { - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleGetAddToCart({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = productCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + HandleGetProduct, + HandleGetProductDetail, + handleAddToCart, + handleDelCart, + handleGetAddToCart, + handleIncrementCart, + handleDecrementCart, +} = require("../services/product.service/product.service"); + +const productCtrl = { + //* Get All Product + getProducts: async (req, res) => { + try { + const { status, success, element } = await HandleGetProduct(); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Get Product Detail + getProductDetail: async (req, res) => { + try { + let product_id = req.params.id; + const { status, success, element } = await HandleGetProductDetail({ + product_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Add To cart + addToCartProduct: async (req, res) => { + try { + const { product_id, quantity } = req.body; + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleAddToCart({ + user_id, + product_id, + quantity, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Increase quantity: + incrementQuantityCartProduct: async (req, res) => { + try { + const { product_id, quantity } = req.body; + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleIncrementCart({ + user_id, + product_id, + quantity, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //** Decrease quantity */ + decrementQuantityCartProduct: async (req, res) => { + try { + const { product_id, quantity } = req.body; + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleDecrementCart({ + user_id, + product_id, + quantity, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Del cart + delCartProduct: async (req, res) => { + try { + const { product_id } = req.body; + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleDelCart({ + user_id, + product_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + getAddToCart: async (req, res) => { + try { + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleGetAddToCart({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = productCtrl; diff --git a/backend/src/v1/user_api/controllers/review.controllers.js b/backend/src/v1/user_api/controllers/review.controllers.js index 1c0a4dc..d1cee2b 100644 --- a/backend/src/v1/user_api/controllers/review.controllers.js +++ b/backend/src/v1/user_api/controllers/review.controllers.js @@ -1,86 +1,86 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const { - handleCreateReview, - handleEditReview, - handleDeleteReview, -} = require("../services/review.service/review.service"); - -const reviewCtrl = { - createReviewProduct: async (req, res) => { - try { - const { rating, comment } = req.body; - let review_id = req.params.id; - let user_id = req.user.id || req.user.user_id; - - const { status, success, element } = await handleCreateReview({ - rating, - comment, - review_id, - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - editReviewProduct: async (req, res) => { - try { - const { comment } = req.body; - const user_id = req.user.id || req.user.user_id; - const product_id = req.params.productId; - const review_id = req.params.commentId; - const { status, success, element } = await handleEditReview({ - comment, - user_id, - product_id, - review_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - deleteReviewProduct: async (req, res) => { - try { - const user_id = req.user.id || req.user.user_id; - const product_id = req.params.productId; - const review_id = req.params.commentId; - const { status, success, element } = await handleDeleteReview({ - user_id, - product_id, - review_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = reviewCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const { + handleCreateReview, + handleEditReview, + handleDeleteReview, +} = require("../services/review.service/review.service"); + +const reviewCtrl = { + createReviewProduct: async (req, res) => { + try { + const { rating, comment } = req.body; + let review_id = req.params.id; + let user_id = req.user.id || req.user.user_id; + + const { status, success, element } = await handleCreateReview({ + rating, + comment, + review_id, + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + editReviewProduct: async (req, res) => { + try { + const { comment } = req.body; + const user_id = req.user.id || req.user.user_id; + const product_id = req.params.productId; + const review_id = req.params.commentId; + const { status, success, element } = await handleEditReview({ + comment, + user_id, + product_id, + review_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + deleteReviewProduct: async (req, res) => { + try { + const user_id = req.user.id || req.user.user_id; + const product_id = req.params.productId; + const review_id = req.params.commentId; + const { status, success, element } = await handleDeleteReview({ + user_id, + product_id, + review_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = reviewCtrl; diff --git a/backend/src/v1/user_api/controllers/user.controllers.js b/backend/src/v1/user_api/controllers/user.controllers.js index f8c73ac..9eae77a 100644 --- a/backend/src/v1/user_api/controllers/user.controllers.js +++ b/backend/src/v1/user_api/controllers/user.controllers.js @@ -1,379 +1,379 @@ -const path = require("path"); -const { returnReasons } = require("../../middlewares/handleError"); -const { - checkLoginUser, - checkLoginGoogle, - checkLoginFacebook, - checkRegisterUser, - CreateNewAcceptToken, - LogoutRemoveAllUser, - HandleProfile, - HandleForgerPasswordUser, - HandleResetPasswordUser, - HandleChangePassword, - HandleUploadProfile, - handleLoginPhoneFirebase, - HandleInfoEveryUsers, -} = require("../../user_api/services/user.service/user.service"); -const { - CheckVerificationUser, -} = require("../services/user.service/checkAuthUser.service"); -const userCtrl = { - //*--------------- Authentication Users --------------- - - //* Login Email and Phone - loginUser: async (req, res) => { - try { - const { email_phone, password, token } = req.body; - const GetIPUser = - req.headers["x-forwarded-for"] || req.connection.remoteAddress; - let session = req.session; - const { status, success, element } = await checkLoginUser({ - email_phone, - password, - token, - GetIPUser, - res, - session, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - loginPhoneFirebase: async (req, res) => { - try { - const { phone_number } = req.body; - let session = req.session; - - const { status, success, element } = await handleLoginPhoneFirebase({ - phone_number, - session, - res, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Login Google - loginUserGoogle: async (req, res) => { - try { - const { tokenId } = req.body; - const { status, success, element } = await checkLoginGoogle({ - tokenId, - res, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Login Facebook - loginUserFacebook: async (req, res) => { - try { - const { userID, accessToken } = req.body; - const { status, success, element } = await checkLoginFacebook({ - userID, - accessToken, - res, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Registers - registerUser: async (req, res) => { - try { - const { - name, - email, - password, - confirmPassword, - sex, - date_of_birth, - phone_number, - token, - } = req.body; - const { status, success, element } = await checkRegisterUser({ - name, - email, - password, - confirmPassword, - sex, - date_of_birth, - phone_number, - token, - req, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Verification Email - verifyEmail: async (req, res) => { - try { - const { userId, uniqueString } = req.params; - const { success } = await CheckVerificationUser(userId, uniqueString); - if (!success) { - return res.sendFile(path.resolve(__dirname, "../../views/error.html")); - } else { - return res.sendFile( - path.resolve(__dirname, "../../views/thankyou.html") - ); - } - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* New AcceptToken - createNewAccessTokens: async (req, res) => { - try { - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await CreateNewAcceptToken({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Logout - LogoutUser: async (req, res) => { - try { - const user_id = req.user.id || req.user.user_id; - const token = req.token; - const session = req.session; - const { status, success, element } = await LogoutRemoveAllUser({ - user_id, - token, - session, - res, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - - //*--------------- Information Users --------------- - - //* Profile User - ProfileUser: async (req, res) => { - try { - const user_id = req.user.id || req.user.user_id; - const session = req.session; - const { status, success, element } = await HandleProfile({ - user_id, - session, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - // * Update Profile - UpdateProfile: async (req, res) => { - try { - const { name, image, phone_number, sex, date_of_birth } = req.body; - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await HandleUploadProfile({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - - //*--------------- Forget,Reset,Change Users --------------- - - //* Forget Password User - ForgetPassword: async (req, res) => { - try { - const { email } = req.body; - const { status, success, element } = await HandleForgerPasswordUser({ - email, - req, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - error, - }); - } - }, - //* Reset Password User - ResetPassword: async (req, res) => { - try { - const { password, confirmPassword } = req.body; - const token = req.params.token; - const { status, success, element } = await HandleResetPasswordUser({ - password, - confirmPassword, - token, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //* Change Password User - ChangePassword: async (req, res) => { - try { - const { password, oldPassword, confirmPassword } = req.body; - const user_id = req.user.id || req.user.user_id; - const { status, success, element } = await HandleChangePassword({ - password, - oldPassword, - confirmPassword, - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - //*--------------- Information Users --------------- - - //* Info Every Users - InfoEveryUsers: async (req, res) => { - try { - let user_id = req.params.id; - const { status, success, element } = await HandleInfoEveryUsers({ - user_id, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = userCtrl; +const path = require("path"); +const { returnReasons } = require("../../middlewares/handleError"); +const { + checkLoginUser, + checkLoginGoogle, + checkLoginFacebook, + checkRegisterUser, + CreateNewAcceptToken, + LogoutRemoveAllUser, + HandleProfile, + HandleForgerPasswordUser, + HandleResetPasswordUser, + HandleChangePassword, + HandleUploadProfile, + handleLoginPhoneFirebase, + HandleInfoEveryUsers, +} = require("../../user_api/services/user.service/user.service"); +const { + CheckVerificationUser, +} = require("../services/user.service/checkAuthUser.service"); +const userCtrl = { + //*--------------- Authentication Users --------------- + + //* Login Email and Phone + loginUser: async (req, res) => { + try { + const { email_phone, password, token } = req.body; + const GetIPUser = + req.headers["x-forwarded-for"] || req.connection.remoteAddress; + let session = req.session; + const { status, success, element } = await checkLoginUser({ + email_phone, + password, + token, + GetIPUser, + res, + session, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + loginPhoneFirebase: async (req, res) => { + try { + const { phone_number } = req.body; + let session = req.session; + + const { status, success, element } = await handleLoginPhoneFirebase({ + phone_number, + session, + res, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Login Google + loginUserGoogle: async (req, res) => { + try { + const { tokenId } = req.body; + const { status, success, element } = await checkLoginGoogle({ + tokenId, + res, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Login Facebook + loginUserFacebook: async (req, res) => { + try { + const { userID, accessToken } = req.body; + const { status, success, element } = await checkLoginFacebook({ + userID, + accessToken, + res, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Registers + registerUser: async (req, res) => { + try { + const { + name, + email, + password, + confirmPassword, + sex, + date_of_birth, + phone_number, + token, + } = req.body; + const { status, success, element } = await checkRegisterUser({ + name, + email, + password, + confirmPassword, + sex, + date_of_birth, + phone_number, + token, + req, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Verification Email + verifyEmail: async (req, res) => { + try { + const { userId, uniqueString } = req.params; + const { success } = await CheckVerificationUser(userId, uniqueString); + if (!success) { + return res.sendFile(path.resolve(__dirname, "../../views/error.html")); + } else { + return res.sendFile( + path.resolve(__dirname, "../../views/thankyou.html") + ); + } + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* New AcceptToken + createNewAccessTokens: async (req, res) => { + try { + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await CreateNewAcceptToken({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Logout + LogoutUser: async (req, res) => { + try { + const user_id = req.user.id || req.user.user_id; + const token = req.token; + const session = req.session; + const { status, success, element } = await LogoutRemoveAllUser({ + user_id, + token, + session, + res, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + + //*--------------- Information Users --------------- + + //* Profile User + ProfileUser: async (req, res) => { + try { + const user_id = req.user.id || req.user.user_id; + const session = req.session; + const { status, success, element } = await HandleProfile({ + user_id, + session, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + // * Update Profile + UpdateProfile: async (req, res) => { + try { + const { name, image, phone_number, sex, date_of_birth } = req.body; + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await HandleUploadProfile({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + + //*--------------- Forget,Reset,Change Users --------------- + + //* Forget Password User + ForgetPassword: async (req, res) => { + try { + const { email } = req.body; + const { status, success, element } = await HandleForgerPasswordUser({ + email, + req, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + error, + }); + } + }, + //* Reset Password User + ResetPassword: async (req, res) => { + try { + const { password, confirmPassword } = req.body; + const token = req.params.token; + const { status, success, element } = await HandleResetPasswordUser({ + password, + confirmPassword, + token, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //* Change Password User + ChangePassword: async (req, res) => { + try { + const { password, oldPassword, confirmPassword } = req.body; + const user_id = req.user.id || req.user.user_id; + const { status, success, element } = await HandleChangePassword({ + password, + oldPassword, + confirmPassword, + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + //*--------------- Information Users --------------- + + //* Info Every Users + InfoEveryUsers: async (req, res) => { + try { + let user_id = req.params.id; + const { status, success, element } = await HandleInfoEveryUsers({ + user_id, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = userCtrl; diff --git a/backend/src/v1/user_api/controllers/voucher.controllers.js b/backend/src/v1/user_api/controllers/voucher.controllers.js index a35bdfe..3898532 100644 --- a/backend/src/v1/user_api/controllers/voucher.controllers.js +++ b/backend/src/v1/user_api/controllers/voucher.controllers.js @@ -1,49 +1,49 @@ -const { returnReasons } = require("../../middlewares/handleError"); -const HELPER = require("../../utils/helper"); -const { - handleVoucher, - handleDelVoucher, -} = require("../services/voucher.service/voucher.service"); -const voucherCtrl = { - addVoucher: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { title } = req.body; - const { status, success, element } = await handleVoucher({ - user_id, - title, - }); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, - delVoucher: async (req, res) => { - try { - let user_id = req.user.id || req.user.user_id; - const { status, success, element } = await handleDelVoucher(user_id); - return res.status(status).json({ - status, - success, - msg: returnReasons(status.toString()), - element, - }); - } catch (error) { - return res.status(503).json({ - status: 503, - success: false, - element: returnReasons("503"), - }); - } - }, -}; -module.exports = voucherCtrl; +const { returnReasons } = require("../../middlewares/handleError"); +const HELPER = require("../../utils/helper"); +const { + handleVoucher, + handleDelVoucher, +} = require("../services/voucher.service/voucher.service"); +const voucherCtrl = { + addVoucher: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { title } = req.body; + const { status, success, element } = await handleVoucher({ + user_id, + title, + }); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, + delVoucher: async (req, res) => { + try { + let user_id = req.user.id || req.user.user_id; + const { status, success, element } = await handleDelVoucher(user_id); + return res.status(status).json({ + status, + success, + msg: returnReasons(status.toString()), + element, + }); + } catch (error) { + return res.status(503).json({ + status: 503, + success: false, + element: returnReasons("503"), + }); + } + }, +}; +module.exports = voucherCtrl; diff --git a/backend/src/v1/user_api/cron_users/index.js b/backend/src/v1/user_api/cron_users/index.js index 5dfa482..b371362 100644 --- a/backend/src/v1/user_api/cron_users/index.js +++ b/backend/src/v1/user_api/cron_users/index.js @@ -1,25 +1,25 @@ -const Users = require("../../models/userModel"); -const UserVerifications = require("../../models/userVerificationModel"); -const CONSTANTS = require("../../configs/constants"); -module.exports = { - /** - * @author Tiến Tài - * Delete Uncheck - */ - async Delete_User_Un_Check_Expired() { - const data = await UserVerifications.find({ - expiresAt: { $lt: Date.now() }, - }).select("userId"); - const users = await Users.find({ - verified: CONSTANTS.DELETED_DISABLE, - }).select("_id"); - for (var i = 0; i < data.length; i++) { - for (var j = 0; j < users.length; j++) { - if (data[i].userId == users[j].id) { - await Users.deleteOne({ _id: users[j].id }); - await UserVerifications.deleteOne({ userId: data[i].userId }); - } - } - } - }, -}; +const Users = require("../../models/userModel"); +const UserVerifications = require("../../models/userVerificationModel"); +const CONSTANTS = require("../../configs/constants"); +module.exports = { + /** + * @author Tiến Tài + * Delete Uncheck + */ + async Delete_User_Un_Check_Expired() { + const data = await UserVerifications.find({ + expiresAt: { $lt: Date.now() }, + }).select("userId"); + const users = await Users.find({ + verified: CONSTANTS.DELETED_DISABLE, + }).select("_id"); + for (var i = 0; i < data.length; i++) { + for (var j = 0; j < users.length; j++) { + if (data[i].userId == users[j].id) { + await Users.deleteOne({ _id: users[j].id }); + await UserVerifications.deleteOne({ userId: data[i].userId }); + } + } + } + }, +}; diff --git a/backend/src/v1/user_api/routes/carousel.routes.js b/backend/src/v1/user_api/routes/carousel.routes.js index a1622d7..7882819 100644 --- a/backend/src/v1/user_api/routes/carousel.routes.js +++ b/backend/src/v1/user_api/routes/carousel.routes.js @@ -1,6 +1,6 @@ -const router = require("express").Router(); -const carouselCtrl = require("../controllers/carousel.controller"); - -//* Get All carousel -router.get("/carousel", carouselCtrl.getallCarousel); -module.exports = router; +const router = require("express").Router(); +const carouselCtrl = require("../controllers/carousel.controller"); + +//* Get All carousel +router.get("/carousel", carouselCtrl.getallCarousel); +module.exports = router; diff --git a/backend/src/v1/user_api/routes/categories.routes.js b/backend/src/v1/user_api/routes/categories.routes.js index ea67919..81f2af6 100644 --- a/backend/src/v1/user_api/routes/categories.routes.js +++ b/backend/src/v1/user_api/routes/categories.routes.js @@ -1,9 +1,9 @@ -const router = require("express").Router(); -const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const authAdmin = require("../../middlewares/VerificationAdmin"); -const categoriesCtrl = require("../controllers/categories.controllers"); - -//* Get All Category -router.get("/user/category", VerifyAcceptToken, categoriesCtrl.getCategory); -module.exports = router; +const router = require("express").Router(); +const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const authAdmin = require("../../middlewares/VerificationAdmin"); +const categoriesCtrl = require("../controllers/categories.controllers"); + +//* Get All Category +router.get("/user/category", VerifyAcceptToken, categoriesCtrl.getCategory); +module.exports = router; diff --git a/backend/src/v1/user_api/routes/feedback.routes.js b/backend/src/v1/user_api/routes/feedback.routes.js index 522922b..7b51d0b 100644 --- a/backend/src/v1/user_api/routes/feedback.routes.js +++ b/backend/src/v1/user_api/routes/feedback.routes.js @@ -1,6 +1,6 @@ -const router = require("express").Router(); -const feedbackCtrl = require("../controllers/feedbacks.controllers"); - -//* Get All Category -router.post("/feedback/send", feedbackCtrl.sendFeedBackUsers); -module.exports = router; +const router = require("express").Router(); +const feedbackCtrl = require("../controllers/feedbacks.controllers"); + +//* Get All Category +router.post("/feedback/send", feedbackCtrl.sendFeedBackUsers); +module.exports = router; diff --git a/backend/src/v1/user_api/routes/order.routes.js b/backend/src/v1/user_api/routes/order.routes.js index 402b387..f1740ce 100644 --- a/backend/src/v1/user_api/routes/order.routes.js +++ b/backend/src/v1/user_api/routes/order.routes.js @@ -1,14 +1,14 @@ -const router = require("express").Router(); -const orderCtrl = require("../controllers/order.controllers"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); - -//* Get history orders -router.get("/order/history", VerifyAcceptToken, orderCtrl.historyOrders); - -//* Delete flag orders -router.post("/order/delete/:id", VerifyAcceptToken, orderCtrl.deleteFlagOrders); - -//* Get Detail orders -router.get("/order/:id", VerifyAcceptToken, orderCtrl.getDetailOrders); - -module.exports = router; +const router = require("express").Router(); +const orderCtrl = require("../controllers/order.controllers"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); + +//* Get history orders +router.get("/order/history", VerifyAcceptToken, orderCtrl.historyOrders); + +//* Delete flag orders +router.post("/order/delete/:id", VerifyAcceptToken, orderCtrl.deleteFlagOrders); + +//* Get Detail orders +router.get("/order/:id", VerifyAcceptToken, orderCtrl.getDetailOrders); + +module.exports = router; diff --git a/backend/src/v1/user_api/routes/payment.routes.js b/backend/src/v1/user_api/routes/payment.routes.js index de7ad5a..9068c09 100644 --- a/backend/src/v1/user_api/routes/payment.routes.js +++ b/backend/src/v1/user_api/routes/payment.routes.js @@ -1,24 +1,24 @@ -const router = require("express").Router(); -const paymentCtrl = require("../controllers/payment.controllers"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); - -//* payment total -router.get("/payment/total", VerifyAcceptToken, paymentCtrl.totalPayment); -//* payment check inStock -router.get("/payment/check/stock", VerifyAcceptToken, paymentCtrl.countInStock); - -//* payment paypal -router.post("/payment/paypal", VerifyAcceptToken, paymentCtrl.paymentPaypal); - -//* payment stripe -router.get("/payment/stripe", VerifyAcceptToken, paymentCtrl.paymentStripe); - -//* Payment Success -router.get("/payment/stripe/success/:id", VerifyAcceptToken, paymentCtrl.paymentStripeSuccess); - -//* Payment Cancel -router.get("/payment/cancel", VerifyAcceptToken, paymentCtrl.paymentStripeCancel); - - - -module.exports = router; +const router = require("express").Router(); +const paymentCtrl = require("../controllers/payment.controllers"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); + +//* payment total +router.get("/payment/total", VerifyAcceptToken, paymentCtrl.totalPayment); +//* payment check inStock +router.get("/payment/check/stock", VerifyAcceptToken, paymentCtrl.countInStock); + +//* payment paypal +router.post("/payment/paypal", VerifyAcceptToken, paymentCtrl.paymentPaypal); + +//* payment stripe +router.get("/payment/stripe", VerifyAcceptToken, paymentCtrl.paymentStripe); + +//* Payment Success +router.get("/payment/stripe/success/:id", VerifyAcceptToken, paymentCtrl.paymentStripeSuccess); + +//* Payment Cancel +router.get("/payment/cancel", VerifyAcceptToken, paymentCtrl.paymentStripeCancel); + + + +module.exports = router; diff --git a/backend/src/v1/user_api/routes/product.routes.js b/backend/src/v1/user_api/routes/product.routes.js index ea23329..25dd9d3 100644 --- a/backend/src/v1/user_api/routes/product.routes.js +++ b/backend/src/v1/user_api/routes/product.routes.js @@ -1,32 +1,32 @@ -const router = require("express").Router(); -const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const productCtrl = require("../controllers/product.controllers"); - -//* Get All Product -router.get("/product", productCtrl.getProducts); - -router.get("/product/detail/:id", productCtrl.getProductDetail); -// * add to cart -router.post( - "/product/add/cart", - VerifyAcceptToken, - productCtrl.addToCartProduct -); -// * InCrement Cart product -router.post( - "/product/increment/cart", - VerifyAcceptToken, - productCtrl.incrementQuantityCartProduct -); -// * DeCrement Cart product -router.post( - "/product/decrement/cart", - VerifyAcceptToken, - productCtrl.decrementQuantityCartProduct -); -// * del Cart Product -router.post("/product/del/cart", VerifyAcceptToken, productCtrl.delCartProduct); -// * Get Add to cart -router.get("/product/get/cart", VerifyAcceptToken, productCtrl.getAddToCart); -module.exports = router; +const router = require("express").Router(); +const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const productCtrl = require("../controllers/product.controllers"); + +//* Get All Product +router.get("/product", productCtrl.getProducts); + +router.get("/product/detail/:id", productCtrl.getProductDetail); +// * add to cart +router.post( + "/product/add/cart", + VerifyAcceptToken, + productCtrl.addToCartProduct +); +// * InCrement Cart product +router.post( + "/product/increment/cart", + VerifyAcceptToken, + productCtrl.incrementQuantityCartProduct +); +// * DeCrement Cart product +router.post( + "/product/decrement/cart", + VerifyAcceptToken, + productCtrl.decrementQuantityCartProduct +); +// * del Cart Product +router.post("/product/del/cart", VerifyAcceptToken, productCtrl.delCartProduct); +// * Get Add to cart +router.get("/product/get/cart", VerifyAcceptToken, productCtrl.getAddToCart); +module.exports = router; diff --git a/backend/src/v1/user_api/routes/review.routes.js b/backend/src/v1/user_api/routes/review.routes.js index 0eff2d4..57e35cd 100644 --- a/backend/src/v1/user_api/routes/review.routes.js +++ b/backend/src/v1/user_api/routes/review.routes.js @@ -1,24 +1,24 @@ -const router = require("express").Router(); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const reviewCtrl = require("../controllers/review.controllers"); - -//* comment Product -router.post( - "/review/create/:id", - VerifyAcceptToken, - reviewCtrl.createReviewProduct -); - -//* edit comment -router.post( - "/review/:productId/update/:commentId", - VerifyAcceptToken, - reviewCtrl.editReviewProduct -); -//* delete comment -router.delete( - "/review/:productId/delete/:commentId", - VerifyAcceptToken, - reviewCtrl.deleteReviewProduct -); -module.exports = router; +const router = require("express").Router(); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const reviewCtrl = require("../controllers/review.controllers"); + +//* comment Product +router.post( + "/review/create/:id", + VerifyAcceptToken, + reviewCtrl.createReviewProduct +); + +//* edit comment +router.post( + "/review/:productId/update/:commentId", + VerifyAcceptToken, + reviewCtrl.editReviewProduct +); +//* delete comment +router.delete( + "/review/:productId/delete/:commentId", + VerifyAcceptToken, + reviewCtrl.deleteReviewProduct +); +module.exports = router; diff --git a/backend/src/v1/user_api/routes/user.routes.js b/backend/src/v1/user_api/routes/user.routes.js index 1d1bf87..e25f30c 100644 --- a/backend/src/v1/user_api/routes/user.routes.js +++ b/backend/src/v1/user_api/routes/user.routes.js @@ -1,54 +1,54 @@ -const router = require("express").Router(); -const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); -const userCtrl = require("../controllers/user.controllers"); -// * -------------- Register ------------- -//! Register Users -router.post("/user/register", userCtrl.registerUser); - -// * ------------- Login ------------- -//!Login Email and Phone -router.post("/user/login", userCtrl.loginUser); - -//!Login Phone OTP Firebase -router.post("/user/login/mobile", userCtrl.loginPhoneFirebase); -//! Login Google Socials -router.post("/user/login/google", userCtrl.loginUserGoogle); -//! Login Facebook Socials -router.post("/user/login/facebook", userCtrl.loginUserFacebook); - -//*------------- Verification ------------- -//! Check Verification -router.get("/user/verify/:userId/:uniqueString", userCtrl.verifyEmail); - -//*------------- Create New AccessToken ------------- -//! New Access Token -router.get( - "/user/new/accessToken", - VerifyRefreshToken, - userCtrl.createNewAccessTokens -); -//*------------- Logout Account Users ------------- -//! Logout Users -router.get("/user/logout", VerifyAcceptToken, userCtrl.LogoutUser); -//*------------- Information Users ------------- -//! Profile Users -router.get("/user/profile", VerifyAcceptToken, userCtrl.ProfileUser); -//! Update Users -router.post("/user/update/profile", VerifyAcceptToken, userCtrl.UpdateProfile); - -//*------------- Forget,reset,change Account Users ------------- -//! Forget Password Users -router.post("/user/forget", userCtrl.ForgetPassword); -//! Reset Password User -router.post("/user/password/reset/:token", userCtrl.ResetPassword); -//! Change Password User -router.post( - "/user/change/password", - VerifyAcceptToken, - userCtrl.ChangePassword -); -//! Get Profile Every Id -router.get("/user/info/:id", userCtrl.InfoEveryUsers); - -module.exports = router; +const router = require("express").Router(); +const VerifyRefreshToken = require("../../middlewares/VerifyRefreshToken.middleware"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); +const userCtrl = require("../controllers/user.controllers"); +// * -------------- Register ------------- +//! Register Users +router.post("/user/register", userCtrl.registerUser); + +// * ------------- Login ------------- +//!Login Email and Phone +router.post("/user/login", userCtrl.loginUser); + +//!Login Phone OTP Firebase +router.post("/user/login/mobile", userCtrl.loginPhoneFirebase); +//! Login Google Socials +router.post("/user/login/google", userCtrl.loginUserGoogle); +//! Login Facebook Socials +router.post("/user/login/facebook", userCtrl.loginUserFacebook); + +//*------------- Verification ------------- +//! Check Verification +router.get("/user/verify/:userId/:uniqueString", userCtrl.verifyEmail); + +//*------------- Create New AccessToken ------------- +//! New Access Token +router.get( + "/user/new/accessToken", + VerifyRefreshToken, + userCtrl.createNewAccessTokens +); +//*------------- Logout Account Users ------------- +//! Logout Users +router.get("/user/logout", VerifyAcceptToken, userCtrl.LogoutUser); +//*------------- Information Users ------------- +//! Profile Users +router.get("/user/profile", VerifyAcceptToken, userCtrl.ProfileUser); +//! Update Users +router.post("/user/update/profile", VerifyAcceptToken, userCtrl.UpdateProfile); + +//*------------- Forget,reset,change Account Users ------------- +//! Forget Password Users +router.post("/user/forget", userCtrl.ForgetPassword); +//! Reset Password User +router.post("/user/password/reset/:token", userCtrl.ResetPassword); +//! Change Password User +router.post( + "/user/change/password", + VerifyAcceptToken, + userCtrl.ChangePassword +); +//! Get Profile Every Id +router.get("/user/info/:id", userCtrl.InfoEveryUsers); + +module.exports = router; diff --git a/backend/src/v1/user_api/routes/voucher.routes.js b/backend/src/v1/user_api/routes/voucher.routes.js index eba3270..a8319f0 100644 --- a/backend/src/v1/user_api/routes/voucher.routes.js +++ b/backend/src/v1/user_api/routes/voucher.routes.js @@ -1,10 +1,10 @@ -const router = require("express").Router(); -const voucherCtrl = require("../controllers/voucher.controllers"); -const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); - -//* Add voucher -router.post("/user/voucher", VerifyAcceptToken, voucherCtrl.addVoucher); - -//* Del voucher -router.get("/user/voucher/del", VerifyAcceptToken, voucherCtrl.delVoucher); -module.exports = router; +const router = require("express").Router(); +const voucherCtrl = require("../controllers/voucher.controllers"); +const VerifyAcceptToken = require("../../middlewares/VerifyAcceptToken.middleware"); + +//* Add voucher +router.post("/user/voucher", VerifyAcceptToken, voucherCtrl.addVoucher); + +//* Del voucher +router.get("/user/voucher/del", VerifyAcceptToken, voucherCtrl.delVoucher); +module.exports = router; diff --git a/backend/src/v1/user_api/services/carousel.service/carousel.service.js b/backend/src/v1/user_api/services/carousel.service/carousel.service.js index f91f9c6..695fed0 100644 --- a/backend/src/v1/user_api/services/carousel.service/carousel.service.js +++ b/backend/src/v1/user_api/services/carousel.service/carousel.service.js @@ -1,52 +1,52 @@ -const { set, get } = require("../../../utils/limited_redis"); -const Carousel = require("../../../models/CarouselModel"); -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -module.exports = { - handleGetallCarousel: async () => { - try { - const carousel_user_redis = await get("carousel"); - if (carousel_user_redis) { - return { - status: 200, - success: true, - element: { - carousels: JSON.parse(carousel_user_redis), - }, - }; - } - const number_random = HELPER.randomNumber(); - - const carousels = await Carousel.aggregate([ - { - $project: { - doc: "$$ROOT", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - - set( - "carousel", - JSON.stringify(carousels), - CONSTANTS._1_DAYS_REDIS + number_random - ); - return { - status: 200, - success: true, - element: { - carousels, - }, - }; - } catch (err) { - return res.status(500).json({ msg: err.message }); - } - }, -}; +const { set, get } = require("../../../utils/limited_redis"); +const Carousel = require("../../../models/CarouselModel"); +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +module.exports = { + handleGetallCarousel: async () => { + try { + const carousel_user_redis = await get("carousel"); + if (carousel_user_redis) { + return { + status: 200, + success: true, + element: { + carousels: JSON.parse(carousel_user_redis), + }, + }; + } + const number_random = HELPER.randomNumber(); + + const carousels = await Carousel.aggregate([ + { + $project: { + doc: "$$ROOT", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + + set( + "carousel", + JSON.stringify(carousels), + CONSTANTS._1_DAYS_REDIS + number_random + ); + return { + status: 200, + success: true, + element: { + carousels, + }, + }; + } catch (err) { + return res.status(500).json({ msg: err.message }); + } + }, +}; diff --git a/backend/src/v1/user_api/services/category.service/Crudcategories.service.js b/backend/src/v1/user_api/services/category.service/Crudcategories.service.js index cced3cf..429232c 100644 --- a/backend/src/v1/user_api/services/category.service/Crudcategories.service.js +++ b/backend/src/v1/user_api/services/category.service/Crudcategories.service.js @@ -1,21 +1,21 @@ -const { set, get } = require("../../../utils/limited_redis"); -const Category = require("../../../models/CategoryModel"); -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -module.exports = { - getAllCategory: async () => { - const categories = await get("categories"); - if (categories) { - return JSON.parse(categories); - } - const number_random = HELPER.randomNumber(); - - const category = await Category.find(); - set( - "categories", - JSON.stringify(category), - CONSTANTS._1_DAYS_REDIS + number_random - ); - return category; - }, -}; +const { set, get } = require("../../../utils/limited_redis"); +const Category = require("../../../models/CategoryModel"); +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +module.exports = { + getAllCategory: async () => { + const categories = await get("categories"); + if (categories) { + return JSON.parse(categories); + } + const number_random = HELPER.randomNumber(); + + const category = await Category.find(); + set( + "categories", + JSON.stringify(category), + CONSTANTS._1_DAYS_REDIS + number_random + ); + return category; + }, +}; diff --git a/backend/src/v1/user_api/services/category.service/category.service.js b/backend/src/v1/user_api/services/category.service/category.service.js index 2003f6b..59ae3e8 100644 --- a/backend/src/v1/user_api/services/category.service/category.service.js +++ b/backend/src/v1/user_api/services/category.service/category.service.js @@ -1,11 +1,11 @@ -const { getAllCategory } = require("./Crudcategories.service"); -module.exports = { - HandleGetCategory: async () => { - const category = await getAllCategory(); - return { - status: 200, - success: true, - element: category, - }; - }, -}; +const { getAllCategory } = require("./Crudcategories.service"); +module.exports = { + HandleGetCategory: async () => { + const category = await getAllCategory(); + return { + status: 200, + success: true, + element: category, + }; + }, +}; diff --git a/backend/src/v1/user_api/services/feedback.service/crud_feedbacl.service.js b/backend/src/v1/user_api/services/feedback.service/crud_feedbacl.service.js index 0ec3f70..39db8a7 100644 --- a/backend/src/v1/user_api/services/feedback.service/crud_feedbacl.service.js +++ b/backend/src/v1/user_api/services/feedback.service/crud_feedbacl.service.js @@ -1,25 +1,25 @@ -const { set, get } = require("../../../utils/limited_redis"); -const Category = require("../../../models/CategoryModel"); -const feedbacks = require("../../../models/feedBackModel"); -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -module.exports = { - sendFeedback: async ( - fullname, - email, - subject, - content, - read_at, - time_log_gmt7_string - ) => { - const newFeedback = new feedbacks({ - fullname, - email, - subject, - content, - send_at: time_log_gmt7_string, - read_at, - }); - await newFeedback.save(); - }, -}; +const { set, get } = require("../../../utils/limited_redis"); +const Category = require("../../../models/CategoryModel"); +const feedbacks = require("../../../models/feedBackModel"); +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +module.exports = { + sendFeedback: async ( + fullname, + email, + subject, + content, + read_at, + time_log_gmt7_string + ) => { + const newFeedback = new feedbacks({ + fullname, + email, + subject, + content, + send_at: time_log_gmt7_string, + read_at, + }); + await newFeedback.save(); + }, +}; diff --git a/backend/src/v1/user_api/services/feedback.service/feedback.service.js b/backend/src/v1/user_api/services/feedback.service/feedback.service.js index 5de862c..f5a8de0 100644 --- a/backend/src/v1/user_api/services/feedback.service/feedback.service.js +++ b/backend/src/v1/user_api/services/feedback.service/feedback.service.js @@ -1,69 +1,69 @@ -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -const { RedisPub } = require("../../../utils/limited_redis"); -const { sendFeedback } = require("./crud_feedbacl.service"); -module.exports = { - handleSendFeedback: async ({ - fullname, - email, - subject, - content, - read_at, - time_log_gmt7_string, - }) => { - if (!fullname || !email || !subject || !content) { - return { - status: 400, - success: false, - element: { - msg: "Please fill in full information", - }, - }; - } - const checkEmail = HELPER.validateEmail(email); - if (!checkEmail) { - return { - status: 307, - success: false, - element: { - msg: "Invalid Email", - }, - }; - } - return Promise.all([ - sendFeedback( - fullname, - email, - subject, - content, - read_at, - time_log_gmt7_string - ), - RedisPub( - "user_feedback", - JSON.stringify({ - email, - fullname, - content, - subject, - }) - ) - ]).then(result => { - return { - status: 200, - success: true, - element: { - msg: "Send Feedback Successfully !!", - }, - }; - }).catch((err) => { - return { - status: 400, - success: true, - element: { - msg: "Send Feedback Fail !!", - }, - }; - }) - }, -}; +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +const { RedisPub } = require("../../../utils/limited_redis"); +const { sendFeedback } = require("./crud_feedbacl.service"); +module.exports = { + handleSendFeedback: async ({ + fullname, + email, + subject, + content, + read_at, + time_log_gmt7_string, + }) => { + if (!fullname || !email || !subject || !content) { + return { + status: 400, + success: false, + element: { + msg: "Please fill in full information", + }, + }; + } + const checkEmail = HELPER.validateEmail(email); + if (!checkEmail) { + return { + status: 307, + success: false, + element: { + msg: "Invalid Email", + }, + }; + } + return Promise.all([ + sendFeedback( + fullname, + email, + subject, + content, + read_at, + time_log_gmt7_string + ), + RedisPub( + "user_feedback", + JSON.stringify({ + email, + fullname, + content, + subject, + }) + ) + ]).then(result => { + return { + status: 200, + success: true, + element: { + msg: "Send Feedback Successfully !!", + }, + }; + }).catch((err) => { + return { + status: 400, + success: true, + element: { + msg: "Send Feedback Fail !!", + }, + }; + }) + }, +}; diff --git a/backend/src/v1/user_api/services/order.service.js/history.service.js b/backend/src/v1/user_api/services/order.service.js/history.service.js index 421bbf6..9db1cd0 100644 --- a/backend/src/v1/user_api/services/order.service.js/history.service.js +++ b/backend/src/v1/user_api/services/order.service.js/history.service.js @@ -1,98 +1,98 @@ -const Payments = require("../../../models/PaymentModel"); -const CONSTANTS = require("../../../configs/constants"); -const PASSWORD = require("../../../utils/password"); -const STORAGE = require("../../../utils/storage"); -module.exports = { - handleHistoryOrder: async ({ user_id }) => { - try { - const history = await Payments.find({ - user_id, - deleteAt: CONSTANTS.DELETED_DISABLE, - }).sort({ createdAt: -1 }); - return { - status: 200, - success: true, - element: { - msg: "Get History Successfully", - history, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleDeleteFlagOrders: async ({ order_id, password, user_id }) => { - try { - const user_email = await STORAGE.checkUserIdExit(user_id); - if (!user_email) { - return { - status: 400, - success: false, - element: { - msg: "User Not Exit", - }, - } - } - const user_password = await PASSWORD.comparePassword( - password, - user_email.password - ); - if (!user_password) { - return { - status: 400, - success: false, - element: { - msg: "Password correct", - }, - } - } - await Payments.findByIdAndUpdate( - { _id: order_id }, - { - deleteAt: CONSTANTS.DELETED_ENABLE, - } - ); - return { - status: 200, - success: true, - element: { - msg: "Delete Payment Successfully", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleDetailOrders: async ({ order_id }) => { - try { - const payment = await Payments.findById(order_id); - return { - status: 200, - success: true, - element: { - payment, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, -}; +const Payments = require("../../../models/PaymentModel"); +const CONSTANTS = require("../../../configs/constants"); +const PASSWORD = require("../../../utils/password"); +const STORAGE = require("../../../utils/storage"); +module.exports = { + handleHistoryOrder: async ({ user_id }) => { + try { + const history = await Payments.find({ + user_id, + deleteAt: CONSTANTS.DELETED_DISABLE, + }).sort({ createdAt: -1 }); + return { + status: 200, + success: true, + element: { + msg: "Get History Successfully", + history, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleDeleteFlagOrders: async ({ order_id, password, user_id }) => { + try { + const user_email = await STORAGE.checkUserIdExit(user_id); + if (!user_email) { + return { + status: 400, + success: false, + element: { + msg: "User Not Exit", + }, + } + } + const user_password = await PASSWORD.comparePassword( + password, + user_email.password + ); + if (!user_password) { + return { + status: 400, + success: false, + element: { + msg: "Password correct", + }, + } + } + await Payments.findByIdAndUpdate( + { _id: order_id }, + { + deleteAt: CONSTANTS.DELETED_ENABLE, + } + ); + return { + status: 200, + success: true, + element: { + msg: "Delete Payment Successfully", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleDetailOrders: async ({ order_id }) => { + try { + const payment = await Payments.findById(order_id); + return { + status: 200, + success: true, + element: { + payment, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, +}; diff --git a/backend/src/v1/user_api/services/payment.service/curd_payment.service.js b/backend/src/v1/user_api/services/payment.service/curd_payment.service.js index 0137109..9955fc1 100644 --- a/backend/src/v1/user_api/services/payment.service/curd_payment.service.js +++ b/backend/src/v1/user_api/services/payment.service/curd_payment.service.js @@ -1,98 +1,98 @@ -const mongoose = require("mongoose"); -const Payments = require("../../../models/PaymentModel"); -const Users = require("../../../models/userModel"); -const Products = require("../../../models/ProductModel"); -const STORAGE = require("../../../utils/storage"); -const REDIS = require("../../../db/redis_db") -const { - get, - hgetall -} = require("../../../utils/limited_redis"); -const createPayment = async ({ - user_id, - cart, - paymentID, - address, - total, - total_apply_voucher, - voucher, -}) => { - const sess = await mongoose.startSession(); - sess.startTransaction(); - try { - const opts = { sess, returnOriginal: false }; - const user = await getUserId(user_id); - const { name, email } = user; - const newPayment = new Payments({ - user_id: user_id, - name, - email, - cart, - cost: total, - voucher: !voucher ? 0 : voucher, - discount: total_apply_voucher, - total: total, - paymentID, - address, - status: true, - }); - await newPayment.save(opts); - await sess.commitTransaction(); - sess.endSession(); - return { - success: true, - element: user, - }; - } catch (error) { - await sess.abortTransaction(); - sess.endSession(); - return { - success: false, - element: { - msg: false, - }, - }; - } -}; -const getUserId = async (user_id) => { - return await Users.findById(user_id).select( - "name email total_cart discount voucher" - ); -}; -const handlePayment = async ({ user_id }) => { - const data = await hgetall(user_id); - var cart = []; - for (var key in data) { - cart.push({ - cart: await Products.find({ _id: key }), - quantity: data[key], - }); - } - let total = 0; - let total_apply_voucher = 0; - const voucher = await get(`voucher_userId:${user_id}`); - for (let i = 0; i < cart.length; i++) { - total += cart[i].cart[0].price * cart[i].quantity; - } - total_apply_voucher = (total * JSON.parse(voucher)) / 100; - - return { cart, total, total_apply_voucher, voucher: JSON.parse(voucher) }; -} -const handlePaymentSuccess = async ({ cart, user_id }) => { - for (let i = 0; i < cart.length; i++) { - STORAGE.sold(cart[i].cart[0]._id, cart[i].quantity, cart[i].cart[0].sold); - STORAGE.stock( - cart[i].cart[0]._id, - cart[i].quantity, - cart[i].cart[0].countInStock - ); - } - let redis_multi = REDIS.pipeline().del(`cartUserId:${user_id}`).del("product_user").del(`voucher_userId:${user_id}`) - redis_multi.exec() -} -module.exports = { - createPayment, - getUserId, - handlePayment, - handlePaymentSuccess -}; +const mongoose = require("mongoose"); +const Payments = require("../../../models/PaymentModel"); +const Users = require("../../../models/userModel"); +const Products = require("../../../models/ProductModel"); +const STORAGE = require("../../../utils/storage"); +const REDIS = require("../../../db/redis_db") +const { + get, + hgetall +} = require("../../../utils/limited_redis"); +const createPayment = async ({ + user_id, + cart, + paymentID, + address, + total, + total_apply_voucher, + voucher, +}) => { + const sess = await mongoose.startSession(); + sess.startTransaction(); + try { + const opts = { sess, returnOriginal: false }; + const user = await getUserId(user_id); + const { name, email } = user; + const newPayment = new Payments({ + user_id: user_id, + name, + email, + cart, + cost: total, + voucher: !voucher ? 0 : voucher, + discount: total_apply_voucher, + total: total, + paymentID, + address, + status: true, + }); + await newPayment.save(opts); + await sess.commitTransaction(); + sess.endSession(); + return { + success: true, + element: user, + }; + } catch (error) { + await sess.abortTransaction(); + sess.endSession(); + return { + success: false, + element: { + msg: false, + }, + }; + } +}; +const getUserId = async (user_id) => { + return await Users.findById(user_id).select( + "name email total_cart discount voucher" + ); +}; +const handlePayment = async ({ user_id }) => { + const data = await hgetall(user_id); + var cart = []; + for (var key in data) { + cart.push({ + cart: await Products.find({ _id: key }), + quantity: data[key], + }); + } + let total = 0; + let total_apply_voucher = 0; + const voucher = await get(`voucher_userId:${user_id}`); + for (let i = 0; i < cart.length; i++) { + total += cart[i].cart[0].price * cart[i].quantity; + } + total_apply_voucher = (total * JSON.parse(voucher)) / 100; + + return { cart, total, total_apply_voucher, voucher: JSON.parse(voucher) }; +} +const handlePaymentSuccess = async ({ cart, user_id }) => { + for (let i = 0; i < cart.length; i++) { + STORAGE.sold(cart[i].cart[0]._id, cart[i].quantity, cart[i].cart[0].sold); + STORAGE.stock( + cart[i].cart[0]._id, + cart[i].quantity, + cart[i].cart[0].countInStock + ); + } + let redis_multi = REDIS.pipeline().del(`cartUserId:${user_id}`).del("product_user").del(`voucher_userId:${user_id}`) + redis_multi.exec() +} +module.exports = { + createPayment, + getUserId, + handlePayment, + handlePaymentSuccess +}; diff --git a/backend/src/v1/user_api/services/payment.service/payment.service.js b/backend/src/v1/user_api/services/payment.service/payment.service.js index 2d07cf3..a080ca4 100644 --- a/backend/src/v1/user_api/services/payment.service/payment.service.js +++ b/backend/src/v1/user_api/services/payment.service/payment.service.js @@ -1,309 +1,309 @@ -const Stripe = require("stripe"); -const { - hgetall, - sumQuantity, - get, - RedisPub, -} = require("../../../utils/limited_redis"); -const { createPayment, handlePayment, handlePaymentSuccess } = require("./curd_payment.service"); -const Products = require("../../../models/ProductModel"); -const CONFIGS = require("../../../configs/config") -const stripe = new Stripe(CONFIGS.STRIPE_KEY); -module.exports = { - handlePaymentTotal: async ({ user_id }) => { - try { - if (!user_id) { - return { - status: 400, - success: false, - element: { - msg: "User Fail !", - }, - }; - } - const data = await hgetall(user_id); - const quantity_sum = await sumQuantity({ user_id }); - - var cart = []; - for (var key in data) { - cart.push({ - cart: await Products.find({ _id: key }), - quantity_sum, - }); - } - let total = 0; - let total_apply_voucher = 0; - const voucher = await get(`voucher_userId:${user_id}`); - for (let i = 0; i < cart.length; i++) { - total += cart[i].cart[0].price * cart[i].quantity_sum; - } - total_apply_voucher = (total * JSON.parse(voucher)) / 100; - return { - status: 200, - success: true, - element: { - total, - voucher: JSON.parse(voucher), - total_apply_voucher, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handleCheckInStock: async ({ user_id }) => { - try { - const data = await hgetall(user_id); - var cart = []; - for (var key in data) { - cart.push({ - cart: await Products.find({ '_id': { $in: [key] } }), - quantity: data[key] - }); - } - let stockAvailable = true; - let outOfStock = []; - for (let i = 0; i < cart.length; i++) { - if (cart[i].cart[0].countInStock === 0 || cart[i].quantity > cart[i].cart[0].countInStock) { - stockAvailable = false; - outOfStock.push({ - outOfStock: cart[i].cart[0].name, - stock: cart[i].cart[0].countInStock, - }); - } - } - return { - status: stockAvailable ? 200 : 400, - success: stockAvailable ? true : false, - element: { - stockAvailable, - outOfStock, - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handlePaymentPaypal: async ({ user_id, paymentID, address }) => { - try { - let { cart, total, total_apply_voucher, voucher } = await handlePayment({ user_id }); - - const { success, element } = await createPayment({ - user_id, - cart, - paymentID, - address, - total, - total_apply_voucher, - voucher: voucher, - }); - if (!success) { - return { - status: 400, - success: false, - element: { - msg: "Payment Paypal Fail !!!", - }, - }; - } - RedisPub( - "user_payment_success", - JSON.stringify({ - email: element?.email, - name: element?.name, - }) - ); - handlePaymentSuccess({ cart, user_id }) - return { - status: 200, - success: true, - element: { - msg: "Payment Paypal Success !!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handlePaymentStripe: async ({ user_id, req }) => { - let UserId = await get(`userId:${user_id}`) - let data = await hgetall(user_id); - UserId = JSON.parse(UserId) - var cart = []; - for (var key in data) { - cart.push({ - cart: await Products.find({ _id: key }), - quantity: data[key], - }); - } - const params = { - submit_type: "pay", - mode: "payment", - payment_method_types: ["card"], - billing_address_collection: "auto", - shipping_address_collection: { - allowed_countries: ["US", "CA", "KE"], - }, - shipping_options: [ - { - shipping_rate_data: { - type: "fixed_amount", - fixed_amount: { - amount: 0, - currency: "usd", - }, - display_name: "Free shipping", - // Delivers between 5-7 business days - delivery_estimate: { - minimum: { - unit: "business_day", - value: 5, - }, - maximum: { - unit: "business_day", - value: 7, - }, - }, - }, - }, - { - shipping_rate_data: { - type: "fixed_amount", - fixed_amount: { - amount: 1500, - currency: "usd", - }, - display_name: "Next day air", - // Delivers in exactly 1 business day - delivery_estimate: { - minimum: { - unit: "business_day", - value: 1, - }, - maximum: { - unit: "business_day", - value: 1, - }, - }, - }, - }, - ], - phone_number_collection: { - enabled: true, - }, - customer_email: UserId.email, - line_items: cart.map((item) => { - return { - price_data: { - currency: "usd", - product_data: { - name: item.cart[0].name, - images: [item.cart[0].image.url], - description: item.cart[0].description, - }, - unit_amount: item.cart[0].price * 100, - }, - adjustable_quantity: { - enabled: true, - minimum: 1, - }, - quantity: item.quantity, - }; - }), - - // success_url: `${req.protocol}://${req.get("host")}/api/payment/stripe/success/{CHECKOUT_SESSION_ID}/${UserId._id}`, - // cancel_url: `${req.protocol}://${req.get("host")}/api/payment/cancel`, - success_url: `${CONFIGS.PORT_FRONTEND_ENV}/payment/stripe/success/{CHECKOUT_SESSION_ID}`, - cancel_url: `${CONFIGS.PORT_FRONTEND_ENV}/cart`, - }; - // Create Checkout Sessions from body params. - const session = await stripe.checkout.sessions.create(params); - - return { - status: 200, - success: true, - element: { - payment_url: session.url, - msg: "Url Payment Stripe !!", - }, - }; - }, - handlePaymentStripeSuccess: async ({ payment_id, user_id }) => { - try { - //data Stripe - const session = await stripe.checkout.sessions.retrieve(payment_id); - const customer = await stripe.customers.retrieve(session.customer); - - //Save Db - let { cart, total, total_apply_voucher, voucher } = await handlePayment({ user_id }); - const { success, element } = await createPayment({ - user_id, - cart, - paymentID: customer.id, - address: customer.shipping.address, - total, - total_apply_voucher, - voucher: voucher, - }); - if (!success) { - return { - status: 400, - success: false, - element: { - msg: "Payment Paypal Fail !!!", - }, - }; - } - RedisPub( - "user_payment_success", - JSON.stringify({ - email: element?.email, - name: element?.name, - }) - ); - handlePaymentSuccess({ cart, user_id }) - return { - status: 200, - success: true, - element: { - msg: "Payment Stripe Success !!", - }, - }; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - handlePaymentStripeCancel: async () => { - return { - status: 200, - success: true, - element: { - msg: "Payment Paypal Cancel !!", - }, - }; - } -}; +const Stripe = require("stripe"); +const { + hgetall, + sumQuantity, + get, + RedisPub, +} = require("../../../utils/limited_redis"); +const { createPayment, handlePayment, handlePaymentSuccess } = require("./curd_payment.service"); +const Products = require("../../../models/ProductModel"); +const CONFIGS = require("../../../configs/config") +const stripe = new Stripe(CONFIGS.STRIPE_KEY); +module.exports = { + handlePaymentTotal: async ({ user_id }) => { + try { + if (!user_id) { + return { + status: 400, + success: false, + element: { + msg: "User Fail !", + }, + }; + } + const data = await hgetall(user_id); + const quantity_sum = await sumQuantity({ user_id }); + + var cart = []; + for (var key in data) { + cart.push({ + cart: await Products.find({ _id: key }), + quantity_sum, + }); + } + let total = 0; + let total_apply_voucher = 0; + const voucher = await get(`voucher_userId:${user_id}`); + for (let i = 0; i < cart.length; i++) { + total += cart[i].cart[0].price * cart[i].quantity_sum; + } + total_apply_voucher = (total * JSON.parse(voucher)) / 100; + return { + status: 200, + success: true, + element: { + total, + voucher: JSON.parse(voucher), + total_apply_voucher, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handleCheckInStock: async ({ user_id }) => { + try { + const data = await hgetall(user_id); + var cart = []; + for (var key in data) { + cart.push({ + cart: await Products.find({ '_id': { $in: [key] } }), + quantity: data[key] + }); + } + let stockAvailable = true; + let outOfStock = []; + for (let i = 0; i < cart.length; i++) { + if (cart[i].cart[0].countInStock === 0 || cart[i].quantity > cart[i].cart[0].countInStock) { + stockAvailable = false; + outOfStock.push({ + outOfStock: cart[i].cart[0].name, + stock: cart[i].cart[0].countInStock, + }); + } + } + return { + status: stockAvailable ? 200 : 400, + success: stockAvailable ? true : false, + element: { + stockAvailable, + outOfStock, + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handlePaymentPaypal: async ({ user_id, paymentID, address }) => { + try { + let { cart, total, total_apply_voucher, voucher } = await handlePayment({ user_id }); + + const { success, element } = await createPayment({ + user_id, + cart, + paymentID, + address, + total, + total_apply_voucher, + voucher: voucher, + }); + if (!success) { + return { + status: 400, + success: false, + element: { + msg: "Payment Paypal Fail !!!", + }, + }; + } + RedisPub( + "user_payment_success", + JSON.stringify({ + email: element?.email, + name: element?.name, + }) + ); + handlePaymentSuccess({ cart, user_id }) + return { + status: 200, + success: true, + element: { + msg: "Payment Paypal Success !!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handlePaymentStripe: async ({ user_id, req }) => { + let UserId = await get(`userId:${user_id}`) + let data = await hgetall(user_id); + UserId = JSON.parse(UserId) + var cart = []; + for (var key in data) { + cart.push({ + cart: await Products.find({ _id: key }), + quantity: data[key], + }); + } + const params = { + submit_type: "pay", + mode: "payment", + payment_method_types: ["card"], + billing_address_collection: "auto", + shipping_address_collection: { + allowed_countries: ["US", "CA", "KE"], + }, + shipping_options: [ + { + shipping_rate_data: { + type: "fixed_amount", + fixed_amount: { + amount: 0, + currency: "usd", + }, + display_name: "Free shipping", + // Delivers between 5-7 business days + delivery_estimate: { + minimum: { + unit: "business_day", + value: 5, + }, + maximum: { + unit: "business_day", + value: 7, + }, + }, + }, + }, + { + shipping_rate_data: { + type: "fixed_amount", + fixed_amount: { + amount: 1500, + currency: "usd", + }, + display_name: "Next day air", + // Delivers in exactly 1 business day + delivery_estimate: { + minimum: { + unit: "business_day", + value: 1, + }, + maximum: { + unit: "business_day", + value: 1, + }, + }, + }, + }, + ], + phone_number_collection: { + enabled: true, + }, + customer_email: UserId.email, + line_items: cart.map((item) => { + return { + price_data: { + currency: "usd", + product_data: { + name: item.cart[0].name, + images: [item.cart[0].image.url], + description: item.cart[0].description, + }, + unit_amount: item.cart[0].price * 100, + }, + adjustable_quantity: { + enabled: true, + minimum: 1, + }, + quantity: item.quantity, + }; + }), + + // success_url: `${req.protocol}://${req.get("host")}/api/payment/stripe/success/{CHECKOUT_SESSION_ID}/${UserId._id}`, + // cancel_url: `${req.protocol}://${req.get("host")}/api/payment/cancel`, + success_url: `${CONFIGS.PORT_FRONTEND_ENV}/payment/stripe/success/{CHECKOUT_SESSION_ID}`, + cancel_url: `${CONFIGS.PORT_FRONTEND_ENV}/cart`, + }; + // Create Checkout Sessions from body params. + const session = await stripe.checkout.sessions.create(params); + + return { + status: 200, + success: true, + element: { + payment_url: session.url, + msg: "Url Payment Stripe !!", + }, + }; + }, + handlePaymentStripeSuccess: async ({ payment_id, user_id }) => { + try { + //data Stripe + const session = await stripe.checkout.sessions.retrieve(payment_id); + const customer = await stripe.customers.retrieve(session.customer); + + //Save Db + let { cart, total, total_apply_voucher, voucher } = await handlePayment({ user_id }); + const { success, element } = await createPayment({ + user_id, + cart, + paymentID: customer.id, + address: customer.shipping.address, + total, + total_apply_voucher, + voucher: voucher, + }); + if (!success) { + return { + status: 400, + success: false, + element: { + msg: "Payment Paypal Fail !!!", + }, + }; + } + RedisPub( + "user_payment_success", + JSON.stringify({ + email: element?.email, + name: element?.name, + }) + ); + handlePaymentSuccess({ cart, user_id }) + return { + status: 200, + success: true, + element: { + msg: "Payment Stripe Success !!", + }, + }; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + handlePaymentStripeCancel: async () => { + return { + status: 200, + success: true, + element: { + msg: "Payment Paypal Cancel !!", + }, + }; + } +}; diff --git a/backend/src/v1/user_api/services/product.service/getproduct.service.js b/backend/src/v1/user_api/services/product.service/getproduct.service.js index d58f379..ddfc611 100644 --- a/backend/src/v1/user_api/services/product.service/getproduct.service.js +++ b/backend/src/v1/user_api/services/product.service/getproduct.service.js @@ -1,77 +1,77 @@ -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -const Products = require("../../../models/ProductModel"); -const { get, set } = require("../../../utils/limited_redis"); -module.exports = { - async getallProductUser() { - try { - const product_user_redis = await get("product_user"); - if (product_user_redis) { - return JSON.parse(product_user_redis); - } - const number_random = HELPER.randomNumber(); - const product_user = await Products.aggregate([ - { - $project: { - _id: "$_id", - name: "$name", - price: "$price", - image: "$image", - description: "$description", - rating: "$rating", - numReviews: "$numReviews", - sold: "$sold", - countInStock: "$countInStock", - categories: "$categories", - latest: { - $cond: { - if: { $gt: ["$createdAt", "$updatedAt"] }, - then: "$createdAt", - else: "$updatedAt", - }, - }, - }, - }, - { $sort: { latest: -1 } }, - ]); - set( - "product_user", - JSON.stringify(product_user), - CONSTANTS._1_DAYS_REDIS + number_random - ); - return product_user; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, - async getallProductUserDetail(product_id) { - try { - var product_user_redis = await get("product_user"); - product_user_redis = JSON.parse(product_user_redis); - if (product_user_redis) { - return product_user_redis.filter((x) => x._id === product_id); - } - const product_detail = await Products.findById(product_id).populate({ - path: "reviews", - populate: { - path: "user", - }, - }); - return product_detail; - } catch (error) { - return { - status: 503, - success: false, - element: { - msg: "Server busy !!", - }, - }; - } - }, -}; +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +const Products = require("../../../models/ProductModel"); +const { get, set } = require("../../../utils/limited_redis"); +module.exports = { + async getallProductUser() { + try { + const product_user_redis = await get("product_user"); + if (product_user_redis) { + return JSON.parse(product_user_redis); + } + const number_random = HELPER.randomNumber(); + const product_user = await Products.aggregate([ + { + $project: { + _id: "$_id", + name: "$name", + price: "$price", + image: "$image", + description: "$description", + rating: "$rating", + numReviews: "$numReviews", + sold: "$sold", + countInStock: "$countInStock", + categories: "$categories", + latest: { + $cond: { + if: { $gt: ["$createdAt", "$updatedAt"] }, + then: "$createdAt", + else: "$updatedAt", + }, + }, + }, + }, + { $sort: { latest: -1 } }, + ]); + set( + "product_user", + JSON.stringify(product_user), + CONSTANTS._1_DAYS_REDIS + number_random + ); + return product_user; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, + async getallProductUserDetail(product_id) { + try { + var product_user_redis = await get("product_user"); + product_user_redis = JSON.parse(product_user_redis); + if (product_user_redis) { + return product_user_redis.filter((x) => x._id === product_id); + } + const product_detail = await Products.findById(product_id).populate({ + path: "reviews", + populate: { + path: "user", + }, + }); + return product_detail; + } catch (error) { + return { + status: 503, + success: false, + element: { + msg: "Server busy !!", + }, + }; + } + }, +}; diff --git a/backend/src/v1/user_api/services/product.service/product.service.js b/backend/src/v1/user_api/services/product.service/product.service.js index 449abaf..36c905b 100644 --- a/backend/src/v1/user_api/services/product.service/product.service.js +++ b/backend/src/v1/user_api/services/product.service/product.service.js @@ -1,152 +1,152 @@ -const { - hmset, - hincrby, - delCart, - hgetall, - hlen, - sumQuantity, - exists, -} = require("../../../utils/limited_redis"); -const { - getallProductUser, - getallProductUserDetail, -} = require("./getproduct.service"); -const Products = require("../../../models/ProductModel"); -const { - handleGetCommentProductId, -} = require("../review.service/review.service"); -module.exports = { - HandleGetProduct: async () => { - const products = await getallProductUser(); - return { - status: 200, - success: true, - element: products, - }; - }, - HandleGetProductDetail: async ({ product_id }) => { - const product_detail = await getallProductUserDetail(product_id); - return { - status: 200, - success: true, - element: { - product_detail, - comment: await handleGetCommentProductId(product_id), - }, - }; - }, - handleAddToCart: async ({ user_id, product_id, quantity }) => { - const check = await handleCheckOutOfStock(product_id, user_id); - if (check) { - return { - status: 400, - success: false, - element: { - msg: "Out of stock !!", - }, - }; - } - await hmset(user_id, product_id, quantity); - return { - status: 200, - success: true, - element: { - msg: "Add to cart Success !!!", - }, - }; - }, - handleIncrementCart: async ({ user_id, product_id, quantity }) => { - const check = await handleCheckOutOfStock(product_id, user_id); - if (check) { - return { - status: 400, - success: false, - element: { - msg: "Out of stock !!", - }, - }; - } - await hincrby(user_id, product_id, quantity); - return { - status: 200, - success: true, - element: { - msg: "Increment to cart Success !!!", - }, - }; - }, - handleDecrementCart: async ({ user_id, product_id, quantity }) => { - await hincrby(user_id, product_id, quantity); - const check = await handleCheckDecrementOutOfStock(product_id, user_id); - if (check) { - await delCart(user_id, product_id); - } - return { - status: 200, - success: true, - element: { - msg: "Decrement to cart Success !!!", - }, - }; - }, - handleDelCart: async ({ user_id, product_id }) => { - await delCart(user_id, product_id); - return { - status: 200, - success: true, - msg: "Del to cart Success !!!", - }; - }, - handleGetAddToCart: async ({ user_id }) => { - const cart_exit = await exists(`cartUserId:${user_id}`); - if (cart_exit === 0) { - return { - status: 200, - success: true, - element: { - msg: "Cart Empty !!!", - }, - }; - } - const data = await hgetall(user_id); - const data_length = await hlen(user_id); - const quantity_sum = await sumQuantity({ user_id }); - var product = []; - for (var key in data) { - product.push({ - product_id: await Products.find({ - _id: key, - }).select("name price countInStock image _id numReviews"), - quantity: data[key], - }); - } - - return { - status: 200, - success: true, - element: { - product, - data_length, - quantity_sum, - }, - }; - }, -}; -const handleCheckOutOfStock = async (product_id, user_id) => { - let product = await Products.findById(product_id).select("countInStock"); - let product_redis = await hgetall(user_id); - let check = product.countInStock <= product_redis[product._id]; - if (check) { - return true; - } - return false; -}; -const handleCheckDecrementOutOfStock = async (product_id, user_id) => { - let product = await Products.findById(product_id).select("countInStock"); - let product_redis = await hgetall(user_id); - let check = product_redis[product._id] === "0"; - if (check) { - return true; - } - return false; -}; +const { + hmset, + hincrby, + delCart, + hgetall, + hlen, + sumQuantity, + exists, +} = require("../../../utils/limited_redis"); +const { + getallProductUser, + getallProductUserDetail, +} = require("./getproduct.service"); +const Products = require("../../../models/ProductModel"); +const { + handleGetCommentProductId, +} = require("../review.service/review.service"); +module.exports = { + HandleGetProduct: async () => { + const products = await getallProductUser(); + return { + status: 200, + success: true, + element: products, + }; + }, + HandleGetProductDetail: async ({ product_id }) => { + const product_detail = await getallProductUserDetail(product_id); + return { + status: 200, + success: true, + element: { + product_detail, + comment: await handleGetCommentProductId(product_id), + }, + }; + }, + handleAddToCart: async ({ user_id, product_id, quantity }) => { + const check = await handleCheckOutOfStock(product_id, user_id); + if (check) { + return { + status: 400, + success: false, + element: { + msg: "Out of stock !!", + }, + }; + } + await hmset(user_id, product_id, quantity); + return { + status: 200, + success: true, + element: { + msg: "Add to cart Success !!!", + }, + }; + }, + handleIncrementCart: async ({ user_id, product_id, quantity }) => { + const check = await handleCheckOutOfStock(product_id, user_id); + if (check) { + return { + status: 400, + success: false, + element: { + msg: "Out of stock !!", + }, + }; + } + await hincrby(user_id, product_id, quantity); + return { + status: 200, + success: true, + element: { + msg: "Increment to cart Success !!!", + }, + }; + }, + handleDecrementCart: async ({ user_id, product_id, quantity }) => { + await hincrby(user_id, product_id, quantity); + const check = await handleCheckDecrementOutOfStock(product_id, user_id); + if (check) { + await delCart(user_id, product_id); + } + return { + status: 200, + success: true, + element: { + msg: "Decrement to cart Success !!!", + }, + }; + }, + handleDelCart: async ({ user_id, product_id }) => { + await delCart(user_id, product_id); + return { + status: 200, + success: true, + msg: "Del to cart Success !!!", + }; + }, + handleGetAddToCart: async ({ user_id }) => { + const cart_exit = await exists(`cartUserId:${user_id}`); + if (cart_exit === 0) { + return { + status: 200, + success: true, + element: { + msg: "Cart Empty !!!", + }, + }; + } + const data = await hgetall(user_id); + const data_length = await hlen(user_id); + const quantity_sum = await sumQuantity({ user_id }); + var product = []; + for (var key in data) { + product.push({ + product_id: await Products.find({ + _id: key, + }).select("name price countInStock image _id numReviews"), + quantity: data[key], + }); + } + + return { + status: 200, + success: true, + element: { + product, + data_length, + quantity_sum, + }, + }; + }, +}; +const handleCheckOutOfStock = async (product_id, user_id) => { + let product = await Products.findById(product_id).select("countInStock"); + let product_redis = await hgetall(user_id); + let check = product.countInStock <= product_redis[product._id]; + if (check) { + return true; + } + return false; +}; +const handleCheckDecrementOutOfStock = async (product_id, user_id) => { + let product = await Products.findById(product_id).select("countInStock"); + let product_redis = await hgetall(user_id); + let check = product_redis[product._id] === "0"; + if (check) { + return true; + } + return false; +}; diff --git a/backend/src/v1/user_api/services/review.service/crud_review.service.js b/backend/src/v1/user_api/services/review.service/crud_review.service.js index 26c2cdf..564df13 100644 --- a/backend/src/v1/user_api/services/review.service/crud_review.service.js +++ b/backend/src/v1/user_api/services/review.service/crud_review.service.js @@ -1,123 +1,123 @@ -const mongoose = require("mongoose"); -const Products = require("../../../models/ProductModel"); -const HELPER = require("../../../utils/helper"); -const CONTAINS = require("../../../configs/constants"); -const REDIS = require("../../../db/redis_db"); -module.exports = { - createReview: async (product, review) => { - const sess = await mongoose.startSession(); - sess.startTransaction(); - try { - const opts = { sess, returnOriginal: false }; - product.reviews.push(review); - product.numReviews = product.reviews.length; - product.rating = - product.reviews.reduce((acc, item) => item.rating + acc, 0) / - product.reviews.length; - - await product.save(opts); - await resetRedisProduct(); - await sess.commitTransaction(); - sess.endSession(); - return { - success: true, - }; - } catch (error) { - await sess.abortTransaction(); - sess.endSession(); - return { - success: false, - }; - } - }, - editReview: async (product, comment, review_id, user_id, product_id) => { - const sess = await mongoose.startSession(); - sess.startTransaction(); - try { - const opts = { sess, returnOriginal: false }; - for (var i = 0; i < product.reviews.length; i++) { - if ( - product.reviews[i]._id == review_id && - product.reviews[i].user == user_id - ) { - product.reviews[i].comment = comment; - } - } - await Products.findByIdAndUpdate( - { _id: product_id }, - - { - updatedAt: Date.now, - } - ); - await product.save(opts); - await sess.commitTransaction(); - sess.endSession(); - await resetRedisProduct(); - return { - success: true, - }; - } catch (error) { - await sess.abortTransaction(); - sess.endSession(); - return { - success: false, - }; - } - }, - deleteReview: async (product, user_id, product_id, review_id) => { - const sess = await mongoose.startSession(); - sess.startTransaction(); - try { - const opts = { sess, returnOriginal: false }; - if (product) { - for (var i = 0; i < product.reviews.length; i++) { - if ( - product.reviews[i]._id == review_id && - product.reviews[i].user == user_id - ) { - product.reviews.splice(i, 1); - } - } - - product.numReviews = product.reviews.length; - - if (product.reviews.length === 0) { - product.rating = 0; - } else { - product.rating = - product.reviews.reduce((acc, item) => item.rating + acc, 0) / - product.reviews.length; - } - } - await product.save(opts); - await resetRedisProduct(); - sess.endSession(); - await resetRedisProduct(); - return { - success: true, - }; - } catch (error) { - await sess.abortTransaction(); - sess.endSession(); - return { - success: false, - }; - } - }, -}; -const resetRedisProduct = async () => { - const random_number = HELPER.randomNumber(); - const product_user = await Products.find().sort({ - createdAt: 1, - }); - let redis_multi = REDIS.pipeline() - .del("product_user") - .set( - "product_user", - JSON.stringify(product_user), - CONTAINS._1_DAYS_REDIS + random_number - ); - redis_multi.exec() - -}; +const mongoose = require("mongoose"); +const Products = require("../../../models/ProductModel"); +const HELPER = require("../../../utils/helper"); +const CONTAINS = require("../../../configs/constants"); +const REDIS = require("../../../db/redis_db"); +module.exports = { + createReview: async (product, review) => { + const sess = await mongoose.startSession(); + sess.startTransaction(); + try { + const opts = { sess, returnOriginal: false }; + product.reviews.push(review); + product.numReviews = product.reviews.length; + product.rating = + product.reviews.reduce((acc, item) => item.rating + acc, 0) / + product.reviews.length; + + await product.save(opts); + await resetRedisProduct(); + await sess.commitTransaction(); + sess.endSession(); + return { + success: true, + }; + } catch (error) { + await sess.abortTransaction(); + sess.endSession(); + return { + success: false, + }; + } + }, + editReview: async (product, comment, review_id, user_id, product_id) => { + const sess = await mongoose.startSession(); + sess.startTransaction(); + try { + const opts = { sess, returnOriginal: false }; + for (var i = 0; i < product.reviews.length; i++) { + if ( + product.reviews[i]._id == review_id && + product.reviews[i].user == user_id + ) { + product.reviews[i].comment = comment; + } + } + await Products.findByIdAndUpdate( + { _id: product_id }, + + { + updatedAt: Date.now, + } + ); + await product.save(opts); + await sess.commitTransaction(); + sess.endSession(); + await resetRedisProduct(); + return { + success: true, + }; + } catch (error) { + await sess.abortTransaction(); + sess.endSession(); + return { + success: false, + }; + } + }, + deleteReview: async (product, user_id, product_id, review_id) => { + const sess = await mongoose.startSession(); + sess.startTransaction(); + try { + const opts = { sess, returnOriginal: false }; + if (product) { + for (var i = 0; i < product.reviews.length; i++) { + if ( + product.reviews[i]._id == review_id && + product.reviews[i].user == user_id + ) { + product.reviews.splice(i, 1); + } + } + + product.numReviews = product.reviews.length; + + if (product.reviews.length === 0) { + product.rating = 0; + } else { + product.rating = + product.reviews.reduce((acc, item) => item.rating + acc, 0) / + product.reviews.length; + } + } + await product.save(opts); + await resetRedisProduct(); + sess.endSession(); + await resetRedisProduct(); + return { + success: true, + }; + } catch (error) { + await sess.abortTransaction(); + sess.endSession(); + return { + success: false, + }; + } + }, +}; +const resetRedisProduct = async () => { + const random_number = HELPER.randomNumber(); + const product_user = await Products.find().sort({ + createdAt: 1, + }); + let redis_multi = REDIS.pipeline() + .del("product_user") + .set( + "product_user", + JSON.stringify(product_user), + CONTAINS._1_DAYS_REDIS + random_number + ); + redis_multi.exec() + +}; diff --git a/backend/src/v1/user_api/services/review.service/review.service.js b/backend/src/v1/user_api/services/review.service/review.service.js index 2bd069b..225d081 100644 --- a/backend/src/v1/user_api/services/review.service/review.service.js +++ b/backend/src/v1/user_api/services/review.service/review.service.js @@ -1,140 +1,140 @@ -const Products = require("../../../models/ProductModel"); -const Users = require("../../../models/userModel"); -const { - createReview, - editReview, - deleteReview, -} = require("./crud_review.service"); -module.exports = { - handleCreateReview: async ({ rating, comment, review_id, user_id }) => { - const product = await Products.findById(review_id); - if (product) { - const alreadyReviewed = await product.reviews.find( - (r) => r.user.toString() === user_id.toString() - ); - if (alreadyReviewed) { - return { - status: 400, - success: false, - element: { - msg: "Product already Reviewed", - }, - }; - } - const user = await Users.find({ _id: user_id }); - if (!user) { - return { - status: 305, - success: true, - element: { - msg: "Users not exit", - }, - }; - } - const review = { - rating: Number(rating), - comment, - user: user_id, - }; - const { success } = await createReview(product, review); - if (!success) { - return { - status: 400, - success: false, - element: { - msg: "Comment Fail", - }, - }; - } - return { - status: 200, - success: true, - element: { - msg: "Comment Product Success", - }, - }; - } - }, - handleEditReview: async ({ comment, user_id, product_id, review_id }) => { - const product = await Products.findById({ _id: product_id }); - const user = await Users.find({ _id: user_id }); - if (!user) { - return { - status: 305, - success: true, - element: { - msg: "Users not exit", - }, - }; - } - const { success } = await editReview( - product, - comment, - review_id, - user_id, - product_id - ); - if (!success) { - return { - status: 400, - success: false, - element: { - msg: "Edit Comment Fail", - }, - }; - } - return { - status: 200, - success: true, - element: { - msg: "Edit Review Success !!", - }, - }; - }, - handleDeleteReview: async ({ user_id, product_id, review_id }) => { - const product = await Products.findById({ _id: product_id }); - const user = await Users.find({ _id: user_id }); - if (!user) { - return { - status: 305, - success: true, - element: { - msg: "Users not exit", - }, - }; - } - const { success } = await deleteReview( - product, - user_id, - product_id, - review_id - ); - if (!success) { - return { - status: 400, - success: false, - element: { - msg: "Delete Comment Fail", - }, - }; - } - return { - status: 200, - success: true, - element: { - msg: "Delete Review Success !!", - }, - }; - }, - handleGetCommentProductId: async (product_id) => { - return await Products.findById(product_id) - .populate({ - path: "reviews", - populate: { - path: "user", - select: { name: 1, email: 1, image: 1 }, - }, - }) - .select("reviews"); - }, -}; +const Products = require("../../../models/ProductModel"); +const Users = require("../../../models/userModel"); +const { + createReview, + editReview, + deleteReview, +} = require("./crud_review.service"); +module.exports = { + handleCreateReview: async ({ rating, comment, review_id, user_id }) => { + const product = await Products.findById(review_id); + if (product) { + const alreadyReviewed = await product.reviews.find( + (r) => r.user.toString() === user_id.toString() + ); + if (alreadyReviewed) { + return { + status: 400, + success: false, + element: { + msg: "Product already Reviewed", + }, + }; + } + const user = await Users.find({ _id: user_id }); + if (!user) { + return { + status: 305, + success: true, + element: { + msg: "Users not exit", + }, + }; + } + const review = { + rating: Number(rating), + comment, + user: user_id, + }; + const { success } = await createReview(product, review); + if (!success) { + return { + status: 400, + success: false, + element: { + msg: "Comment Fail", + }, + }; + } + return { + status: 200, + success: true, + element: { + msg: "Comment Product Success", + }, + }; + } + }, + handleEditReview: async ({ comment, user_id, product_id, review_id }) => { + const product = await Products.findById({ _id: product_id }); + const user = await Users.find({ _id: user_id }); + if (!user) { + return { + status: 305, + success: true, + element: { + msg: "Users not exit", + }, + }; + } + const { success } = await editReview( + product, + comment, + review_id, + user_id, + product_id + ); + if (!success) { + return { + status: 400, + success: false, + element: { + msg: "Edit Comment Fail", + }, + }; + } + return { + status: 200, + success: true, + element: { + msg: "Edit Review Success !!", + }, + }; + }, + handleDeleteReview: async ({ user_id, product_id, review_id }) => { + const product = await Products.findById({ _id: product_id }); + const user = await Users.find({ _id: user_id }); + if (!user) { + return { + status: 305, + success: true, + element: { + msg: "Users not exit", + }, + }; + } + const { success } = await deleteReview( + product, + user_id, + product_id, + review_id + ); + if (!success) { + return { + status: 400, + success: false, + element: { + msg: "Delete Comment Fail", + }, + }; + } + return { + status: 200, + success: true, + element: { + msg: "Delete Review Success !!", + }, + }; + }, + handleGetCommentProductId: async (product_id) => { + return await Products.findById(product_id) + .populate({ + path: "reviews", + populate: { + path: "user", + select: { name: 1, email: 1, image: 1 }, + }, + }) + .select("reviews"); + }, +}; diff --git a/backend/src/v1/user_api/services/user.service/checkAuthUser.service.js b/backend/src/v1/user_api/services/user.service/checkAuthUser.service.js index 2a40494..873a5c3 100644 --- a/backend/src/v1/user_api/services/user.service/checkAuthUser.service.js +++ b/backend/src/v1/user_api/services/user.service/checkAuthUser.service.js @@ -1,393 +1,393 @@ -const { - deleteVerificationAndUser, - UpdateVerificationUser, -} = require("./createEditDeleteUser.service"); - -const STORAGE = require("../../../utils/storage"); -const HELPER = require("../../../utils/helper"); -const PASSWORD = require("../../../utils/password"); -const { checkVerification } = require("../../../utils/storage"); -const { getProfileId } = require("./getalluser.service"); -module.exports = { - CheckRegister: async ({ - email, - phone_number, - password, - confirmPassword, - date_of_birth, - }) => { - const checkEmail = HELPER.validateEmail(email); - if (!checkEmail) { - return { - status: 307, - success: false, - element: { - msg: "Invalid Email", - }, - }; - } - const user_email_exits = await STORAGE.checkUserExit(email); - - if (user_email_exits) { - return { - status: 307, - success: false, - element: { - msg: "Email already exits !!", - }, - }; - } - if (isNaN(phone_number)) { - return { - status: 306, - success: false, - element: { - msg: "Phone is must be number.", - }, - }; - } - const check_phone_vietnamese = HELPER.isVietnamesePhoneNumber(phone_number); - if (!check_phone_vietnamese) { - return { - status: 400, - success: false, - element: { - msg: "Incorrect phone number.", - }, - }; - } - const user_phone_exits = await STORAGE.checkPhoneExit(phone_number); - if (user_phone_exits.length > 0) { - return { - status: 306, - success: false, - element: { - msg: "Phone already exits.", - }, - }; - } - - const check_date = HELPER.validateDate(date_of_birth); - if (!date_of_birth) { - return { - status: 400, - success: false, - element: { - msg: "Please Choose A Date.", - }, - }; - } else if (!check_date) { - return { - status: 400, - success: false, - element: { - msg: "Incorrect Date .", - }, - }; - } - if (password !== confirmPassword) { - return { - status: 403, - success: false, - element: { - msg: "Password and confirm password does not match!", - }, - }; - } - if (password.length < 6) { - return { - status: 401, - success: false, - element: { - msg: "Password is at least 6 characters long. ", - }, - }; - } - - const user_password = HELPER.isPassword(password); - if (!user_password) { - return { - status: 401, - success: false, - element: { - msg: "Password not safe. ", - }, - }; - } - return { - success: true, - }; - }, - CheckVerificationUser: async (userId, uniqueString) => { - const check_user = await checkVerification(userId); - if (check_user) { - const expiredAt = check_user.expiresAt; - const hashedUniqueString = check_user.uniqueString; - if (expiredAt < Date.now()) { - await deleteVerificationAndUser(userId); - return { - success: false, - }; - } else { - const isMatch = await PASSWORD.comparePassword( - uniqueString, - hashedUniqueString - ); - if (isMatch) { - await UpdateVerificationUser(userId); - return { - success: true, - }; - } else { - return { - status: 400, - success: false, - element: { - msg: "Link invalid, unique string is not match", - }, - }; - } - } - } else { - return { - status: 400, - success: false, - element: { - msg: "Link is invalid because userid incorrect", - }, - }; - } - }, - CheckForget: async ({ email }) => { - const checkEmail = HELPER.validateEmail(email); - if (!checkEmail) { - return { - status: 307, - success: false, - element: { - msg: "Invalid Email", - }, - }; - } - const user_email_exits = await STORAGE.checkUserExit(email); - if (!user_email_exits) { - return { - status: 307, - success: false, - element: { - msg: "Email not exits.", - }, - }; - } - return { - success: true, - element: user_email_exits, - }; - }, - CheckResetPassword: async ({ password, confirmPassword, token }) => { - const resetPasswordToken = HELPER.resetPasswordToken(token); - const user = await STORAGE.CheckUserExpired(resetPasswordToken); - if (!user) { - return { - status: 400, - success: false, - element: { - msg: "Reset Password Token is invalid or has been expired", - }, - }; - } - if (!password && !confirmPassword) { - return { - status: 403, - success: false, - element: { - msg: "Password or confirmPassword are not empty.", - }, - }; - } - - if (password.length < 6) { - return { - status: 401, - success: false, - element: { - msg: "Password is at least 6 characters long. ", - }, - }; - } - - const user_password = HELPER.isPassword(password); - if (!user_password) { - return { - status: 401, - success: false, - element: { - msg: "Password not safe. ", - }, - }; - } - if (confirmPassword !== password) { - return { - status: 400, - success: false, - element: { - msg: "Password and confirm password does not match!", - }, - }; - } - return { - success: true, - element: user, - }; - }, - CheckChangePassword: async ({ - password, - oldPassword, - confirmPassword, - user_id, - }) => { - const user = await getProfileId(user_id); - if (!password) - return { - status: 400, - success: false, - element: { - msg: "Password are not empty.", - }, - }; - - if (!confirmPassword) - return { - status: 400, - success: false, - element: { - msg: " Confirm are not empty.", - }, - }; - - if (!oldPassword) - return { - status: 400, - success: false, - element: { - msg: "Old Password are not empty.", - }, - }; - - if (password.length < 6) - return { - status: 400, - success: false, - element: { - msg: "Password is at least 6 characters long.", - }, - }; - - const reg = HELPER.isPassword(password); - if (!reg) { - return { - status: 400, - success: false, - element: { - msg: "Includes 6 characters, uppercase, lowercase and some and special characters.", - }, - }; - } - if (confirmPassword !== password) { - return { - status: 400, - success: false, - element: { - msg: "Password and confirm password does not match!", - }, - }; - } - - const isMatch = await PASSWORD.comparePassword(oldPassword, user.password); - if (!isMatch) { - return { - status: 400, - success: false, - element: { - msg: " Old Password Incorrect", - }, - }; - } - return { - success: true, - element: user, - }; - }, - CheckUpdateProfile: async ({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }) => { - if ((!name, !image, !phone_number, !sex, !date_of_birth)) { - return { - status: 308, - success: false, - element: { - msg: "Invalid Empty", - }, - }; - } - if (isNaN(phone_number)) { - return { - status: 306, - success: false, - element: { - msg: "Phone is must be number.", - }, - }; - } - - const check_phone_vietnamese = HELPER.isVietnamesePhoneNumber(phone_number); - if (!check_phone_vietnamese) { - return { - status: 400, - success: false, - element: { - msg: "Incorrect phone number.", - }, - }; - } - const checkPhoneUserExit = await STORAGE.checkPhoneExitExceptUserMain( - user_id, - phone_number - ); - if (checkPhoneUserExit.length > 0) { - return { - status: 306, - success: false, - element: { - msg: "Phone Exited", - }, - }; - } - const check_date = HELPER.validateDate(date_of_birth); - if (!date_of_birth) { - return { - status: 400, - success: false, - element: { - msg: "Please Choose A Date.", - }, - }; - } else if (!check_date) { - return { - status: 400, - success: false, - element: { - msg: "Incorrect Date .", - }, - }; - } - return { - success: true, - }; - }, -}; +const { + deleteVerificationAndUser, + UpdateVerificationUser, +} = require("./createEditDeleteUser.service"); + +const STORAGE = require("../../../utils/storage"); +const HELPER = require("../../../utils/helper"); +const PASSWORD = require("../../../utils/password"); +const { checkVerification } = require("../../../utils/storage"); +const { getProfileId } = require("./getalluser.service"); +module.exports = { + CheckRegister: async ({ + email, + phone_number, + password, + confirmPassword, + date_of_birth, + }) => { + const checkEmail = HELPER.validateEmail(email); + if (!checkEmail) { + return { + status: 307, + success: false, + element: { + msg: "Invalid Email", + }, + }; + } + const user_email_exits = await STORAGE.checkUserExit(email); + + if (user_email_exits) { + return { + status: 307, + success: false, + element: { + msg: "Email already exits !!", + }, + }; + } + if (isNaN(phone_number)) { + return { + status: 306, + success: false, + element: { + msg: "Phone is must be number.", + }, + }; + } + const check_phone_vietnamese = HELPER.isVietnamesePhoneNumber(phone_number); + if (!check_phone_vietnamese) { + return { + status: 400, + success: false, + element: { + msg: "Incorrect phone number.", + }, + }; + } + const user_phone_exits = await STORAGE.checkPhoneExit(phone_number); + if (user_phone_exits.length > 0) { + return { + status: 306, + success: false, + element: { + msg: "Phone already exits.", + }, + }; + } + + const check_date = HELPER.validateDate(date_of_birth); + if (!date_of_birth) { + return { + status: 400, + success: false, + element: { + msg: "Please Choose A Date.", + }, + }; + } else if (!check_date) { + return { + status: 400, + success: false, + element: { + msg: "Incorrect Date .", + }, + }; + } + if (password !== confirmPassword) { + return { + status: 403, + success: false, + element: { + msg: "Password and confirm password does not match!", + }, + }; + } + if (password.length < 6) { + return { + status: 401, + success: false, + element: { + msg: "Password is at least 6 characters long. ", + }, + }; + } + + const user_password = HELPER.isPassword(password); + if (!user_password) { + return { + status: 401, + success: false, + element: { + msg: "Password not safe. ", + }, + }; + } + return { + success: true, + }; + }, + CheckVerificationUser: async (userId, uniqueString) => { + const check_user = await checkVerification(userId); + if (check_user) { + const expiredAt = check_user.expiresAt; + const hashedUniqueString = check_user.uniqueString; + if (expiredAt < Date.now()) { + await deleteVerificationAndUser(userId); + return { + success: false, + }; + } else { + const isMatch = await PASSWORD.comparePassword( + uniqueString, + hashedUniqueString + ); + if (isMatch) { + await UpdateVerificationUser(userId); + return { + success: true, + }; + } else { + return { + status: 400, + success: false, + element: { + msg: "Link invalid, unique string is not match", + }, + }; + } + } + } else { + return { + status: 400, + success: false, + element: { + msg: "Link is invalid because userid incorrect", + }, + }; + } + }, + CheckForget: async ({ email }) => { + const checkEmail = HELPER.validateEmail(email); + if (!checkEmail) { + return { + status: 307, + success: false, + element: { + msg: "Invalid Email", + }, + }; + } + const user_email_exits = await STORAGE.checkUserExit(email); + if (!user_email_exits) { + return { + status: 307, + success: false, + element: { + msg: "Email not exits.", + }, + }; + } + return { + success: true, + element: user_email_exits, + }; + }, + CheckResetPassword: async ({ password, confirmPassword, token }) => { + const resetPasswordToken = HELPER.resetPasswordToken(token); + const user = await STORAGE.CheckUserExpired(resetPasswordToken); + if (!user) { + return { + status: 400, + success: false, + element: { + msg: "Reset Password Token is invalid or has been expired", + }, + }; + } + if (!password && !confirmPassword) { + return { + status: 403, + success: false, + element: { + msg: "Password or confirmPassword are not empty.", + }, + }; + } + + if (password.length < 6) { + return { + status: 401, + success: false, + element: { + msg: "Password is at least 6 characters long. ", + }, + }; + } + + const user_password = HELPER.isPassword(password); + if (!user_password) { + return { + status: 401, + success: false, + element: { + msg: "Password not safe. ", + }, + }; + } + if (confirmPassword !== password) { + return { + status: 400, + success: false, + element: { + msg: "Password and confirm password does not match!", + }, + }; + } + return { + success: true, + element: user, + }; + }, + CheckChangePassword: async ({ + password, + oldPassword, + confirmPassword, + user_id, + }) => { + const user = await getProfileId(user_id); + if (!password) + return { + status: 400, + success: false, + element: { + msg: "Password are not empty.", + }, + }; + + if (!confirmPassword) + return { + status: 400, + success: false, + element: { + msg: " Confirm are not empty.", + }, + }; + + if (!oldPassword) + return { + status: 400, + success: false, + element: { + msg: "Old Password are not empty.", + }, + }; + + if (password.length < 6) + return { + status: 400, + success: false, + element: { + msg: "Password is at least 6 characters long.", + }, + }; + + const reg = HELPER.isPassword(password); + if (!reg) { + return { + status: 400, + success: false, + element: { + msg: "Includes 6 characters, uppercase, lowercase and some and special characters.", + }, + }; + } + if (confirmPassword !== password) { + return { + status: 400, + success: false, + element: { + msg: "Password and confirm password does not match!", + }, + }; + } + + const isMatch = await PASSWORD.comparePassword(oldPassword, user.password); + if (!isMatch) { + return { + status: 400, + success: false, + element: { + msg: " Old Password Incorrect", + }, + }; + } + return { + success: true, + element: user, + }; + }, + CheckUpdateProfile: async ({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }) => { + if ((!name, !image, !phone_number, !sex, !date_of_birth)) { + return { + status: 308, + success: false, + element: { + msg: "Invalid Empty", + }, + }; + } + if (isNaN(phone_number)) { + return { + status: 306, + success: false, + element: { + msg: "Phone is must be number.", + }, + }; + } + + const check_phone_vietnamese = HELPER.isVietnamesePhoneNumber(phone_number); + if (!check_phone_vietnamese) { + return { + status: 400, + success: false, + element: { + msg: "Incorrect phone number.", + }, + }; + } + const checkPhoneUserExit = await STORAGE.checkPhoneExitExceptUserMain( + user_id, + phone_number + ); + if (checkPhoneUserExit.length > 0) { + return { + status: 306, + success: false, + element: { + msg: "Phone Exited", + }, + }; + } + const check_date = HELPER.validateDate(date_of_birth); + if (!date_of_birth) { + return { + status: 400, + success: false, + element: { + msg: "Please Choose A Date.", + }, + }; + } else if (!check_date) { + return { + status: 400, + success: false, + element: { + msg: "Incorrect Date .", + }, + }; + } + return { + success: true, + }; + }, +}; diff --git a/backend/src/v1/user_api/services/user.service/createEditDeleteUser.service.js b/backend/src/v1/user_api/services/user.service/createEditDeleteUser.service.js index ceb991c..8eebc51 100644 --- a/backend/src/v1/user_api/services/user.service/createEditDeleteUser.service.js +++ b/backend/src/v1/user_api/services/user.service/createEditDeleteUser.service.js @@ -1,118 +1,118 @@ -const { updateProfileId } = require("./getalluser.service"); -const Users = require("../../../models/userModel"); -const UserVerifications = require("../../../models/userVerificationModel"); -const CONSTANTS = require("../../../configs/constants"); -const HELPER = require("../../../utils/helper"); -const { - destroyStorage, -} = require("../../../upload_cloudinary/services/uploadStorage.service"); - -// ** Delete Verification -const deleteVerification = async (userId) => { - UserVerifications.deleteOne({ userId }); -}; -//** Create User */ -const createUser = async ( - name, - email, - password, - sex, - date_of_birth, - phone_number -) => { - const newUser = new Users({ - name, - email, - password, - sex, - date_of_birth, - phone_number, - }); - return await newUser.save(); -}; -//* Update Profile */ -const UpdateProfile = async ({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, -}) => { - return Promise.all([deleteImageAutoCloud(user_id), Users.findOneAndUpdate( - { _id: user_id }, - { - name, - image, - phone_number, - sex, - date_of_birth, - } - ), - updateProfileId(user_id) - ]).then(() => { - return true; - }).catch(err => { - return false; - }) -}; -//** Delete User And Verification */ -const deleteVerificationAndUser = async (userId) => { - return Promise.all([ - UserVerifications.deleteOne({ userId }), Users.deleteOne({ _id: userId }) - ]).then((rs) => { - return true; - }).catch(err => { - return false; - }) -}; -//** Update Verification CheckEmail */ -const UpdateVerificationUser = async (userId) => { - - return Promise.all([ - Users.findOneAndUpdate( - { _id: userId }, - { - verified: CONSTANTS.DELETED_ENABLE, - checkLogin: CONSTANTS.DELETED_ENABLE, - } - ), deleteVerification(userId) - ]).then((rs) => { - return true; - }).catch(err => { - return false; - }) - return true; -}; -//** Create_acceptToken */ -const NewAcceptToken = (user) => { - return HELPER.createAccessToken(user); -}; -//** Update Password */ -const UpdatePassword = async ({ user_id, password }) => { - return Users.findByIdAndUpdate( - { _id: user_id }, - { password: password }, - { new: true } - ); -}; -//** Delete Image Cloud auto */ -const deleteImageAutoCloud = async (user_id) => { - const user = await Users.findById(user_id); - let public_id = user?.image?.public_id - return destroyStorage(public_id); -}; -module.exports = { - //* CreateUser - createUser, - //** Delete User And Verification */ - deleteVerificationAndUser, - // ** Update User Check Verification - UpdateVerificationUser, - //** New access TokenId */ - NewAcceptToken, - //* Update Password - UpdatePassword, - //* Update Profile - UpdateProfile, -}; +const { updateProfileId } = require("./getalluser.service"); +const Users = require("../../../models/userModel"); +const UserVerifications = require("../../../models/userVerificationModel"); +const CONSTANTS = require("../../../configs/constants"); +const HELPER = require("../../../utils/helper"); +const { + destroyStorage, +} = require("../../../upload_cloudinary/services/uploadStorage.service"); + +// ** Delete Verification +const deleteVerification = async (userId) => { + UserVerifications.deleteOne({ userId }); +}; +//** Create User */ +const createUser = async ( + name, + email, + password, + sex, + date_of_birth, + phone_number +) => { + const newUser = new Users({ + name, + email, + password, + sex, + date_of_birth, + phone_number, + }); + return await newUser.save(); +}; +//* Update Profile */ +const UpdateProfile = async ({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, +}) => { + return Promise.all([deleteImageAutoCloud(user_id), Users.findOneAndUpdate( + { _id: user_id }, + { + name, + image, + phone_number, + sex, + date_of_birth, + } + ), + updateProfileId(user_id) + ]).then(() => { + return true; + }).catch(err => { + return false; + }) +}; +//** Delete User And Verification */ +const deleteVerificationAndUser = async (userId) => { + return Promise.all([ + UserVerifications.deleteOne({ userId }), Users.deleteOne({ _id: userId }) + ]).then((rs) => { + return true; + }).catch(err => { + return false; + }) +}; +//** Update Verification CheckEmail */ +const UpdateVerificationUser = async (userId) => { + + return Promise.all([ + Users.findOneAndUpdate( + { _id: userId }, + { + verified: CONSTANTS.DELETED_ENABLE, + checkLogin: CONSTANTS.DELETED_ENABLE, + } + ), deleteVerification(userId) + ]).then((rs) => { + return true; + }).catch(err => { + return false; + }) + return true; +}; +//** Create_acceptToken */ +const NewAcceptToken = (user) => { + return HELPER.createAccessToken(user); +}; +//** Update Password */ +const UpdatePassword = async ({ user_id, password }) => { + return Users.findByIdAndUpdate( + { _id: user_id }, + { password: password }, + { new: true } + ); +}; +//** Delete Image Cloud auto */ +const deleteImageAutoCloud = async (user_id) => { + const user = await Users.findById(user_id); + let public_id = user?.image?.public_id + return destroyStorage(public_id); +}; +module.exports = { + //* CreateUser + createUser, + //** Delete User And Verification */ + deleteVerificationAndUser, + // ** Update User Check Verification + UpdateVerificationUser, + //** New access TokenId */ + NewAcceptToken, + //* Update Password + UpdatePassword, + //* Update Profile + UpdateProfile, +}; diff --git a/backend/src/v1/user_api/services/user.service/getalluser.service.js b/backend/src/v1/user_api/services/user.service/getalluser.service.js index ed72455..d9a519f 100644 --- a/backend/src/v1/user_api/services/user.service/getalluser.service.js +++ b/backend/src/v1/user_api/services/user.service/getalluser.service.js @@ -1,52 +1,52 @@ -const Users = require("../../../models/userModel"); -const Orders = require("../../../models/PaymentModel"); -const HELPER = require("../../../utils/helper"); -const CONTAINS = require("../../../configs/constants"); -const { set, get, del } = require("../../../utils/limited_redis"); -const REDIS = require("../../../db/redis_db"); -const getProfileId = async (userId) => { - const user_redis = await get(`userId:${userId}`); - if (user_redis) { - return JSON.parse(user_redis); - } - const random_number = HELPER.randomNumber(); - const user = await Users.findById(userId).select("+password"); - if (user) { - set( - `userId:${userId}`, - JSON.stringify(user), - CONTAINS._1_DAYS_REDIS + random_number - ); - } - return user; -}; -const getInfoEveryUser = async (userId) => { - const user = await Users.findById(userId).select( - "name email phone date_of_birth image sex phone_number" - ); - return user; -}; -const getOrderInfoEveryUser = async (userId) => { - const order_user = await Orders.find({ user_id: userId }).select("_id"); - return order_user.length; -}; - -const updateProfileId = async (userId) => { - const random_number = HELPER.randomNumber(); - const user = await Users.findById(userId).select("+password"); - let redis_multi = REDIS.pipeline() - .del(`userId:${userId}`) - .set( - `userId:${userId}`, - JSON.stringify(user), - CONTAINS._1_DAYS_REDIS + random_number - ); - redis_multi.exec() -}; - -module.exports = { - getProfileId, - updateProfileId, - getInfoEveryUser, - getOrderInfoEveryUser, -}; +const Users = require("../../../models/userModel"); +const Orders = require("../../../models/PaymentModel"); +const HELPER = require("../../../utils/helper"); +const CONTAINS = require("../../../configs/constants"); +const { set, get, del } = require("../../../utils/limited_redis"); +const REDIS = require("../../../db/redis_db"); +const getProfileId = async (userId) => { + const user_redis = await get(`userId:${userId}`); + if (user_redis) { + return JSON.parse(user_redis); + } + const random_number = HELPER.randomNumber(); + const user = await Users.findById(userId).select("+password"); + if (user) { + set( + `userId:${userId}`, + JSON.stringify(user), + CONTAINS._1_DAYS_REDIS + random_number + ); + } + return user; +}; +const getInfoEveryUser = async (userId) => { + const user = await Users.findById(userId).select( + "name email phone date_of_birth image sex phone_number" + ); + return user; +}; +const getOrderInfoEveryUser = async (userId) => { + const order_user = await Orders.find({ user_id: userId }).select("_id"); + return order_user.length; +}; + +const updateProfileId = async (userId) => { + const random_number = HELPER.randomNumber(); + const user = await Users.findById(userId).select("+password"); + let redis_multi = REDIS.pipeline() + .del(`userId:${userId}`) + .set( + `userId:${userId}`, + JSON.stringify(user), + CONTAINS._1_DAYS_REDIS + random_number + ); + redis_multi.exec() +}; + +module.exports = { + getProfileId, + updateProfileId, + getInfoEveryUser, + getOrderInfoEveryUser, +}; diff --git a/backend/src/v1/user_api/services/user.service/newVerification.service.js b/backend/src/v1/user_api/services/user.service/newVerification.service.js index dde8f04..8c587b4 100644 --- a/backend/src/v1/user_api/services/user.service/newVerification.service.js +++ b/backend/src/v1/user_api/services/user.service/newVerification.service.js @@ -1,13 +1,13 @@ -const UserVerifications = require("../../../models/userVerificationModel"); -const CONSTANTS = require("../../../configs/constants"); -module.exports = { - Verification: async ({ newUser, hashedUniqueString }) => { - const newVerification = new UserVerifications({ - userId: newUser.id, - uniqueString: hashedUniqueString, - createdAt: Date.now(), - expiresAt: Date.now() + CONSTANTS._45_MINUTES, - }); - return newVerification.save(); - }, -}; +const UserVerifications = require("../../../models/userVerificationModel"); +const CONSTANTS = require("../../../configs/constants"); +module.exports = { + Verification: async ({ newUser, hashedUniqueString }) => { + const newVerification = new UserVerifications({ + userId: newUser.id, + uniqueString: hashedUniqueString, + createdAt: Date.now(), + expiresAt: Date.now() + CONSTANTS._45_MINUTES, + }); + return newVerification.save(); + }, +}; diff --git a/backend/src/v1/user_api/services/user.service/sendEmail.service.js b/backend/src/v1/user_api/services/user.service/sendEmail.service.js index 3b449d8..0bcc958 100644 --- a/backend/src/v1/user_api/services/user.service/sendEmail.service.js +++ b/backend/src/v1/user_api/services/user.service/sendEmail.service.js @@ -1,45 +1,45 @@ -const nodeMailer = require("nodemailer"); -const hbs = require("nodemailer-express-handlebars"); -const path = require("path"); -const CONFIGS = require("../../../configs/config"); -require("dotenv").config(); -const sendEmail = async (options) => { - const transporter = nodeMailer.createTransport({ - host: CONFIGS.SMTP_HOST, - port: CONFIGS.SMTP_PORT, - secure: false, // use SSL - service: CONFIGS.SMTP_SERVICE, - auth: { - user: CONFIGS.SMTP_MAIL, - pass: CONFIGS.SMTP_PASSWORD, - }, - tls: { - rejectUnauthorized: false, - }, - }); - - const handlebarOptions = { - viewEngine: { - extName: ".html", - partialsDir: path.resolve("./src/v1/views"), - defaultLayout: false, - }, - viewPath: path.resolve("./src/v1/views"), - extName: ".html", - }; - - transporter.use("compile", hbs(handlebarOptions)); - - const mailOptions = { - from: options.from, - to: options.to, - subject: options.subject, - attachments: options.attachments, - template: options.template, - context: options.context, - html: options.html, - }; - await transporter.sendMail(mailOptions); -}; - -module.exports = sendEmail; +const nodeMailer = require("nodemailer"); +const hbs = require("nodemailer-express-handlebars"); +const path = require("path"); +const CONFIGS = require("../../../configs/config"); +require("dotenv").config(); +const sendEmail = async (options) => { + const transporter = nodeMailer.createTransport({ + host: CONFIGS.SMTP_HOST, + port: CONFIGS.SMTP_PORT, + secure: false, // use SSL + service: CONFIGS.SMTP_SERVICE, + auth: { + user: CONFIGS.SMTP_MAIL, + pass: CONFIGS.SMTP_PASSWORD, + }, + tls: { + rejectUnauthorized: false, + }, + }); + + const handlebarOptions = { + viewEngine: { + extName: ".html", + partialsDir: path.resolve("./src/v1/views"), + defaultLayout: false, + }, + viewPath: path.resolve("./src/v1/views"), + extName: ".html", + }; + + transporter.use("compile", hbs(handlebarOptions)); + + const mailOptions = { + from: options.from, + to: options.to, + subject: options.subject, + attachments: options.attachments, + template: options.template, + context: options.context, + html: options.html, + }; + await transporter.sendMail(mailOptions); +}; + +module.exports = sendEmail; diff --git a/backend/src/v1/user_api/services/user.service/user.service.js b/backend/src/v1/user_api/services/user.service/user.service.js index 9cf0242..4e0f247 100644 --- a/backend/src/v1/user_api/services/user.service/user.service.js +++ b/backend/src/v1/user_api/services/user.service/user.service.js @@ -1,480 +1,480 @@ -const { v4: uuidv4 } = require("uuid"); -const { - createAccessToken, - createRefreshToken, - randomString, -} = require("../../../utils/helper"); -const { - LoginEmail, - LoginPhone, - CheckEmail, - RegisterSocial, -} = require("./userType.service"); -const { - CheckRegister, - CheckForget, - CheckResetPassword, - CheckChangePassword, - CheckUpdateProfile, -} = require("./checkAuthUser.service"); -const { UserSpam } = require("./userSpam.service"); -const { - callDataGoogle, - saveCookies, - callDataFacebook, - GenerateRefreshToken, -} = require("../../../utils/storage"); -const { - Verification, -} = require("../../services/user.service/newVerification.service"); -const { - createUser, - NewAcceptToken, - UpdatePassword, - UpdateProfile, -} = require("./createEditDeleteUser.service"); -const { - getProfileId, - getInfoEveryUser, - getOrderInfoEveryUser, -} = require("./getalluser.service"); -const { get, RedisPub, del } = require("../../../utils/limited_redis"); -const PASSWORD = require("../../../utils/password"); -const STORAGE = require("../../../utils/storage"); -const CONSTANTS = require("../../../configs/constants"); -const CONFIGS = require("../../../configs/config"); -const Users = require("../../../models/userModel"); -module.exports = { - //*--------------- Handle Authentication Users --------------- - checkLoginUser: async ({ - email_phone, - password, - token, - GetIPUser, - res, - session, - }) => { - const { status, _ttl, msg } = UserSpam(GetIPUser); - if (status === 400) { - return { - status, - success: false, - element: { - _ttl, - msg, - }, - }; - } - let result_user = null; - if (email_phone.includes("@") == true) { - result_user = await LoginEmail(email_phone, password); - } else { - result_user = await LoginPhone(email_phone); - } - if (!result_user || result_user.success === false) { - return { - status: result_user?.status, - success: result_user?.success, - element: result_user.element, - }; - } - session.users = { - id: result_user._id, - email: email_phone, - }; - session.save(); - const accessToken = createAccessToken({ id: result_user._id }); - const refreshToken = await GenerateRefreshToken({ id: result_user._id }); - saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - }, - handleLoginPhoneFirebase: async ({ phone_number, session, res }) => { - const user_phone = await STORAGE.checkPhoneExitFirebase(phone_number); - if (!user_phone) { - return { - status: 400, - success: false, - element: { - msg: "Phone Numbers Not Exit !!!", - }, - }; - } - session.users = { - id: user_phone._id, - email: user_phone.email, - }; - session.save(); - const accessToken = createAccessToken({ id: user_phone._id }); - const refreshToken = await GenerateRefreshToken({ id: user_phone._id }); - saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - }, - checkLoginGoogle: async ({ tokenId, res }) => { - const user_google = await callDataGoogle(tokenId); - const { name, email, picture } = user_google.payload; - let result_user = await CheckEmail(email); - if (result_user) { - const accessToken = createAccessToken({ id: result_user._id }); - const refreshToken = await GenerateRefreshToken({ id: result_user._id }); - saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - } else { - var password = randomString(10); - let newUser = await RegisterSocial({ - name, - email, - picture, - password, - }); - if (!newUser) { - return { - status: 503, - success: false, - }; - } - const accessToken = createAccessToken({ id: newUser._id }); - const refreshToken = createRefreshToken({ id: newUser._id }); - saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - } - }, - checkLoginFacebook: async ({ userID, accessToken, res }) => { - let response = await callDataFacebook(userID, accessToken); - const { email, name, picture } = response; - let result_user = await CheckEmail(email); - if (result_user) { - const accessToken = createAccessToken({ id: result_user._id }); - // const refreshToken = createRefreshToken({ id: result_user._id }); - const refreshToken = await GenerateRefreshToken({ id: result_user._id }); - - saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - } else { - var password = randomString(10); - let newUser = await RegisterSocial({ - name, - email, - picture, - password, - }); - if (!newUser) { - return { - status: 503, - success: false, - }; - } - const accessToken = createAccessToken({ id: newUser._id }); - const refreshToken = createRefreshToken({ id: newUser._id }); - saveCookies(res, refreshToken); - return { - status: 200, - success: true, - element: { - accessToken, - refreshToken, - }, - }; - } - }, - checkRegisterUser: async ({ - name, - email, - password, - confirmPassword, - sex, - date_of_birth, - phone_number, - token, - req, - }) => { - const { status, success, element } = await CheckRegister({ - email, - phone_number, - password, - confirmPassword, - date_of_birth, - }); - if (!success) { - return { - status, - success, - element, - }; - } - const password_user = await PASSWORD.encodePassword(password); - let newUser = await createUser( - name, - email, - password_user, - sex, - date_of_birth, - phone_number - ); - const resetPasswordUrl = `${req.protocol}://${req.get("host")}/`; - - const currentUrl = resetPasswordUrl; - const uniqueString = uuidv4() + newUser.id; - const hashedUniqueString = await PASSWORD.encodePassword(uniqueString); - - await Verification({ newUser, hashedUniqueString }); - const confirmEmailUrl = - currentUrl + "api/user/verify/" + newUser.id + "/" + uniqueString; - await RedisPub( - "user_register", - JSON.stringify({ - confirmEmailUrl, - email, - }) - ); - return { - status: 200, - success: true, - element: { - msg: `Verification email sent to ${email} `, - }, - }; - }, - CreateNewAcceptToken: async ({ user_id }) => { - const newAccessTokens = NewAcceptToken({ user_id }); - return { - status: 200, - success: true, - element: { - accessToken: newAccessTokens, - }, - }; - }, - LogoutRemoveAllUser: async ({ user_id, token, session, res }) => { - await del(user_id); - res.clearCookie("refreshtoken", { - path: "/api/user/new/accessToken", - }); - session.destroy(); - return { - status: 200, - success: true, - element: { msg: "Logged out success" }, - }; - }, - HandleForgerPasswordUser: async ({ email, req }) => { - const { status, success, element } = await CheckForget({ - email, - }); - if (!success) { - return { - status, - success, - element, - }; - } - let user = element; - const resetToken = user.getResetPasswordToken(); - - await user.save({ validateBeforeSave: CONSTANTS.DELETED_DISABLE }); - // const resetPasswordUrl = `${req.protocol}://${req.get( - // "host" - // )}/user/password/reset/${resetToken}`; - const resetPasswordUrl = `${CONFIGS.PORT_FRONTEND_ENV}/user/password/reset/${resetToken}`; - await RedisPub( - "user_forget_password", - JSON.stringify({ - resetPasswordUrl, - email, - }) - ); - return { - status: 200, - success: true, - element: { - msg: `Email sent to ${user.email} successfully`, - }, - }; - }, - HandleResetPasswordUser: async ({ password, confirmPassword, token }) => { - const { status, success, element } = await CheckResetPassword({ - password, - confirmPassword, - token, - }); - if (!success) { - return { - status, - success, - element, - }; - } - let user = element; - user.password = password; - user.resetPasswordToken = undefined; - user.resetPasswordExpire = undefined; - const salt = await PASSWORD.genSalt(); - const passwordHash = await PASSWORD.encodeResetPassword( - user.password, - salt - ); - await UpdatePassword({ - user_id: user.id, password: passwordHash - }); - return { - status: 200, - success: true, - element: { - msg: "Reset successfully", - }, - }; - }, - HandleChangePassword: async ({ - password, - oldPassword, - confirmPassword, - user_id, - }) => { - const { status, success, element } = await CheckChangePassword({ - password, - oldPassword, - confirmPassword, - user_id, - }); - if (!success) { - return { - status, - success, - element, - }; - } - const salt = await PASSWORD.genSalt(); - const passwordHash = await PASSWORD.encodeResetPassword(password, salt); - await UpdatePassword({ - user_id: user_id, - password: passwordHash, - }); - return { - status: 200, - success: true, - element: { - msg: "Change Password Successfully 😂!", - }, - }; - }, - //*--------------- Handle Information Users --------------- - HandleProfile: async ({ user_id, session }) => { - let profile_user_id = await get(`userId:${user_id}`); - if (profile_user_id) { - return { - status: 200, - success: true, - element: JSON.parse(profile_user_id), - }; - } - if (session?.users?.id) { - const user = await getProfileId(session?.users.id); - return { - status: 200, - success: true, - element: user, - }; - } - - const user = await getProfileId(user_id); - return { - status: 200, - success: true, - element: user, - }; - }, - HandleUploadProfile: async ({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }) => { - const { status, success, element } = await CheckUpdateProfile({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }); - if (!success) { - return { - status, - success, - element, - }; - } - await UpdateProfile({ - name, - image, - phone_number, - sex, - date_of_birth, - user_id, - }); - return { - status: 200, - success: true, - element: { - msg: "Updated Profile Successfully !", - }, - }; - }, - HandleInfoEveryUsers: async ({ user_id }) => { - if (!user_id) { - return { - status: 401, - success: false, - element: { - msg: "Get Info User Fail !", - }, - }; - } - const user = await getInfoEveryUser(user_id); - const order_user = await getOrderInfoEveryUser(user_id); - return { - status: 200, - success: true, - element: { - info: user, - order_user: order_user, - }, - }; - }, -}; +const { v4: uuidv4 } = require("uuid"); +const { + createAccessToken, + createRefreshToken, + randomString, +} = require("../../../utils/helper"); +const { + LoginEmail, + LoginPhone, + CheckEmail, + RegisterSocial, +} = require("./userType.service"); +const { + CheckRegister, + CheckForget, + CheckResetPassword, + CheckChangePassword, + CheckUpdateProfile, +} = require("./checkAuthUser.service"); +const { UserSpam } = require("./userSpam.service"); +const { + callDataGoogle, + saveCookies, + callDataFacebook, + GenerateRefreshToken, +} = require("../../../utils/storage"); +const { + Verification, +} = require("../../services/user.service/newVerification.service"); +const { + createUser, + NewAcceptToken, + UpdatePassword, + UpdateProfile, +} = require("./createEditDeleteUser.service"); +const { + getProfileId, + getInfoEveryUser, + getOrderInfoEveryUser, +} = require("./getalluser.service"); +const { get, RedisPub, del } = require("../../../utils/limited_redis"); +const PASSWORD = require("../../../utils/password"); +const STORAGE = require("../../../utils/storage"); +const CONSTANTS = require("../../../configs/constants"); +const CONFIGS = require("../../../configs/config"); +const Users = require("../../../models/userModel"); +module.exports = { + //*--------------- Handle Authentication Users --------------- + checkLoginUser: async ({ + email_phone, + password, + token, + GetIPUser, + res, + session, + }) => { + const { status, _ttl, msg } = UserSpam(GetIPUser); + if (status === 400) { + return { + status, + success: false, + element: { + _ttl, + msg, + }, + }; + } + let result_user = null; + if (email_phone.includes("@") == true) { + result_user = await LoginEmail(email_phone, password); + } else { + result_user = await LoginPhone(email_phone); + } + if (!result_user || result_user.success === false) { + return { + status: result_user?.status, + success: result_user?.success, + element: result_user.element, + }; + } + session.users = { + id: result_user._id, + email: email_phone, + }; + session.save(); + const accessToken = createAccessToken({ id: result_user._id }); + const refreshToken = await GenerateRefreshToken({ id: result_user._id }); + saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + }, + handleLoginPhoneFirebase: async ({ phone_number, session, res }) => { + const user_phone = await STORAGE.checkPhoneExitFirebase(phone_number); + if (!user_phone) { + return { + status: 400, + success: false, + element: { + msg: "Phone Numbers Not Exit !!!", + }, + }; + } + session.users = { + id: user_phone._id, + email: user_phone.email, + }; + session.save(); + const accessToken = createAccessToken({ id: user_phone._id }); + const refreshToken = await GenerateRefreshToken({ id: user_phone._id }); + saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + }, + checkLoginGoogle: async ({ tokenId, res }) => { + const user_google = await callDataGoogle(tokenId); + const { name, email, picture } = user_google.payload; + let result_user = await CheckEmail(email); + if (result_user) { + const accessToken = createAccessToken({ id: result_user._id }); + const refreshToken = await GenerateRefreshToken({ id: result_user._id }); + saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + } else { + var password = randomString(10); + let newUser = await RegisterSocial({ + name, + email, + picture, + password, + }); + if (!newUser) { + return { + status: 503, + success: false, + }; + } + const accessToken = createAccessToken({ id: newUser._id }); + const refreshToken = createRefreshToken({ id: newUser._id }); + saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + } + }, + checkLoginFacebook: async ({ userID, accessToken, res }) => { + let response = await callDataFacebook(userID, accessToken); + const { email, name, picture } = response; + let result_user = await CheckEmail(email); + if (result_user) { + const accessToken = createAccessToken({ id: result_user._id }); + // const refreshToken = createRefreshToken({ id: result_user._id }); + const refreshToken = await GenerateRefreshToken({ id: result_user._id }); + + saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + } else { + var password = randomString(10); + let newUser = await RegisterSocial({ + name, + email, + picture, + password, + }); + if (!newUser) { + return { + status: 503, + success: false, + }; + } + const accessToken = createAccessToken({ id: newUser._id }); + const refreshToken = createRefreshToken({ id: newUser._id }); + saveCookies(res, refreshToken); + return { + status: 200, + success: true, + element: { + accessToken, + refreshToken, + }, + }; + } + }, + checkRegisterUser: async ({ + name, + email, + password, + confirmPassword, + sex, + date_of_birth, + phone_number, + token, + req, + }) => { + const { status, success, element } = await CheckRegister({ + email, + phone_number, + password, + confirmPassword, + date_of_birth, + }); + if (!success) { + return { + status, + success, + element, + }; + } + const password_user = await PASSWORD.encodePassword(password); + let newUser = await createUser( + name, + email, + password_user, + sex, + date_of_birth, + phone_number + ); + const resetPasswordUrl = `${req.protocol}://${req.get("host")}/`; + + const currentUrl = resetPasswordUrl; + const uniqueString = uuidv4() + newUser.id; + const hashedUniqueString = await PASSWORD.encodePassword(uniqueString); + + await Verification({ newUser, hashedUniqueString }); + const confirmEmailUrl = + currentUrl + "api/user/verify/" + newUser.id + "/" + uniqueString; + await RedisPub( + "user_register", + JSON.stringify({ + confirmEmailUrl, + email, + }) + ); + return { + status: 200, + success: true, + element: { + msg: `Verification email sent to ${email} `, + }, + }; + }, + CreateNewAcceptToken: async ({ user_id }) => { + const newAccessTokens = NewAcceptToken({ user_id }); + return { + status: 200, + success: true, + element: { + accessToken: newAccessTokens, + }, + }; + }, + LogoutRemoveAllUser: async ({ user_id, token, session, res }) => { + await del(user_id); + res.clearCookie("refreshtoken", { + path: "/api/user/new/accessToken", + }); + session.destroy(); + return { + status: 200, + success: true, + element: { msg: "Logged out success" }, + }; + }, + HandleForgerPasswordUser: async ({ email, req }) => { + const { status, success, element } = await CheckForget({ + email, + }); + if (!success) { + return { + status, + success, + element, + }; + } + let user = element; + const resetToken = user.getResetPasswordToken(); + + await user.save({ validateBeforeSave: CONSTANTS.DELETED_DISABLE }); + // const resetPasswordUrl = `${req.protocol}://${req.get( + // "host" + // )}/user/password/reset/${resetToken}`; + const resetPasswordUrl = `${CONFIGS.PORT_FRONTEND_ENV}/user/password/reset/${resetToken}`; + await RedisPub( + "user_forget_password", + JSON.stringify({ + resetPasswordUrl, + email, + }) + ); + return { + status: 200, + success: true, + element: { + msg: `Email sent to ${user.email} successfully`, + }, + }; + }, + HandleResetPasswordUser: async ({ password, confirmPassword, token }) => { + const { status, success, element } = await CheckResetPassword({ + password, + confirmPassword, + token, + }); + if (!success) { + return { + status, + success, + element, + }; + } + let user = element; + user.password = password; + user.resetPasswordToken = undefined; + user.resetPasswordExpire = undefined; + const salt = await PASSWORD.genSalt(); + const passwordHash = await PASSWORD.encodeResetPassword( + user.password, + salt + ); + await UpdatePassword({ + user_id: user.id, password: passwordHash + }); + return { + status: 200, + success: true, + element: { + msg: "Reset successfully", + }, + }; + }, + HandleChangePassword: async ({ + password, + oldPassword, + confirmPassword, + user_id, + }) => { + const { status, success, element } = await CheckChangePassword({ + password, + oldPassword, + confirmPassword, + user_id, + }); + if (!success) { + return { + status, + success, + element, + }; + } + const salt = await PASSWORD.genSalt(); + const passwordHash = await PASSWORD.encodeResetPassword(password, salt); + await UpdatePassword({ + user_id: user_id, + password: passwordHash, + }); + return { + status: 200, + success: true, + element: { + msg: "Change Password Successfully 😂!", + }, + }; + }, + //*--------------- Handle Information Users --------------- + HandleProfile: async ({ user_id, session }) => { + let profile_user_id = await get(`userId:${user_id}`); + if (profile_user_id) { + return { + status: 200, + success: true, + element: JSON.parse(profile_user_id), + }; + } + if (session?.users?.id) { + const user = await getProfileId(session?.users.id); + return { + status: 200, + success: true, + element: user, + }; + } + + const user = await getProfileId(user_id); + return { + status: 200, + success: true, + element: user, + }; + }, + HandleUploadProfile: async ({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }) => { + const { status, success, element } = await CheckUpdateProfile({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }); + if (!success) { + return { + status, + success, + element, + }; + } + await UpdateProfile({ + name, + image, + phone_number, + sex, + date_of_birth, + user_id, + }); + return { + status: 200, + success: true, + element: { + msg: "Updated Profile Successfully !", + }, + }; + }, + HandleInfoEveryUsers: async ({ user_id }) => { + if (!user_id) { + return { + status: 401, + success: false, + element: { + msg: "Get Info User Fail !", + }, + }; + } + const user = await getInfoEveryUser(user_id); + const order_user = await getOrderInfoEveryUser(user_id); + return { + status: 200, + success: true, + element: { + info: user, + order_user: order_user, + }, + }; + }, +}; diff --git a/backend/src/v1/user_api/services/user.service/userSpam.service.js b/backend/src/v1/user_api/services/user.service/userSpam.service.js index a45749a..3d7e5a4 100644 --- a/backend/src/v1/user_api/services/user.service/userSpam.service.js +++ b/backend/src/v1/user_api/services/user.service/userSpam.service.js @@ -1,28 +1,28 @@ -"use strict"; -const { incr, ttl, expire } = require("../../../utils/limited_redis"); -module.exports = { - UserSpam: async (GetIPUser) => { - try { - const numRequests = await incr(GetIPUser); - let _ttl; - if (numRequests === 6) { - await expire(GetIPUser, 60); - _ttl = 60; - } else { - _ttl = await ttl(GetIPUser); - } - if (numRequests > 5) { - return { - status: 400, - _ttl, - msg: `You Block ${_ttl}s,Thank You`, - }; - } - return true; - } catch (error) { - return { - status: 503, - }; - } - }, -}; +"use strict"; +const { incr, ttl, expire } = require("../../../utils/limited_redis"); +module.exports = { + UserSpam: async (GetIPUser) => { + try { + const numRequests = await incr(GetIPUser); + let _ttl; + if (numRequests === 6) { + await expire(GetIPUser, 60); + _ttl = 60; + } else { + _ttl = await ttl(GetIPUser); + } + if (numRequests > 5) { + return { + status: 400, + _ttl, + msg: `You Block ${_ttl}s,Thank You`, + }; + } + return true; + } catch (error) { + return { + status: 503, + }; + } + }, +}; diff --git a/backend/src/v1/user_api/services/user.service/userType.service.js b/backend/src/v1/user_api/services/user.service/userType.service.js index 25931e6..a289e53 100644 --- a/backend/src/v1/user_api/services/user.service/userType.service.js +++ b/backend/src/v1/user_api/services/user.service/userType.service.js @@ -1,98 +1,98 @@ -"use strict"; -const STORAGE = require("../../../utils/storage"); -const PASSWORD = require("../../../utils/password"); -const Users = require("../../../models/userModel"); -const HELPER = require("../../../utils/helper.js"); -const { RedisPub } = require("../../../utils/limited_redis"); - -module.exports = { - LoginEmail: async (email_phone, password) => { - try { - // const recapCha = await STORAGE.validateHuman(token); - // if (!recapCha) { - // return { - // status: 402, - // success: false, - // element: "You Check RecapCha Fail ", - // }; - // } - const user_email = await STORAGE.checkUserExit(email_phone); - if (!user_email) - return { - status: 305, - success: false, - }; - if (user_email.verified === false) { - return { - status: 400, - success: false, - element: { - msg: "Email hasn't been verified. Please check email inbox", - }, - }; - } - const user_password = await PASSWORD.comparePassword( - password, - user_email?.password - ); - if (!user_password) { - return { - status: 403, - success: false, - }; - } - return user_email; - } catch (error) { - return { - status: 503, - }; - } - }, - LoginPhone: async (email_phone) => { - try { - const check_phone = HELPER.isVietnamesePhoneNumber(email_phone); - if (!check_phone) { - return { - status: 306, - success: false, - }; - } - const user_phone = await STORAGE.checkPhoneExit(email_phone); - return user_phone; - } catch (error) { - return { - status: 503, - }; - } - }, - CheckEmail: async (email) => { - const user_email = await STORAGE.checkUserExit(email); - return user_email; - }, - //* Register Login - RegisterSocial: async ({ name, email, picture, password }) => { - const password_random = await PASSWORD.encodePassword(password); - let newUser = new Users({ - name: name, - email, - password: password_random, - image: { - public_id: STORAGE.createID(), - url: picture, - }, - verified: true, - }); - return Promise.all([newUser.save(), RedisPub( - "user_register_password_google_facebook", - JSON.stringify({ - password, - name, - email, - }) - )]).then(rs => { - return newUser; - }).catch(err => { - return err; - }); - }, -}; +"use strict"; +const STORAGE = require("../../../utils/storage"); +const PASSWORD = require("../../../utils/password"); +const Users = require("../../../models/userModel"); +const HELPER = require("../../../utils/helper.js"); +const { RedisPub } = require("../../../utils/limited_redis"); + +module.exports = { + LoginEmail: async (email_phone, password) => { + try { + // const recapCha = await STORAGE.validateHuman(token); + // if (!recapCha) { + // return { + // status: 402, + // success: false, + // element: "You Check RecapCha Fail ", + // }; + // } + const user_email = await STORAGE.checkUserExit(email_phone); + if (!user_email) + return { + status: 305, + success: false, + }; + if (user_email.verified === false) { + return { + status: 400, + success: false, + element: { + msg: "Email hasn't been verified. Please check email inbox", + }, + }; + } + const user_password = await PASSWORD.comparePassword( + password, + user_email?.password + ); + if (!user_password) { + return { + status: 403, + success: false, + }; + } + return user_email; + } catch (error) { + return { + status: 503, + }; + } + }, + LoginPhone: async (email_phone) => { + try { + const check_phone = HELPER.isVietnamesePhoneNumber(email_phone); + if (!check_phone) { + return { + status: 306, + success: false, + }; + } + const user_phone = await STORAGE.checkPhoneExit(email_phone); + return user_phone; + } catch (error) { + return { + status: 503, + }; + } + }, + CheckEmail: async (email) => { + const user_email = await STORAGE.checkUserExit(email); + return user_email; + }, + //* Register Login + RegisterSocial: async ({ name, email, picture, password }) => { + const password_random = await PASSWORD.encodePassword(password); + let newUser = new Users({ + name: name, + email, + password: password_random, + image: { + public_id: STORAGE.createID(), + url: picture, + }, + verified: true, + }); + return Promise.all([newUser.save(), RedisPub( + "user_register_password_google_facebook", + JSON.stringify({ + password, + name, + email, + }) + )]).then(rs => { + return newUser; + }).catch(err => { + return err; + }); + }, +}; diff --git a/backend/src/v1/user_api/services/voucher.service/curd.vouchers.js b/backend/src/v1/user_api/services/voucher.service/curd.vouchers.js index a2c2ed2..c9beb6e 100644 --- a/backend/src/v1/user_api/services/voucher.service/curd.vouchers.js +++ b/backend/src/v1/user_api/services/voucher.service/curd.vouchers.js @@ -1,7 +1,7 @@ -const Voucher = require("../../../models/VoucherModel"); -const checkVoucher = async (title) => { - return Voucher.findOne({ title }); -}; -module.exports = { - checkVoucher, -}; +const Voucher = require("../../../models/VoucherModel"); +const checkVoucher = async (title) => { + return Voucher.findOne({ title }); +}; +module.exports = { + checkVoucher, +}; diff --git a/backend/src/v1/user_api/services/voucher.service/voucher.service.js b/backend/src/v1/user_api/services/voucher.service/voucher.service.js index 629933c..742f850 100644 --- a/backend/src/v1/user_api/services/voucher.service/voucher.service.js +++ b/backend/src/v1/user_api/services/voucher.service/voucher.service.js @@ -1,52 +1,52 @@ -const { set, get, del } = require("../../../utils/limited_redis"); -const { checkVoucher } = require("./curd.vouchers"); -const CONSTANTS = require("../../../configs/constants"); -module.exports = { - handleVoucher: async ({ user_id, title }) => { - const check_voucher = await checkVoucher(title); - if (!check_voucher) - return { - status: 400, - success: false, - element: { - msg: "This Voucher already exists.", - }, - }; - set( - `voucher_userId:${user_id}`, - check_voucher.value, - CONSTANTS._15_MINUTES_REDIS - ); - try { - return { - status: 200, - success: true, - element: { - msg: "Apply voucher Successfully !!", - }, - }; - } catch (err) { - return res.status(500).json({ msg: err.message }); - } - }, - handleDelVoucher: async (user_id) => { - let voucher_save_redis = await get(`voucher_userId:${user_id}`); - if (!voucher_save_redis) { - return { - status: 400, - success: false, - element: { - msg: "No Voucher", - }, - }; - } - del(`voucher_userId:${user_id}`); - return { - status: 200, - success: true, - element: { - msg: "Del voucher Success !!", - }, - }; - }, -}; +const { set, get, del } = require("../../../utils/limited_redis"); +const { checkVoucher } = require("./curd.vouchers"); +const CONSTANTS = require("../../../configs/constants"); +module.exports = { + handleVoucher: async ({ user_id, title }) => { + const check_voucher = await checkVoucher(title); + if (!check_voucher) + return { + status: 400, + success: false, + element: { + msg: "This Voucher already exists.", + }, + }; + set( + `voucher_userId:${user_id}`, + check_voucher.value, + CONSTANTS._15_MINUTES_REDIS + ); + try { + return { + status: 200, + success: true, + element: { + msg: "Apply voucher Successfully !!", + }, + }; + } catch (err) { + return res.status(500).json({ msg: err.message }); + } + }, + handleDelVoucher: async (user_id) => { + let voucher_save_redis = await get(`voucher_userId:${user_id}`); + if (!voucher_save_redis) { + return { + status: 400, + success: false, + element: { + msg: "No Voucher", + }, + }; + } + del(`voucher_userId:${user_id}`); + return { + status: 200, + success: true, + element: { + msg: "Del voucher Success !!", + }, + }; + }, +}; diff --git a/backend/src/v1/utils/helper.js b/backend/src/v1/utils/helper.js index 4d0f9cc..664120e 100644 --- a/backend/src/v1/utils/helper.js +++ b/backend/src/v1/utils/helper.js @@ -1,248 +1,248 @@ -const jwt = require("jsonwebtoken"); -const crypto = require("crypto"); -const CONTAINS = require("../configs/constants"); -const CONFIGS = require("../configs/config"); -module.exports = { - /** - * validate email with emailRegex - * @author Nguyen Tiến Tài - * - * @param {string} email - * - * @returns {boolean} true: this email is valid, false: this is not a email - */ - validateEmail(email) { - //Validates the email address - var emailRegex = - /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; - return emailRegex.test(email); - }, - - /** - * validate phone number - * - * @param {number} phone - * - * @returns {boolean} - */ - isVietnamesePhoneNumber(phone_number) { - var phoneRegex = /([\+84|84|0]+(3|5|7|8|9|1[2|6|8|9]))+([0-9]{8})\b/; - return phoneRegex.test(phone_number); - }, - /** - * Change format date to dd/mm/yyyy - * @param {date} date - * - * @returns {date} - */ - changeFormatDate: (date) => { - let datePart = date.match(/\d+/g), - year = datePart[0], - month = datePart[1], - day = datePart[2]; - return day + "/" + month + "/" + year; - }, - - /** - * validate slottime: from_time/to_time format - * - * @param {string} time - * - * @returns {boolean} - */ - validateTime(time) { - var timeRegex = /^(0[0-9]|1[0-9]|2[0-3])(:[0-5]\d)(:[0-5]\d)$/g; - return timeRegex.test(time); - }, - - /** - * validate input date format as ISO standard - * - * @param {string} date - * - * @returns {boolean} - */ - validateIsoDate(date) { - var dateRegex = /^(19|20)\d\d-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/g; - return dateRegex.test(date); - }, - /** - * validate password - * - * @param {string} password - * - * @returns {boolean} - */ - isPassword(password) { - let reg = new RegExp( - "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{6,}$" - ).test(password); - return reg; - }, - /** - * validate date - * @param {number} phone - * - * @returns {boolean} - */ - validateDate(date_of_birth) { - let regex = new RegExp( - "([0-9]{4}[-](0[1-9]|1[0-2])[-]([0-2]{1}[0-9]{1}|3[0-1]{1})|([0-2]{1}[0-9]{1}|3[0-1]{1})[-](0[1-9]|1[0-2])[-][0-9]{4})" - ); - - return regex.test(date_of_birth); - }, - /** - * randomString - * - * @param {number} number - * - * @returns {string} - */ - - randomString(length) { - var result = ""; - var characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - var charactersLength = characters.length; - for (var i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * charactersLength)); - } - return result; - }, - - /** - * Time Vietnamese - * - * - * @returns {date} - */ - - getCurrentTimeJP() { - return new Date().toLocaleString("en-US", { timeZone: "Asia/Ho_Chi_Minh" }); - }, - /** - * Time Vietnamese - * - * - * @returns {date} - */ - - createToISOString() { - return new Date().toISOString(); - }, - - /** sleep web - * Time Vietnamese - * - * @param {number} headers - * - * @returns {number} - */ - sleep: async (seconds) => { - return await new Promise((rs, rj) => { - setTimeout(() => { - rs(true); - }, seconds * 1000); - }); - }, - /** Create access token - * Time Vietnamese - * - * @param {string} headers - * - * @returns {string} - */ - createAccessToken(user) { - return jwt.sign(user, CONFIGS.ACCESS_TOKEN_SECRET, { - expiresIn: CONTAINS.EXPIRES_ACCESS_TOKEN, - }); - }, - /** Create refresh token - * Time Vietnamese - * - * @param {string} headers - * - * @returns {string} - */ - createRefreshToken(user) { - return jwt.sign(user, CONFIGS.REFRESH_TOKEN_SECRET, { - expiresIn: CONTAINS.EXPIRES_REFRESH_TOKEN, - }); - }, - /** Create refresh token - * Time Vietnamese - * - * @param {string} headers - * - * @returns {string} - */ - //* Replace URL - getURIFromTemplate(template, data) { - const { userID, accessToken } = data; - return eval("`" + template.replace(/`/g, "\\`") + "`"); - }, - /** Take user access token - * Time Vietnamese - * - * @param {string} body - * - * @returns {object} - */ - //* Verify AcceptToken - VerifyAccToken(token) { - return jwt.verify(token, CONFIGS.ACCESS_TOKEN_SECRET); - }, - /** Take user access token - * Time Vietnamese - * - * @param {string} body - * - * @returns {object} - */ - //* Verify RefreshToken - /** verification - * - * @param {string} token - * - * @returns {string} - */ - - VerifyRefreshToken(token) { - return jwt.verify(token, CONFIGS.REFRESH_TOKEN_SECRET); - }, - //* Decode Password - /** - * - * @param {string} token - * - * @returns {string} - */ - decodeJWT(token) { - return jwt.decode(token, CONFIGS.JWT_KEY); - }, - //* Key crypto - /** - * @returns {string} random - */ - resetTokens() { - return crypto.randomBytes(CONTAINS.CRYPTO_TOKEN).toString("hex"); - }, - //* Key crypto password - /** token password reset - * @returns {string} random - */ - resetPasswordToken(resetToken) { - return crypto.createHash("sha256").update(resetToken).digest("hex"); - }, - /** Random Number - * Time Vietnamese - * - * @param {number} - * - * @returns {number} random 1->100 - */ - randomNumber() { - return Math.floor(Math.random() * 99) + 1; - }, -}; +const jwt = require("jsonwebtoken"); +const crypto = require("crypto"); +const CONTAINS = require("../configs/constants"); +const CONFIGS = require("../configs/config"); +module.exports = { + /** + * validate email with emailRegex + * @author Nguyen Tiến Tài + * + * @param {string} email + * + * @returns {boolean} true: this email is valid, false: this is not a email + */ + validateEmail(email) { + //Validates the email address + var emailRegex = + /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; + return emailRegex.test(email); + }, + + /** + * validate phone number + * + * @param {number} phone + * + * @returns {boolean} + */ + isVietnamesePhoneNumber(phone_number) { + var phoneRegex = /([\+84|84|0]+(3|5|7|8|9|1[2|6|8|9]))+([0-9]{8})\b/; + return phoneRegex.test(phone_number); + }, + /** + * Change format date to dd/mm/yyyy + * @param {date} date + * + * @returns {date} + */ + changeFormatDate: (date) => { + let datePart = date.match(/\d+/g), + year = datePart[0], + month = datePart[1], + day = datePart[2]; + return day + "/" + month + "/" + year; + }, + + /** + * validate slottime: from_time/to_time format + * + * @param {string} time + * + * @returns {boolean} + */ + validateTime(time) { + var timeRegex = /^(0[0-9]|1[0-9]|2[0-3])(:[0-5]\d)(:[0-5]\d)$/g; + return timeRegex.test(time); + }, + + /** + * validate input date format as ISO standard + * + * @param {string} date + * + * @returns {boolean} + */ + validateIsoDate(date) { + var dateRegex = /^(19|20)\d\d-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/g; + return dateRegex.test(date); + }, + /** + * validate password + * + * @param {string} password + * + * @returns {boolean} + */ + isPassword(password) { + let reg = new RegExp( + "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{6,}$" + ).test(password); + return reg; + }, + /** + * validate date + * @param {number} phone + * + * @returns {boolean} + */ + validateDate(date_of_birth) { + let regex = new RegExp( + "([0-9]{4}[-](0[1-9]|1[0-2])[-]([0-2]{1}[0-9]{1}|3[0-1]{1})|([0-2]{1}[0-9]{1}|3[0-1]{1})[-](0[1-9]|1[0-2])[-][0-9]{4})" + ); + + return regex.test(date_of_birth); + }, + /** + * randomString + * + * @param {number} number + * + * @returns {string} + */ + + randomString(length) { + var result = ""; + var characters = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var charactersLength = characters.length; + for (var i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; + }, + + /** + * Time Vietnamese + * + * + * @returns {date} + */ + + getCurrentTimeJP() { + return new Date().toLocaleString("en-US", { timeZone: "Asia/Ho_Chi_Minh" }); + }, + /** + * Time Vietnamese + * + * + * @returns {date} + */ + + createToISOString() { + return new Date().toISOString(); + }, + + /** sleep web + * Time Vietnamese + * + * @param {number} headers + * + * @returns {number} + */ + sleep: async (seconds) => { + return await new Promise((rs, rj) => { + setTimeout(() => { + rs(true); + }, seconds * 1000); + }); + }, + /** Create access token + * Time Vietnamese + * + * @param {string} headers + * + * @returns {string} + */ + createAccessToken(user) { + return jwt.sign(user, CONFIGS.ACCESS_TOKEN_SECRET, { + expiresIn: CONTAINS.EXPIRES_ACCESS_TOKEN, + }); + }, + /** Create refresh token + * Time Vietnamese + * + * @param {string} headers + * + * @returns {string} + */ + createRefreshToken(user) { + return jwt.sign(user, CONFIGS.REFRESH_TOKEN_SECRET, { + expiresIn: CONTAINS.EXPIRES_REFRESH_TOKEN, + }); + }, + /** Create refresh token + * Time Vietnamese + * + * @param {string} headers + * + * @returns {string} + */ + //* Replace URL + getURIFromTemplate(template, data) { + const { userID, accessToken } = data; + return eval("`" + template.replace(/`/g, "\\`") + "`"); + }, + /** Take user access token + * Time Vietnamese + * + * @param {string} body + * + * @returns {object} + */ + //* Verify AcceptToken + VerifyAccToken(token) { + return jwt.verify(token, CONFIGS.ACCESS_TOKEN_SECRET); + }, + /** Take user access token + * Time Vietnamese + * + * @param {string} body + * + * @returns {object} + */ + //* Verify RefreshToken + /** verification + * + * @param {string} token + * + * @returns {string} + */ + + VerifyRefreshToken(token) { + return jwt.verify(token, CONFIGS.REFRESH_TOKEN_SECRET); + }, + //* Decode Password + /** + * + * @param {string} token + * + * @returns {string} + */ + decodeJWT(token) { + return jwt.decode(token, CONFIGS.JWT_KEY); + }, + //* Key crypto + /** + * @returns {string} random + */ + resetTokens() { + return crypto.randomBytes(CONTAINS.CRYPTO_TOKEN).toString("hex"); + }, + //* Key crypto password + /** token password reset + * @returns {string} random + */ + resetPasswordToken(resetToken) { + return crypto.createHash("sha256").update(resetToken).digest("hex"); + }, + /** Random Number + * Time Vietnamese + * + * @param {number} + * + * @returns {number} random 1->100 + */ + randomNumber() { + return Math.floor(Math.random() * 99) + 1; + }, +}; diff --git a/backend/src/v1/utils/limited_redis.js b/backend/src/v1/utils/limited_redis.js index 106f2d8..c571e00 100644 --- a/backend/src/v1/utils/limited_redis.js +++ b/backend/src/v1/utils/limited_redis.js @@ -1,284 +1,284 @@ -"use strict"; - -const REDIS = require("../db/redis_db"); -const CONSTANTS = require("../configs/constants"); -/** - * @author Nguyen Tiến Tài - * - * @param {number} number - * - * @returns {string} return "Ok" - */ -const incr = (key) => { - return REDIS.incr(key, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * @param {*} key - * - * @returns {json} " - */ -const ttl = (key) => { - return REDIS.ttl(key, (err, ttl) => { - if (err) { - err; - } - ttl; - }); -}; - -/** - * @param {*} key - * - * @returns {json} " - */ -const get = (key) => { - return REDIS.get(key, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * @param {*,*} - * - * @returns {json} " - */ -const set = (key, value, time) => { - return REDIS.set(key, value, "EX", time, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * @param {*,*} key - * - * @returns {number} - */ -const expire = (key, ttl) => { - return REDIS.expire(key, ttl, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * @param {*} key - * - * @returns {string} return "Ok" - */ -const del = (key) => { - return REDIS.del(key, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * @param {*,number} - * - * @returns {string} return "Ok" - */ -const setnx = (key, count) => { - return REDIS.setnx(key, count, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * - * @param {*,number} number - * - * @returns {string} return "Ok" - */ -const decrby = (key, count) => { - return REDIS.decrby(key, count, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * - * @param {*} number - * - * @returns {string} return "Ok" - */ -const incrby = (key, count) => { - return REDIS.incrby(key, count, (err, result) => { - if (err) { - err; - } - result; - }); -}; - -/** - * - * @param {*} number - * - * @returns {string} return "Ok" - */ -const exists = (key) => { - return REDIS.exists(key, (err, result) => { - if (err) { - err; - } - result; - }); -}; -/** - * Order Not buy auto delete - * @param {*,number} - * - * @returns {string} return "Ok" - */ -//?Delete Event order -const addDelayEventOrder = ({ orderId, delay }) => { - return REDIS.set( - orderId, - "notify-keyspace-events", - "EX", - delay, - (err, result) => { - if (err) { - err; - } - result; - } - ); -}; -const saveTokenRedis = (orderId, value, delay) => { - return REDIS.set(orderId, value, "EX", delay, (err, result) => { - if (err) { - err; - } - result; - }); -}; -//? Redis Pub -const RedisPub = (name, value) => { - return REDIS.publish(name, value, (err, result) => { - if (err) { - err; - } - result; - }); -}; -//? Redis Add -const hmset = (user_id, product_id, quantity) => { - return REDIS.hmset( - `cartUserId:${user_id}`, - product_id, - quantity, - (err, result) => { - if (err) { - err; - } - ExpireCart(user_id); - result; - } - ); -}; -//? Get All user add -const hgetall = (user_id) => { - return REDIS.hgetall(`cartUserId:${user_id}`, (err, result) => { - if (err) { - return err; - } - return result; - }); -}; -//? increase and decrease quantity -const hincrby = (user_id, product_id, quantity) => { - return REDIS.hincrby( - `cartUserId:${user_id}`, - product_id, - quantity, - (err, result) => { - if (err) { - err; - } - result; - } - ); -}; -//? length cart -const hlen = (user_id) => { - return REDIS.hlen(`cartUserId:${user_id}`, (err, result) => { - if (err) { - err; - } - result; - }); -}; -//? Dele cart -const delCart = (user_id, product_id) => { - return REDIS.hdel(`cartUserId:${user_id}`, product_id, (err, result) => { - if (err) { - err; - } - result; - }); -}; -//? sum quantity user -const sumQuantity = ({ user_id }) => { - return REDIS.eval( - `local sum = 0 local i=1 local a1 = redis.call('hvals','cartUserId:${user_id}') while(a1[i]) do sum=sum+a1[i] i=i+1 end return sum`, - 0 - ); -}; -//? Expire -const ExpireCart = (user_id) => { - return REDIS.expire( - `cartUserId:${user_id}`, - CONSTANTS._1_HOURS_REDIS, - (err, result) => { - if (err) { - err; - } - result; - } - ); -}; -module.exports = { - incr, - ttl, - get, - set, - expire, - addDelayEventOrder, - del, - setnx, - decrby, - exists, - incrby, - saveTokenRedis, - RedisPub, - hmset, - hgetall, - hincrby, - sumQuantity, - hlen, - delCart, - ExpireCart, -}; +"use strict"; + +const REDIS = require("../db/redis_db"); +const CONSTANTS = require("../configs/constants"); +/** + * @author Nguyen Tiến Tài + * + * @param {number} number + * + * @returns {string} return "Ok" + */ +const incr = (key) => { + return REDIS.incr(key, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * @param {*} key + * + * @returns {json} " + */ +const ttl = (key) => { + return REDIS.ttl(key, (err, ttl) => { + if (err) { + err; + } + ttl; + }); +}; + +/** + * @param {*} key + * + * @returns {json} " + */ +const get = (key) => { + return REDIS.get(key, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * @param {*,*} + * + * @returns {json} " + */ +const set = (key, value, time) => { + return REDIS.set(key, value, "EX", time, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * @param {*,*} key + * + * @returns {number} + */ +const expire = (key, ttl) => { + return REDIS.expire(key, ttl, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * @param {*} key + * + * @returns {string} return "Ok" + */ +const del = (key) => { + return REDIS.del(key, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * @param {*,number} + * + * @returns {string} return "Ok" + */ +const setnx = (key, count) => { + return REDIS.setnx(key, count, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * + * @param {*,number} number + * + * @returns {string} return "Ok" + */ +const decrby = (key, count) => { + return REDIS.decrby(key, count, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * + * @param {*} number + * + * @returns {string} return "Ok" + */ +const incrby = (key, count) => { + return REDIS.incrby(key, count, (err, result) => { + if (err) { + err; + } + result; + }); +}; + +/** + * + * @param {*} number + * + * @returns {string} return "Ok" + */ +const exists = (key) => { + return REDIS.exists(key, (err, result) => { + if (err) { + err; + } + result; + }); +}; +/** + * Order Not buy auto delete + * @param {*,number} + * + * @returns {string} return "Ok" + */ +//?Delete Event order +const addDelayEventOrder = ({ orderId, delay }) => { + return REDIS.set( + orderId, + "notify-keyspace-events", + "EX", + delay, + (err, result) => { + if (err) { + err; + } + result; + } + ); +}; +const saveTokenRedis = (orderId, value, delay) => { + return REDIS.set(orderId, value, "EX", delay, (err, result) => { + if (err) { + err; + } + result; + }); +}; +//? Redis Pub +const RedisPub = (name, value) => { + return REDIS.publish(name, value, (err, result) => { + if (err) { + err; + } + result; + }); +}; +//? Redis Add +const hmset = (user_id, product_id, quantity) => { + return REDIS.hmset( + `cartUserId:${user_id}`, + product_id, + quantity, + (err, result) => { + if (err) { + err; + } + ExpireCart(user_id); + result; + } + ); +}; +//? Get All user add +const hgetall = (user_id) => { + return REDIS.hgetall(`cartUserId:${user_id}`, (err, result) => { + if (err) { + return err; + } + return result; + }); +}; +//? increase and decrease quantity +const hincrby = (user_id, product_id, quantity) => { + return REDIS.hincrby( + `cartUserId:${user_id}`, + product_id, + quantity, + (err, result) => { + if (err) { + err; + } + result; + } + ); +}; +//? length cart +const hlen = (user_id) => { + return REDIS.hlen(`cartUserId:${user_id}`, (err, result) => { + if (err) { + err; + } + result; + }); +}; +//? Dele cart +const delCart = (user_id, product_id) => { + return REDIS.hdel(`cartUserId:${user_id}`, product_id, (err, result) => { + if (err) { + err; + } + result; + }); +}; +//? sum quantity user +const sumQuantity = ({ user_id }) => { + return REDIS.eval( + `local sum = 0 local i=1 local a1 = redis.call('hvals','cartUserId:${user_id}') while(a1[i]) do sum=sum+a1[i] i=i+1 end return sum`, + 0 + ); +}; +//? Expire +const ExpireCart = (user_id) => { + return REDIS.expire( + `cartUserId:${user_id}`, + CONSTANTS._1_HOURS_REDIS, + (err, result) => { + if (err) { + err; + } + result; + } + ); +}; +module.exports = { + incr, + ttl, + get, + set, + expire, + addDelayEventOrder, + del, + setnx, + decrby, + exists, + incrby, + saveTokenRedis, + RedisPub, + hmset, + hgetall, + hincrby, + sumQuantity, + hlen, + delCart, + ExpireCart, +}; diff --git a/backend/src/v1/utils/password.js b/backend/src/v1/utils/password.js index c5c6c32..17e0348 100644 --- a/backend/src/v1/utils/password.js +++ b/backend/src/v1/utils/password.js @@ -1,41 +1,41 @@ -const bcrypt = require("bcrypt"); -const CONSTANTS = require("../configs/constants"); - -module.exports = { - /** - * Encode Password - * @author Nguyen Tiến Tài - * - * @param {string} random - * - */ - encodePassword: (password) => { - return bcrypt.hash(password, CONSTANTS.SALT_ROUNDS); - }, - /** - * Encode reset password - * - * @param {string} random - * - */ - encodeResetPassword: async (password, salt) => { - return bcrypt.hash(password, salt); - }, - - /** - * Compare Password - * - * @returns {boolean} true - */ - comparePassword: (password_text, password_hash) => { - return bcrypt.compare(password_text, password_hash); - }, - /** - * gen salt - * - * @returns {string} - */ - genSalt: async () => { - return bcrypt.genSalt(CONSTANTS.SALT_ROUNDS); - }, -}; +const bcrypt = require("bcrypt"); +const CONSTANTS = require("../configs/constants"); + +module.exports = { + /** + * Encode Password + * @author Nguyen Tiến Tài + * + * @param {string} random + * + */ + encodePassword: (password) => { + return bcrypt.hash(password, CONSTANTS.SALT_ROUNDS); + }, + /** + * Encode reset password + * + * @param {string} random + * + */ + encodeResetPassword: async (password, salt) => { + return bcrypt.hash(password, salt); + }, + + /** + * Compare Password + * + * @returns {boolean} true + */ + comparePassword: (password_text, password_hash) => { + return bcrypt.compare(password_text, password_hash); + }, + /** + * gen salt + * + * @returns {string} + */ + genSalt: async () => { + return bcrypt.genSalt(CONSTANTS.SALT_ROUNDS); + }, +}; diff --git a/backend/src/v1/utils/random_code.js b/backend/src/v1/utils/random_code.js index 6874dd8..33e265d 100644 --- a/backend/src/v1/utils/random_code.js +++ b/backend/src/v1/utils/random_code.js @@ -1,14 +1,14 @@ -module.exports = { - /** - * random code - * @author Nguyen Tiến Tài - * - * @param {string} random - * - */ - randomCode: () => { - let now = Date.now().toString(); - now += now + Math.floor(Math.random() * 10); - return [now.slice(0, 4), now.slice(4, 10), now.slice(10, 14)].join("-"); - }, -}; +module.exports = { + /** + * random code + * @author Nguyen Tiến Tài + * + * @param {string} random + * + */ + randomCode: () => { + let now = Date.now().toString(); + now += now + Math.floor(Math.random() * 10); + return [now.slice(0, 4), now.slice(4, 10), now.slice(10, 14)].join("-"); + }, +}; diff --git a/backend/src/v1/utils/storage.js b/backend/src/v1/utils/storage.js index b237698..013f8c2 100644 --- a/backend/src/v1/utils/storage.js +++ b/backend/src/v1/utils/storage.js @@ -1,298 +1,298 @@ -const fetch = require("node-fetch"); -const { OAuth2Client } = require("google-auth-library"); -const rateLimit = require("express-rate-limit"); -const { Sonyflake } = require("sonyflake"); -const { createRefreshToken } = require("../utils/helper"); -const { get, saveTokenRedis } = require("../utils/limited_redis"); -const CONSTANTS = require("../configs/constants"); -const REDIS = require("../db/redis_db"); -const CONFIGS = require("../configs/config"); -const Users = require("../models/userModel"); -const Category = require("../models/CategoryModel"); -const Products = require("../models/ProductModel"); -const Carousels = require("../models/CarouselModel"); -const Vouchers = require("../models/VoucherModel"); -const UserVerifications = require("../models/userVerificationModel"); -const HELPER = require("../utils/helper"); -const CLIENT_ID = CONFIGS.GOOGLE_CLIENT_IDS; -const client = new OAuth2Client(CLIENT_ID); -module.exports = { - /** - * * code Status - */ - reasonPhraseCodeProNewMap: () => { - const result = new Map([ - ["100", CONSTANTS.STATUS_CODE_100], - ["101", CONSTANTS.STATUS_CODE_101], - ["102", CONSTANTS.STATUS_CODE_102], - ["103", CONSTANTS.STATUS_CODE_103], - ["200", CONSTANTS.STATUS_CODE_200], - ["201", CONSTANTS.STATUS_CODE_201], - ["202", CONSTANTS.STATUS_CODE_202], - ["203", CONSTANTS.STATUS_CODE_203], - ["204", CONSTANTS.STATUS_CODE_204], - ["302", CONSTANTS.STATUS_CODE_302], - ["305", CONSTANTS.STATUS_CODE_305], - ["306", CONSTANTS.STATUS_CODE_306], - ["307", CONSTANTS.STATUS_CODE_307], - ["308", CONSTANTS.STATUS_CODE_308], - ["403", CONSTANTS.STATUS_CODE_403], - ["404", CONSTANTS.STATUS_CODE_404], - ["503", CONSTANTS.STATUS_CODE_503], - ["default", CONSTANTS.STATUS_CODE_DEFAULT], - ]); - return result; - }, - - //* RecapCha - async validateHuman(token) { - const secret = CONFIGS.RECAPTCHA_SECRET_KEY; - const response = await fetch( - `https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${token}`, - { - method: "POST", - } - ); - let data = await response.json(); - return data.success; - }, - //* Users email - async checkUserExit(email) { - const user = await Users.findOne({ - email: email, - // role: CONSTANTS.ACCOUNT_USER, - }); - return user; - }, - async checkUserIdExit(id) { - const user = await Users.findOne({ - _id: id, - // role: CONSTANTS.ACCOUNT_USER, - }); - return user; - }, - //* Users email admin - async checkAdminExit(email) { - const user = await Users.findOne({ - email: email, - role: CONSTANTS.ACCOUNT_ADMIN, - }); - return user; - }, - //* async check User Exit Except User main - async checkPhoneExitExceptUserMain(user_id, phone_number) { - const user = await Users.find({ - _id: { $ne: user_id }, - phone_number: phone_number, - role: CONSTANTS.ACCOUNT_USER, - }); - return user; - }, - //* Product check Exit - - async checkProductExit(name) { - const user = await Products.find({ - name, - }); - return user; - }, - //* async check Product Exit Except Product main - - async checkProductExitExceptUserMain(product_id, name) { - const user = await Products.find({ - _id: { $ne: product_id }, - name, - }); - return user; - }, - //* Carousel check Exit Except Product main - async checkCarouselExitExceptUserMain(_id, heading) { - const carousel = await Carousels.find({ - _id: { $ne: _id }, - heading, - }); - return carousel; - }, - //* Carousel check Exit - async checkCarouselExit(heading) { - const carousel = await Carousels.find({ - heading, - }); - return carousel; - }, - //* check phone exit - async checkPhoneExit(phone_number) { - const user = await Users.find({ - phone_number: phone_number, - }); - return user; - }, - //* CheckPhoneExit Firebase - async checkPhoneExitFirebase(phone_number) { - return await Users.findOne({ - phone_number: phone_number, - }); - }, - //* Check exit category - async checkCategoryExit(name) { - return await Category.findOne({ name }); - }, - //* Check exit ExitExcept - - async checkCategoryExitExceptUserMain(category_id, name) { - const categories = await Category.find({ - _id: { $ne: category_id }, - name, - }); - return categories; - }, - //* Check verification - async checkVerification(userId) { - const userVerification = await UserVerifications.findOne({ userId }); - return userVerification; - }, - //*Take Data user Google - async callDataGoogle(tokenId) { - return await client.verifyIdToken({ - idToken: tokenId, - audience: CLIENT_ID, - }); - }, - //*Take Data user facebook - callDataFacebook(userID, accessToken) { - let urlGraphFacebook = HELPER.getURIFromTemplate( - CONSTANTS.STORAGE_GRAPH_FACEBOOK, - { - userID, - accessToken, - } - ); - return fetch(urlGraphFacebook, { - method: "GET", - }).then((response) => response.json()); - }, - //* check role user_id - async checkRoleUserId({ user_id }) { - await Users.findOne({ - _id: user_id, - role: CONSTANTS.ACCOUNT_ADMIN, - }); - }, - //* cookie - saveCookies(res, refreshToken) { - res.cookie("refreshtoken", refreshToken, { - httpOnly: CONFIGS.NODE_ENV === "PRODUCTION" ? true : false, - sameSite: CONFIGS.NODE_ENV === "PRODUCTION" ? true : false, - secure: CONFIGS.NODE_ENV === "PRODUCTION" ? true : false, - path: "/api/user/new/accessToken", - maxAge: CONSTANTS._7_DAY, - }); - }, - //*Handle RefetchToken - async GenerateRefreshToken(user) { - const refresh = await get(user.id.toString()); - if (refresh) { - return refresh; - } - const refreshToken = createRefreshToken(user); - await saveTokenRedis(user.id, refreshToken, CONSTANTS._7_DAYS_REDIS); - return refreshToken; - }, - //* Check user reset Expired - async CheckUserExpired(resetPasswordToken) { - const user = await Users.findOne({ - resetPasswordToken, - resetPasswordExpire: { $gt: Date.now() }, - }); - return user; - }, - //*Stock - async stock(id, quantity, countInStock) { - try { - await Products.findOneAndUpdate( - { _id: id }, - { - countInStock: Number(countInStock) - Number(quantity), - } - ); - } catch (error) { - console.error( - "----------------------Stock--------error------------", - error - ); - } - }, - //*Sold - async sold(id, quantity, oldSold) { - try { - await Products.findOneAndUpdate( - { _id: id }, - { - sold: Number(quantity) + Number(oldSold), - } - ); - } catch (error) { - console.error( - "----------------------Sold--------error------------", - error - ); - } - }, - //* Check voucher exit - async checkVoucherExit(title) { - return await Vouchers.find({ - title, - }); - }, - //* Voucher check Exit Except main - async checkVoucherExitExceptUserMain(voucher_id, title) { - return await Vouchers.find({ - _id: { $ne: voucher_id }, - title, - }); - }, - //* Check type upload - detectedFileType(content_type) { - const images = ["image/jpeg", "image/png", "image/gif", "image/webp"]; - const videos = [ - "video/mp4", - "video/3gp", - "video/ogg", - "video/x-msvideo", - "video/quicktime", - ]; - const documents = [ - "application/pdf", - "application/msword", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - ]; - const audio = ["audio/aac", "audio/mpeg", "audio/ogg", "audio/wav"]; - - if (images.includes(content_type)) { - return "image"; - } - - if (videos.includes(content_type)) { - return "video"; - } - - if (documents.includes(content_type)) { - return "document"; - } - - if (audio.includes(content_type)) { - return "audio"; - } - - // not found return null - return null; - }, - createID() { - const sonyflake = new Sonyflake({ - machineId: 2, // in range 2^16 - epoch: Date.UTC(2020, 4, 18, 0, 0, 0), // timestamp - }); - const id = sonyflake.nextId(); - return id; - }, -}; +const fetch = require("node-fetch"); +const { OAuth2Client } = require("google-auth-library"); +const rateLimit = require("express-rate-limit"); +const { Sonyflake } = require("sonyflake"); +const { createRefreshToken } = require("../utils/helper"); +const { get, saveTokenRedis } = require("../utils/limited_redis"); +const CONSTANTS = require("../configs/constants"); +const REDIS = require("../db/redis_db"); +const CONFIGS = require("../configs/config"); +const Users = require("../models/userModel"); +const Category = require("../models/CategoryModel"); +const Products = require("../models/ProductModel"); +const Carousels = require("../models/CarouselModel"); +const Vouchers = require("../models/VoucherModel"); +const UserVerifications = require("../models/userVerificationModel"); +const HELPER = require("../utils/helper"); +const CLIENT_ID = CONFIGS.GOOGLE_CLIENT_IDS; +const client = new OAuth2Client(CLIENT_ID); +module.exports = { + /** + * * code Status + */ + reasonPhraseCodeProNewMap: () => { + const result = new Map([ + ["100", CONSTANTS.STATUS_CODE_100], + ["101", CONSTANTS.STATUS_CODE_101], + ["102", CONSTANTS.STATUS_CODE_102], + ["103", CONSTANTS.STATUS_CODE_103], + ["200", CONSTANTS.STATUS_CODE_200], + ["201", CONSTANTS.STATUS_CODE_201], + ["202", CONSTANTS.STATUS_CODE_202], + ["203", CONSTANTS.STATUS_CODE_203], + ["204", CONSTANTS.STATUS_CODE_204], + ["302", CONSTANTS.STATUS_CODE_302], + ["305", CONSTANTS.STATUS_CODE_305], + ["306", CONSTANTS.STATUS_CODE_306], + ["307", CONSTANTS.STATUS_CODE_307], + ["308", CONSTANTS.STATUS_CODE_308], + ["403", CONSTANTS.STATUS_CODE_403], + ["404", CONSTANTS.STATUS_CODE_404], + ["503", CONSTANTS.STATUS_CODE_503], + ["default", CONSTANTS.STATUS_CODE_DEFAULT], + ]); + return result; + }, + + //* RecapCha + async validateHuman(token) { + const secret = CONFIGS.RECAPTCHA_SECRET_KEY; + const response = await fetch( + `https://www.google.com/recaptcha/api/siteverify?secret=${secret}&response=${token}`, + { + method: "POST", + } + ); + let data = await response.json(); + return data.success; + }, + //* Users email + async checkUserExit(email) { + const user = await Users.findOne({ + email: email, + // role: CONSTANTS.ACCOUNT_USER, + }); + return user; + }, + async checkUserIdExit(id) { + const user = await Users.findOne({ + _id: id, + // role: CONSTANTS.ACCOUNT_USER, + }); + return user; + }, + //* Users email admin + async checkAdminExit(email) { + const user = await Users.findOne({ + email: email, + role: CONSTANTS.ACCOUNT_ADMIN, + }); + return user; + }, + //* async check User Exit Except User main + async checkPhoneExitExceptUserMain(user_id, phone_number) { + const user = await Users.find({ + _id: { $ne: user_id }, + phone_number: phone_number, + role: CONSTANTS.ACCOUNT_USER, + }); + return user; + }, + //* Product check Exit + + async checkProductExit(name) { + const user = await Products.find({ + name, + }); + return user; + }, + //* async check Product Exit Except Product main + + async checkProductExitExceptUserMain(product_id, name) { + const user = await Products.find({ + _id: { $ne: product_id }, + name, + }); + return user; + }, + //* Carousel check Exit Except Product main + async checkCarouselExitExceptUserMain(_id, heading) { + const carousel = await Carousels.find({ + _id: { $ne: _id }, + heading, + }); + return carousel; + }, + //* Carousel check Exit + async checkCarouselExit(heading) { + const carousel = await Carousels.find({ + heading, + }); + return carousel; + }, + //* check phone exit + async checkPhoneExit(phone_number) { + const user = await Users.find({ + phone_number: phone_number, + }); + return user; + }, + //* CheckPhoneExit Firebase + async checkPhoneExitFirebase(phone_number) { + return await Users.findOne({ + phone_number: phone_number, + }); + }, + //* Check exit category + async checkCategoryExit(name) { + return await Category.findOne({ name }); + }, + //* Check exit ExitExcept + + async checkCategoryExitExceptUserMain(category_id, name) { + const categories = await Category.find({ + _id: { $ne: category_id }, + name, + }); + return categories; + }, + //* Check verification + async checkVerification(userId) { + const userVerification = await UserVerifications.findOne({ userId }); + return userVerification; + }, + //*Take Data user Google + async callDataGoogle(tokenId) { + return await client.verifyIdToken({ + idToken: tokenId, + audience: CLIENT_ID, + }); + }, + //*Take Data user facebook + callDataFacebook(userID, accessToken) { + let urlGraphFacebook = HELPER.getURIFromTemplate( + CONSTANTS.STORAGE_GRAPH_FACEBOOK, + { + userID, + accessToken, + } + ); + return fetch(urlGraphFacebook, { + method: "GET", + }).then((response) => response.json()); + }, + //* check role user_id + async checkRoleUserId({ user_id }) { + await Users.findOne({ + _id: user_id, + role: CONSTANTS.ACCOUNT_ADMIN, + }); + }, + //* cookie + saveCookies(res, refreshToken) { + res.cookie("refreshtoken", refreshToken, { + httpOnly: CONFIGS.NODE_ENV === "PRODUCTION" ? true : false, + sameSite: CONFIGS.NODE_ENV === "PRODUCTION" ? true : false, + secure: CONFIGS.NODE_ENV === "PRODUCTION" ? true : false, + path: "/api/user/new/accessToken", + maxAge: CONSTANTS._7_DAY, + }); + }, + //*Handle RefetchToken + async GenerateRefreshToken(user) { + const refresh = await get(user.id.toString()); + if (refresh) { + return refresh; + } + const refreshToken = createRefreshToken(user); + await saveTokenRedis(user.id, refreshToken, CONSTANTS._7_DAYS_REDIS); + return refreshToken; + }, + //* Check user reset Expired + async CheckUserExpired(resetPasswordToken) { + const user = await Users.findOne({ + resetPasswordToken, + resetPasswordExpire: { $gt: Date.now() }, + }); + return user; + }, + //*Stock + async stock(id, quantity, countInStock) { + try { + await Products.findOneAndUpdate( + { _id: id }, + { + countInStock: Number(countInStock) - Number(quantity), + } + ); + } catch (error) { + console.error( + "----------------------Stock--------error------------", + error + ); + } + }, + //*Sold + async sold(id, quantity, oldSold) { + try { + await Products.findOneAndUpdate( + { _id: id }, + { + sold: Number(quantity) + Number(oldSold), + } + ); + } catch (error) { + console.error( + "----------------------Sold--------error------------", + error + ); + } + }, + //* Check voucher exit + async checkVoucherExit(title) { + return await Vouchers.find({ + title, + }); + }, + //* Voucher check Exit Except main + async checkVoucherExitExceptUserMain(voucher_id, title) { + return await Vouchers.find({ + _id: { $ne: voucher_id }, + title, + }); + }, + //* Check type upload + detectedFileType(content_type) { + const images = ["image/jpeg", "image/png", "image/gif", "image/webp"]; + const videos = [ + "video/mp4", + "video/3gp", + "video/ogg", + "video/x-msvideo", + "video/quicktime", + ]; + const documents = [ + "application/pdf", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ]; + const audio = ["audio/aac", "audio/mpeg", "audio/ogg", "audio/wav"]; + + if (images.includes(content_type)) { + return "image"; + } + + if (videos.includes(content_type)) { + return "video"; + } + + if (documents.includes(content_type)) { + return "document"; + } + + if (audio.includes(content_type)) { + return "audio"; + } + + // not found return null + return null; + }, + createID() { + const sonyflake = new Sonyflake({ + machineId: 2, // in range 2^16 + epoch: Date.UTC(2020, 4, 18, 0, 0, 0), // timestamp + }); + const id = sonyflake.nextId(); + return id; + }, +}; diff --git a/backend/src/v1/views/Error.html b/backend/src/v1/views/Error.html index 74ebfc1..223e5af 100644 --- a/backend/src/v1/views/Error.html +++ b/backend/src/v1/views/Error.html @@ -1,1549 +1,1549 @@ - - - - - - - - - - - - - - - - Error Key - - - -
-
- -

Thank You for 😉 !

-
-
- - + + + + + + + + + + + + + + + + Error Key + + + +
+
+ +

Thank You for 😉 !

+
+
+ + diff --git a/backend/src/v1/views/confirm-email.html b/backend/src/v1/views/confirm-email.html index 17890e7..6f4e0fe 100644 --- a/backend/src/v1/views/confirm-email.html +++ b/backend/src/v1/views/confirm-email.html @@ -1,692 +1,692 @@ - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - - -
- -
-
- - - -
- - - - - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - -
- -
-
-
- Please confirm your email -
-
-
- Yes, we know. -
-
-
- An email to confirm an email. 🤪 -
-
-
- Please validate your email address in order to get - started using Shop Shoe. -
-
- - - - -
- Confirm Your Email - -
-
-
- Or verify using this link: -
-
- -
-
- Need Help? -
-
-
- Please send and feedback or bug info
- to - nguyentientai10@gmail.com -
-
-
- - -
-
- - - -
- - - - - - -
- - -
- - - - - - -
- - - - - - - - -
-
- Tổ dân phố 9,Thị Trấn Vạn Giã,Vạn Ninh,Khánh - Hòa -
-
-
- Support - from ShopShoe -
-
-
-
- - -
-
- - -
- - + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + +
+ +
+
+ + + +
+ + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+
+
+ Please confirm your email +
+
+
+ Yes, we know. +
+
+
+ An email to confirm an email. 🤪 +
+
+
+ Please validate your email address in order to get + started using Shop Shoe. +
+
+ + + + +
+ Confirm Your Email + +
+
+
+ Or verify using this link: +
+
+ +
+
+ Need Help? +
+
+
+ Please send and feedback or bug info
+ to + nguyentientai10@gmail.com +
+
+
+ + +
+
+ + + +
+ + + + + + +
+ + +
+ + + + + + +
+ + + + + + + + +
+
+ Tổ dân phố 9,Thị Trấn Vạn Giã,Vạn Ninh,Khánh + Hòa +
+
+
+ Support + from ShopShoe +
+
+
+
+ + +
+
+ + +
+ + diff --git a/backend/src/v1/views/feedback.html b/backend/src/v1/views/feedback.html index e3bcc74..0368378 100644 --- a/backend/src/v1/views/feedback.html +++ b/backend/src/v1/views/feedback.html @@ -1,625 +1,625 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/backend/src/v1/views/forgot-password.html b/backend/src/v1/views/forgot-password.html index 68a8563..88fea9e 100644 --- a/backend/src/v1/views/forgot-password.html +++ b/backend/src/v1/views/forgot-password.html @@ -1,544 +1,544 @@ - - - - - - - - - - - - - - - - - - - -
-
- - - - - - -
-
- -
- - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - -
- -
-
-
- Link Reset 😍! -
-
-
- It seems that you’ve forgotten your password. -
-
- - - - - - -
- -
-
- - - - -
- Reset Link -
-
-
- If you did not make this request, just ignore this - email. Otherwise please click the button above to - reset your password. -
-
-
- - -
-
- - - -
- - - - - - -
- - -
- - - - - - -
- - - - - - - - -
-
- Support Customer - https://profile-forme.surge.sh/ -
-
-
- Email Tai Dev Web - -- Thank You For Visiting 💓! -
-
-
-
- - -
-
- - -
- - + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+
+ +
+ + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ +
+
+
+ Link Reset 😍! +
+
+
+ It seems that you’ve forgotten your password. +
+
+ + + + + + +
+ +
+
+ + + + +
+ Reset Link +
+
+
+ If you did not make this request, just ignore this + email. Otherwise please click the button above to + reset your password. +
+
+
+ + +
+
+ + + +
+ + + + + + +
+ + +
+ + + + + + +
+ + + + + + + + +
+
+ Support Customer + https://profile-forme.surge.sh/ +
+
+
+ Email Tai Dev Web + -- Thank You For Visiting 💓! +
+
+
+
+ + +
+
+ + +
+ + diff --git a/backend/src/v1/views/password-register.html b/backend/src/v1/views/password-register.html index dbe51b7..44b7794 100644 --- a/backend/src/v1/views/password-register.html +++ b/backend/src/v1/views/password-register.html @@ -1,606 +1,606 @@ - - - New Password - - - - - - - - - - - - - - - + + + New Password + + + + + + + + + + + + + + + diff --git a/backend/src/v1/views/response_feedback.html b/backend/src/v1/views/response_feedback.html index ca5e218..10d7724 100644 --- a/backend/src/v1/views/response_feedback.html +++ b/backend/src/v1/views/response_feedback.html @@ -1,625 +1,625 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/backend/src/v1/views/thankyou.html b/backend/src/v1/views/thankyou.html index a37e49f..0d68b22 100644 --- a/backend/src/v1/views/thankyou.html +++ b/backend/src/v1/views/thankyou.html @@ -1,1549 +1,1549 @@ - - - - - - - - - - - - - - - - Thank You - - - -
-
- -

Thank You for 😉 !

-
-
- - + + + + + + + + + + + + + + + + Thank You + + + +
+
+ +

Thank You for 😉 !

+
+
+ + diff --git a/backend/src/v1/views/verify-success.html b/backend/src/v1/views/verify-success.html index 33c3865..71e8808 100644 --- a/backend/src/v1/views/verify-success.html +++ b/backend/src/v1/views/verify-success.html @@ -1,1548 +1,1548 @@ - - - - - - - - - - - - - - - - Document - - - -
-
- - -

Thank You for 😉 !

-
-
- + + + + + + + + + + + + + + + + Document + + + +
+
+ + +

Thank You for 😉 !

+
+
+ \ No newline at end of file diff --git a/backend/vercel.json b/backend/vercel.json index 8e6549a..ab68ad7 100644 --- a/backend/vercel.json +++ b/backend/vercel.json @@ -1,6 +1,6 @@ -{ - "version": 2, - "name": "name-of-your-vercel-app", - "builds": [{ "src": "server.js", "use": "@vercel/node" }], - "routes": [{ "src": "/api(.*)", "dest": "/server.js" }] -} +{ + "version": 2, + "name": "name-of-your-vercel-app", + "builds": [{ "src": "server.js", "use": "@vercel/node" }], + "routes": [{ "src": "/api(.*)", "dest": "/server.js" }] +} diff --git a/docker-compose.yml b/docker-compose.yml index c2ca00a..c8bff36 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,97 +1,97 @@ -version: "3.7" - -services: -###! Backend ### - backend: - container_name: backend - depends_on: - - mongodb - - redis - restart: always - build: - dockerfile: Dockerfile.dev - context: ./backend - environment: - PORT: '${PORT}' - ports: - - ${PORT}:${PORT} - volumes: - - /app/node_modules - - ./backend:/app - env_file: - - .env - command: npm run dev - networks: - - shopshoe - -###! NoSql: MongoDB ### - mongodb: - image: mongo - restart: always - env_file: - - .env - environment: - MONGO_PORT: '${MONGO_PORT}' - MONGODB_URL: '${MONGODB_URL}' - MONGO_USER: '${MONGO_USER}' - MONGO_PASSWORD: '${MONGO_PASSWORD}' - volumes: - - ./backend/mongo-entrypoint:/docker-entrypoint-initdb.d - - ./backend/data:/data/db - - ./backend/mongoconfig:/data/configdb - ports: - - ${MONGO_PORT}:${MONGO_PORT} - - networks: - - shopshoe - -###! Redis ### - redis: - image: redis:6.2 - restart: always - environment: - REDIS_PASSWORD: '${REDIS_PASSWORD}' - env_file: - - .env - networks: - - shopshoe -###! Frontend ### - frontend: - depends_on: - - backend - stdin_open: true - tty: true - container_name: frontend - build: - dockerfile: Dockerfile.dev - context: ./frontend - - volumes: - - /app/node_modules - - ./frontend:/app - ports: - - 3001:3000 - environment: - - CHOKIDAR_USEPOLLING=true - networks: - - shopshoe -###! WebServer:NGINX ### - nginx: - image: nginx:1.21.3 - container_name: nginx - depends_on: - - backend - - frontend - restart: always - build: - dockerfile: Dockerfile.dev - context: ./nginx - ports: - - "8084:80" - networks: - - shopshoe - -###! Networks general ### -networks: - shopshoe: - driver: bridge +version: "3.7" + +services: +###! Backend ### + backend: + container_name: backend + depends_on: + - mongodb + - redis + restart: always + build: + dockerfile: Dockerfile.dev + context: ./backend + environment: + PORT: '${PORT}' + ports: + - ${PORT}:${PORT} + volumes: + - /app/node_modules + - ./backend:/app + env_file: + - .env + command: npm run dev + networks: + - shopshoe + +###! NoSql: MongoDB ### + mongodb: + image: mongo + restart: always + env_file: + - .env + environment: + MONGO_PORT: '${MONGO_PORT}' + MONGODB_URL: '${MONGODB_URL}' + MONGO_USER: '${MONGO_USER}' + MONGO_PASSWORD: '${MONGO_PASSWORD}' + volumes: + - ./backend/mongo-entrypoint:/docker-entrypoint-initdb.d + - ./backend/data:/data/db + - ./backend/mongoconfig:/data/configdb + ports: + - ${MONGO_PORT}:${MONGO_PORT} + + networks: + - shopshoe + +###! Redis ### + redis: + image: redis:6.2 + restart: always + environment: + REDIS_PASSWORD: '${REDIS_PASSWORD}' + env_file: + - .env + networks: + - shopshoe +###! Frontend ### + frontend: + depends_on: + - backend + stdin_open: true + tty: true + container_name: frontend + build: + dockerfile: Dockerfile.dev + context: ./frontend + + volumes: + - /app/node_modules + - ./frontend:/app + ports: + - 3001:3000 + environment: + - CHOKIDAR_USEPOLLING=true + networks: + - shopshoe +###! WebServer:NGINX ### + nginx: + image: nginx:1.21.3 + container_name: nginx + depends_on: + - backend + - frontend + restart: always + build: + dockerfile: Dockerfile.dev + context: ./nginx + ports: + - "8084:80" + networks: + - shopshoe + +###! Networks general ### +networks: + shopshoe: + driver: bridge diff --git a/dump.rdb b/dump.rdb index a43a8e3..5de8ca2 100644 Binary files a/dump.rdb and b/dump.rdb differ diff --git a/frontend/.dockerignore b/frontend/.dockerignore index 1781d93..3f1cf7d 100644 --- a/frontend/.dockerignore +++ b/frontend/.dockerignore @@ -1,3 +1,3 @@ -node_modules -.git +node_modules +.git Dockerfile \ No newline at end of file diff --git a/frontend/.editorconfig b/frontend/.editorconfig new file mode 100644 index 0000000..3454886 --- /dev/null +++ b/frontend/.editorconfig @@ -0,0 +1,14 @@ +# https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/frontend/.env.xample b/frontend/.env.xample index 373fe27..41216a5 100644 --- a/frontend/.env.xample +++ b/frontend/.env.xample @@ -1,30 +1,30 @@ -################## SETTING MAIN ################### -REACT_APP_API_URL=REACT_APP_API_URL - -NODE_ENV=NODE_ENV - -REACT_APP_KEY_FACEBOOK=REACT_APP_KEY_FACEBOOK -REACT_APP_KEY_FACEBOOK_TEST=REACT_APP_KEY_FACEBOOK_TEST - -REACT_APP_KEY_GOOGLE=REACT_APP_KEY_GOOGLE - -REACT_APP_KEY_RECAPTCHA=REACT_APP_KEY_RECAPTCHA - -REACT_APP_KEY_RECAPTCHA_V3=REACT_APP_KEY_RECAPTCHA_V3 - -REACT_APP_KEY_GOOGLE_MAP=REACT_APP_KEY_GOOGLE_MAP - -REACT_APP_KEY_GOOGLE_MAP_MAIN=REACT_APP_KEY_GOOGLE_MAP_MAIN - -REACT_APP_GOOGLE_LAT=REACT_APP_GOOGLE_LAT -REACT_APP_GOOGLE_LNG=REACT_APP_GOOGLE_LNG - - -################## Config Firebase ################### -REACT_APP_API_KEY=REACT_APP_API_KEY -REACT_APP_AUTH_DOMAIN=REACT_APP_AUTH_DOMAIN -REACT_APP_DATA_BASE_URL=REACT_APP_DATA_BASE_UR -REACT_APP_PROJECT_ID=REACT_APP_PROJECT_ID -REACT_APP_STORAGE_BUCKET=REACT_APP_STORAGE_BUCKET -REACT_APP_MESSAGING_SENDER_ID=REACT_APP_MESSAGING_SENDER_ID +################## SETTING MAIN ################### +REACT_APP_API_URL=REACT_APP_API_URL + +NODE_ENV=NODE_ENV + +REACT_APP_KEY_FACEBOOK=REACT_APP_KEY_FACEBOOK +REACT_APP_KEY_FACEBOOK_TEST=REACT_APP_KEY_FACEBOOK_TEST + +REACT_APP_KEY_GOOGLE=REACT_APP_KEY_GOOGLE + +REACT_APP_KEY_RECAPTCHA=REACT_APP_KEY_RECAPTCHA + +REACT_APP_KEY_RECAPTCHA_V3=REACT_APP_KEY_RECAPTCHA_V3 + +REACT_APP_KEY_GOOGLE_MAP=REACT_APP_KEY_GOOGLE_MAP + +REACT_APP_KEY_GOOGLE_MAP_MAIN=REACT_APP_KEY_GOOGLE_MAP_MAIN + +REACT_APP_GOOGLE_LAT=REACT_APP_GOOGLE_LAT +REACT_APP_GOOGLE_LNG=REACT_APP_GOOGLE_LNG + + +################## Config Firebase ################### +REACT_APP_API_KEY=REACT_APP_API_KEY +REACT_APP_AUTH_DOMAIN=REACT_APP_AUTH_DOMAIN +REACT_APP_DATA_BASE_URL=REACT_APP_DATA_BASE_UR +REACT_APP_PROJECT_ID=REACT_APP_PROJECT_ID +REACT_APP_STORAGE_BUCKET=REACT_APP_STORAGE_BUCKET +REACT_APP_MESSAGING_SENDER_ID=REACT_APP_MESSAGING_SENDER_ID REACT_APP_APP_ID=REACT_APP_APP_ID \ No newline at end of file diff --git a/frontend/.eslintignore b/frontend/.eslintignore new file mode 100644 index 0000000..4a3e304 --- /dev/null +++ b/frontend/.eslintignore @@ -0,0 +1,5 @@ +build/*.js +src/assets +src/main.js +public +dist diff --git a/frontend/.eslintrc b/frontend/.eslintrc new file mode 100644 index 0000000..9e9572a --- /dev/null +++ b/frontend/.eslintrc @@ -0,0 +1,35 @@ +{ + "extends": ["react-app", "prettier"], + "plugins": ["react", "eslint-plugin-prettier", "prettier"], + "parserOptions": { + "ecmaFeatures": { + "jsx": true, + "js": true, + "modules": true + } + }, + "rules": { + "prettier/prettier": [ + "warn", + { + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxSingleQuote": false, + "printWidth": 120, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false, + "vueIndentScriptAndStyle": false + } + ] + } +} diff --git a/frontend/.prettierignore b/frontend/.prettierignore new file mode 100644 index 0000000..0a7a306 --- /dev/null +++ b/frontend/.prettierignore @@ -0,0 +1,2 @@ +package.json +build diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 0000000..66472f5 --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,19 @@ +{ + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxSingleQuote": false, + "printWidth": 120, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "useTabs": false, + "vueIndentScriptAndStyle": false +} diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 5f7493f..63384f0 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,14 +1,14 @@ -### STAGE 1: Build ### -FROM node:14-alpine as builder -WORKDIR /app -COPY package*.json ./ -RUN npm install -COPY . . -RUN npm run build - -### STAGE 2: Production Environment ### -FROM nginx:1.9.15-alpine -COPY --from=builder /app/build /usr/share/nginx/html -COPY --from=builder /app/nginx/nginx.conf /etc/nginx/conf.d/default.conf -EXPOSE 3000 +### STAGE 1: Build ### +FROM node:14-alpine as builder +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +### STAGE 2: Production Environment ### +FROM nginx:1.9.15-alpine +COPY --from=builder /app/build /usr/share/nginx/html +COPY --from=builder /app/nginx/nginx.conf /etc/nginx/conf.d/default.conf +EXPOSE 3000 CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev index 402dc40..c528b18 100644 --- a/frontend/Dockerfile.dev +++ b/frontend/Dockerfile.dev @@ -1,13 +1,13 @@ -FROM node:14-alpine - -WORKDIR /app - -COPY package*.json ./ - -RUN npm install - -COPY . . - -EXPOSE 3000 - +FROM node:14-alpine + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install + +COPY . . + +EXPOSE 3000 + CMD [ "npm", "start" ] \ No newline at end of file diff --git a/frontend/build/asset-manifest.json b/frontend/build/asset-manifest.json index cb47285..b6a55e3 100644 --- a/frontend/build/asset-manifest.json +++ b/frontend/build/asset-manifest.json @@ -1,18 +1,18 @@ -{ - "files": { - "main.css": "/static/css/main.dd87fb77.css", - "main.js": "/static/js/main.bb205d9b.js", - "static/js/27.58725458.chunk.js": "/static/js/27.58725458.chunk.js", - "static/media/xe.gif": "/static/media/xe.bbee5381a81e7e148999.gif", - "static/media/loading.gif": "/static/media/loading.944bc93cc92f717fa04b.gif", - "static/media/true.png": "/static/media/true.7f4b8091c267f8bdfd8c.png", - "static/media/home.jpg": "/static/media/home.0194505ca36882e84c67.jpg", - "static/media/logo.png": "/static/media/logo.da082dce2f5ca14e0ecb.png", - "static/media/stripes.png": "/static/media/stripes.537991bd56b3146f4d3d.png", - "index.html": "/index.html" - }, - "entrypoints": [ - "static/css/main.dd87fb77.css", - "static/js/main.bb205d9b.js" - ] +{ + "files": { + "main.css": "/static/css/main.dd87fb77.css", + "main.js": "/static/js/main.bb205d9b.js", + "static/js/27.58725458.chunk.js": "/static/js/27.58725458.chunk.js", + "static/media/xe.gif": "/static/media/xe.bbee5381a81e7e148999.gif", + "static/media/loading.gif": "/static/media/loading.944bc93cc92f717fa04b.gif", + "static/media/true.png": "/static/media/true.7f4b8091c267f8bdfd8c.png", + "static/media/home.jpg": "/static/media/home.0194505ca36882e84c67.jpg", + "static/media/logo.png": "/static/media/logo.da082dce2f5ca14e0ecb.png", + "static/media/stripes.png": "/static/media/stripes.537991bd56b3146f4d3d.png", + "index.html": "/index.html" + }, + "entrypoints": [ + "static/css/main.dd87fb77.css", + "static/js/main.bb205d9b.js" + ] } \ No newline at end of file diff --git a/frontend/build/manifest.json b/frontend/build/manifest.json index 080d6c7..2f2be64 100644 --- a/frontend/build/manifest.json +++ b/frontend/build/manifest.json @@ -1,25 +1,25 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/frontend/build/robots.txt b/frontend/build/robots.txt index e9e57dc..9dd52a5 100644 --- a/frontend/build/robots.txt +++ b/frontend/build/robots.txt @@ -1,3 +1,3 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/frontend/build/static/js/main.bb205d9b.js b/frontend/build/static/js/main.bb205d9b.js index 18a6ee6..8b81508 100644 --- a/frontend/build/static/js/main.bb205d9b.js +++ b/frontend/build/static/js/main.bb205d9b.js @@ -1,2 +1,2 @@ -/*! For license information please see main.bb205d9b.js.LICENSE.txt */ +/*! For license information please see main.bb205d9b.js.LICENSE.txt */ (function(){var __webpack_modules__={1881:function(e,t,n){e.exports=n(6948)},7570:function(e,t,n){"use strict";var r=n(899),i=n(8980),a=n(2508),o=n(3917),s=n(6551),l=n(7652),u=n(8652),c=n(775),d=n(4685),f=n(7691);e.exports=function(e){return new Promise((function(t,n){var h,p=e.data,m=e.headers,v=e.responseType;function g(){e.cancelToken&&e.cancelToken.unsubscribe(h),e.signal&&e.signal.removeEventListener("abort",h)}r.isFormData(p)&&delete m["Content-Type"];var y=new XMLHttpRequest;if(e.auth){var b=e.auth.username||"",_=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";m.Authorization="Basic "+btoa(b+":"+_)}var x=s(e.baseURL,e.url);function w(){if(y){var r="getAllResponseHeaders"in y?l(y.getAllResponseHeaders()):null,a={data:v&&"text"!==v&&"json"!==v?y.response:y.responseText,status:y.status,statusText:y.statusText,headers:r,config:e,request:y};i((function(e){t(e),g()}),(function(e){n(e),g()}),a),y=null}}if(y.open(e.method.toUpperCase(),o(x,e.params,e.paramsSerializer),!0),y.timeout=e.timeout,"onloadend"in y?y.onloadend=w:y.onreadystatechange=function(){y&&4===y.readyState&&(0!==y.status||y.responseURL&&0===y.responseURL.indexOf("file:"))&&setTimeout(w)},y.onabort=function(){y&&(n(c("Request aborted",e,"ECONNABORTED",y)),y=null)},y.onerror=function(){n(c("Network Error",e,null,y)),y=null},y.ontimeout=function(){var t=e.timeout?"timeout of "+e.timeout+"ms exceeded":"timeout exceeded",r=e.transitional||d.transitional;e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(c(t,e,r.clarifyTimeoutError?"ETIMEDOUT":"ECONNABORTED",y)),y=null},r.isStandardBrowserEnv()){var A=(e.withCredentials||u(x))&&e.xsrfCookieName?a.read(e.xsrfCookieName):void 0;A&&(m[e.xsrfHeaderName]=A)}"setRequestHeader"in y&&r.forEach(m,(function(e,t){"undefined"===typeof p&&"content-type"===t.toLowerCase()?delete m[t]:y.setRequestHeader(t,e)})),r.isUndefined(e.withCredentials)||(y.withCredentials=!!e.withCredentials),v&&"json"!==v&&(y.responseType=e.responseType),"function"===typeof e.onDownloadProgress&&y.addEventListener("progress",e.onDownloadProgress),"function"===typeof e.onUploadProgress&&y.upload&&y.upload.addEventListener("progress",e.onUploadProgress),(e.cancelToken||e.signal)&&(h=function(e){y&&(n(!e||e&&e.type?new f("canceled"):e),y.abort(),y=null)},e.cancelToken&&e.cancelToken.subscribe(h),e.signal&&(e.signal.aborted?h():e.signal.addEventListener("abort",h))),p||(p=null),y.send(p)}))}},6948:function(e,t,n){"use strict";var r=n(899),i=n(8813),a=n(5141),o=n(6276);var s=function e(t){var n=new a(t),s=i(a.prototype.request,n);return r.extend(s,a.prototype,n),r.extend(s,n),s.create=function(n){return e(o(t,n))},s}(n(4685));s.Axios=a,s.Cancel=n(7691),s.CancelToken=n(3914),s.isCancel=n(7797),s.VERSION=n(2102).version,s.all=function(e){return Promise.all(e)},s.spread=n(2922),s.isAxiosError=n(7079),e.exports=s,e.exports.default=s},7691:function(e){"use strict";function t(e){this.message=e}t.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},t.prototype.__CANCEL__=!0,e.exports=t},3914:function(e,t,n){"use strict";var r=n(7691);function i(e){if("function"!==typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var n=this;this.promise.then((function(e){if(n._listeners){var t,r=n._listeners.length;for(t=0;t=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};r.forEach(["delete","get","head"],(function(e){l.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){l.headers[e]=r.merge(o)})),e.exports=l},2102:function(e){e.exports={version:"0.25.0"}},8813:function(e){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r=0)return;o[t]="set-cookie"===t?(o[t]?o[t]:[]).concat([n]):o[t]?o[t]+", "+n:n}})),o):o}},2922:function(e){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},7828:function(e,t,n){"use strict";var r=n(2102).version,i={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){i[e]=function(n){return typeof n===e||"a"+(t<1?"n ":" ")+e}}));var a={};i.transitional=function(e,t,n){function i(e,t){return"[Axios v"+r+"] Transitional option '"+e+"'"+t+(n?". "+n:"")}return function(n,r,o){if(!1===e)throw new Error(i(r," has been removed"+(t?" in "+t:"")));return t&&!a[r]&&(a[r]=!0,console.warn(i(r," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(n,r,o)}},e.exports={assertOptions:function(e,t,n){if("object"!==typeof e)throw new TypeError("options must be an object");for(var r=Object.keys(e),i=r.length;i-- >0;){var a=r[i],o=t[a];if(o){var s=e[a],l=void 0===s||o(s,a,e);if(!0!==l)throw new TypeError("option "+a+" must be "+l)}else if(!0!==n)throw Error("Unknown option "+a)}},validators:i}},899:function(e,t,n){"use strict";var r=n(8813),i=Object.prototype.toString;function a(e){return Array.isArray(e)}function o(e){return"undefined"===typeof e}function s(e){return"[object ArrayBuffer]"===i.call(e)}function l(e){return null!==e&&"object"===typeof e}function u(e){if("[object Object]"!==i.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function c(e){return"[object Function]"===i.call(e)}function d(e,t){if(null!==e&&"undefined"!==typeof e)if("object"!==typeof e&&(e=[e]),a(e))for(var n=0,r=e.length;n1?n[1]=1:n[1]<=0&&(n[1]=0),HSVtoRGB(n[0],n[1],n[2])}function addBrightnessToRGB(e,t){var n=RGBtoHSV(255*e[0],255*e[1],255*e[2]);return n[2]+=t,n[2]>1?n[2]=1:n[2]<0&&(n[2]=0),HSVtoRGB(n[0],n[1],n[2])}function addHueToRGB(e,t){var n=RGBtoHSV(255*e[0],255*e[1],255*e[2]);return n[0]+=t/360,n[0]>1?n[0]-=1:n[0]<0&&(n[0]+=1),HSVtoRGB(n[0],n[1],n[2])}var rgbToHex=function(){var e,t,n=[];for(e=0;e<256;e+=1)t=e.toString(16),n[e]=1===t.length?"0"+t:t;return function(e,t,r){return e<0&&(e=0),t<0&&(t=0),r<0&&(r=0),"#"+n[e]+n[t]+n[r]}}(),setSubframeEnabled=function(e){subframeEnabled=!!e},getSubframeEnabled=function(){return subframeEnabled},setExpressionsPlugin=function(e){expressionsPlugin=e},getExpressionsPlugin=function(){return expressionsPlugin},setDefaultCurveSegments=function(e){defaultCurveSegments=e},getDefaultCurveSegments=function(){return defaultCurveSegments},setIdPrefix=function(e){idPrefix$1=e},getIdPrefix=function(){return idPrefix$1};function createNS(e){return document.createElementNS(svgNS,e)}function _typeof$5(e){return _typeof$5="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$5(e)}var dataManager=function(){var e,t,n=1,r=[],i={onmessage:function(){},postMessage:function(t){e({data:t})}},a={postMessage:function(e){i.onmessage({data:e})}};function o(){t||(t=function(t){if(window.Worker&&window.Blob&&getWebWorker()){var n=new Blob(["var _workerSelf = self; self.onmessage = ",t.toString()],{type:"text/javascript"}),r=URL.createObjectURL(n);return new Worker(r)}return e=t,i}((function(e){if(a.dataManager||(a.dataManager=function(){function e(i,a){var o,s,l,u,d,f,h=i.length;for(s=0;s=0;t-=1)if("sh"===e[t].ty)if(e[t].ks.k.i)r(e[t].ks.k);else for(a=e[t].ks.k.length,i=0;in[0]||!(n[0]>e[0])&&(e[1]>n[1]||!(n[1]>e[1])&&(e[2]>n[2]||!(n[2]>e[2])&&null))}var a=function(){var e=[4,4,14];function t(e){var t=e.t.d;e.t.d={k:[{s:t,t:0}]}}function n(e){var n,r=e.length;for(n=0;n=0;n-=1)if("sh"===e[n].ty)if(e[n].ks.k.i)e[n].ks.k.c=e[n].closed;else for(i=e[n].ks.k.length,r=0;r500)&&(this._imageLoaded(),clearInterval(n)),t+=1}.bind(this),50)}function a(e){var t={assetData:e},n=r(e,this.assetsPath,this.path);return dataManager.loadData(n,function(e){t.img=e,this._footageLoaded()}.bind(this),function(){t.img={},this._footageLoaded()}.bind(this)),t}function o(){this._imageLoaded=t.bind(this),this._footageLoaded=n.bind(this),this.testImageLoaded=i.bind(this),this.createFootageData=a.bind(this),this.assetsPath="",this.path="",this.totalImages=0,this.totalFootages=0,this.loadedAssets=0,this.loadedFootagesCount=0,this.imagesLoadedCb=null,this.images=[]}return o.prototype={loadAssets:function(e,t){var n;this.imagesLoadedCb=t;var r=e.length;for(n=0;nthis.animationData.op&&(this.animationData.op=e.op,this.totalFrames=Math.floor(e.op-this.animationData.ip));var t,n,r=this.animationData.layers,i=r.length,a=e.layers,o=a.length;for(n=0;nthis.timeCompleted&&(this.currentFrame=this.timeCompleted),this.trigger("enterFrame"),this.renderFrame(),this.trigger("drawnFrame")},AnimationItem.prototype.renderFrame=function(){if(!1!==this.isLoaded&&this.renderer)try{this.renderer.renderFrame(this.currentFrame+this.firstFrame)}catch(e){this.triggerRenderFrameError(e)}},AnimationItem.prototype.play=function(e){e&&this.name!==e||!0===this.isPaused&&(this.isPaused=!1,this.trigger("_pause"),this.audioController.resume(),this._idle&&(this._idle=!1,this.trigger("_active")))},AnimationItem.prototype.pause=function(e){e&&this.name!==e||!1===this.isPaused&&(this.isPaused=!0,this.trigger("_play"),this._idle=!0,this.trigger("_idle"),this.audioController.pause())},AnimationItem.prototype.togglePause=function(e){e&&this.name!==e||(!0===this.isPaused?this.play():this.pause())},AnimationItem.prototype.stop=function(e){e&&this.name!==e||(this.pause(),this.playCount=0,this._completedLoop=!1,this.setCurrentRawFrameValue(0))},AnimationItem.prototype.getMarkerData=function(e){for(var t,n=0;n=this.totalFrames-1&&this.frameModifier>0?this.loop&&this.playCount!==this.loop?t>=this.totalFrames?(this.playCount+=1,this.checkSegments(t%this.totalFrames)||(this.setCurrentRawFrameValue(t%this.totalFrames),this._completedLoop=!0,this.trigger("loopComplete"))):this.setCurrentRawFrameValue(t):this.checkSegments(t>this.totalFrames?t%this.totalFrames:0)||(n=!0,t=this.totalFrames-1):t<0?this.checkSegments(t%this.totalFrames)||(!this.loop||this.playCount--<=0&&!0!==this.loop?(n=!0,t=0):(this.setCurrentRawFrameValue(this.totalFrames+t%this.totalFrames),this._completedLoop?this.trigger("loopComplete"):this._completedLoop=!0)):this.setCurrentRawFrameValue(t),n&&(this.setCurrentRawFrameValue(t),this.pause(),this.trigger("complete"))}},AnimationItem.prototype.adjustSegment=function(e,t){this.playCount=0,e[1]0&&(this.playSpeed<0?this.setSpeed(-this.playSpeed):this.setDirection(-1)),this.totalFrames=e[0]-e[1],this.timeCompleted=this.totalFrames,this.firstFrame=e[1],this.setCurrentRawFrameValue(this.totalFrames-.001-t)):e[1]>e[0]&&(this.frameModifier<0&&(this.playSpeed<0?this.setSpeed(-this.playSpeed):this.setDirection(1)),this.totalFrames=e[1]-e[0],this.timeCompleted=this.totalFrames,this.firstFrame=e[0],this.setCurrentRawFrameValue(.001+t)),this.trigger("segmentStart")},AnimationItem.prototype.setSegment=function(e,t){var n=-1;this.isPaused&&(this.currentRawFrame+this.firstFramet&&(n=t-e)),this.firstFrame=e,this.totalFrames=t-e,this.timeCompleted=this.totalFrames,-1!==n&&this.goToAndStop(n,!0)},AnimationItem.prototype.playSegments=function(e,t){if(t&&(this.segments.length=0),"object"===_typeof$4(e[0])){var n,r=e.length;for(n=0;n=0;n-=1)t[n].animation.destroy(e)},e.freeze=function(){o=!0},e.unfreeze=function(){o=!1,p()},e.setVolume=function(e,n){var i;for(i=0;i=.001?function(e,t,n,r){for(var i=0;i<4;++i){var a=l(t,n,r);if(0===a)return t;t-=(s(t,n,r)-e)/a}return t}(e,u,t,r):0===c?u:function(e,t,n,r,i){var a,o,l=0;do{(a=s(o=t+(n-t)/2,r,i)-e)>0?n=o:t=o}while(Math.abs(a)>1e-7&&++l<10);return o}(e,a,a+n,t,r)}},e}(),pooling={double:function(e){return e.concat(createSizedArray(e.length))}},poolFactory=function(e,t,n){var r=0,i=e,a=createSizedArray(i);return{newElement:function(){return r?a[r-=1]:t()},release:function(e){r===i&&(a=pooling.double(a),i*=2),n&&n(e),a[r]=e,r+=1}}},bezierLengthPool=poolFactory(8,(function(){return{addedLength:0,percents:createTypedArray("float32",getDefaultCurveSegments()),lengths:createTypedArray("float32",getDefaultCurveSegments())}})),segmentsLengthPool=poolFactory(8,(function(){return{lengths:[],totalLength:0}}),(function(e){var t,n=e.lengths.length;for(t=0;t-.001&&o<.001}var n=function(e,t,n,r){var i,a,o,s,l,u,c=getDefaultCurveSegments(),d=0,f=[],h=[],p=bezierLengthPool.newElement();for(o=n.length,i=0;io?-1:1,u=!0;u;)if(r[a]<=o&&r[a+1]>o?(s=(o-r[a])/(r[a+1]-r[a]),u=!1):a+=l,a<0||a>=i-1){if(a===i-1)return n[a];u=!1}return n[a]+(n[a+1]-n[a])*s}var s=createTypedArray("float32",8);return{getSegmentsLength:function(e){var t,r=segmentsLengthPool.newElement(),i=e.c,a=e.v,o=e.o,s=e.i,l=e._length,u=r.lengths,c=0;for(t=0;t1&&(a=1);var c,d=o(a,u),f=o(l=l>1?1:l,u),h=t.length,p=1-d,m=1-f,v=p*p*p,g=d*p*p*3,y=d*d*p*3,b=d*d*d,_=p*p*m,x=d*p*m+p*d*m+p*p*f,w=d*d*m+p*d*f+d*p*f,A=d*d*f,k=p*m*m,E=d*m*m+p*f*m+p*m*f,S=d*f*m+p*f*f+d*m*f,P=d*f*f,C=m*m*m,T=f*m*m+m*f*m+m*m*f,O=f*f*m+m*f*f+f*m*f,$=f*f*f;for(c=0;ch?f>p?f-h-p:p-h-f:p>h?p-h-f:h-f-p)>-1e-4&&d<1e-4}}}var bez=bezFunction(),PropertyFactory=function(){var e=initialDefaultFrame,t=Math.abs;function n(e,t){var n,i=this.offsetTime;"multidimensional"===this.propType&&(n=createTypedArray("float32",this.pv.length));for(var a,o,s,l,u,c,d,f,h,p=t.lastIndex,m=p,v=this.keyframes.length-1,g=!0;g;){if(a=this.keyframes[m],o=this.keyframes[m+1],m===v-1&&e>=o.t-i){a.h&&(a=o),p=0;break}if(o.t-i>e){p=m;break}m=b||e<_){var w=e>=b?x.points.length-1:0;for(u=x.points[w].point.length,l=0;l=E&&k=b?(n[0]=y[0],n[1]=y[1],n[2]=y[2]):e<=_?(n[0]=a.s[0],n[1]=a.s[1],n[2]=a.s[2]):function(e,t){var n=t[0],r=t[1],i=t[2],a=t[3],o=Math.atan2(2*r*a-2*n*i,1-2*r*r-2*i*i),s=Math.asin(2*n*r+2*i*a),l=Math.atan2(2*n*a-2*r*i,1-2*n*n-2*i*i);e[0]=o/degToRads,e[1]=s/degToRads,e[2]=l/degToRads}(n,function(e,t,n){var r,i,a,o,s,l=[],u=e[0],c=e[1],d=e[2],f=e[3],h=t[0],p=t[1],m=t[2],v=t[3];return(i=u*h+c*p+d*m+f*v)<0&&(i=-i,h=-h,p=-p,m=-m,v=-v),1-i>1e-6?(r=Math.acos(i),a=Math.sin(r),o=Math.sin((1-n)*r)/a,s=Math.sin(n*r)/a):(o=1-n,s=n),l[0]=o*u+s*h,l[1]=o*c+s*p,l[2]=o*d+s*m,l[3]=o*f+s*v,l}(r(a.s),r(y),(e-_)/(b-_)));else for(m=0;m=b?c=1:e<_?c=0:(a.o.x.constructor===Array?(s.__fnct||(s.__fnct=[]),s.__fnct[m]?h=s.__fnct[m]:(S=void 0===a.o.x[m]?a.o.x[0]:a.o.x[m],P=void 0===a.o.y[m]?a.o.y[0]:a.o.y[m],C=void 0===a.i.x[m]?a.i.x[0]:a.i.x[m],T=void 0===a.i.y[m]?a.i.y[0]:a.i.y[m],h=BezierFactory.getBezierEasing(S,P,C,T).get,s.__fnct[m]=h)):s.__fnct?h=s.__fnct:(S=a.o.x,P=a.o.y,C=a.i.x,T=a.i.y,h=BezierFactory.getBezierEasing(S,P,C,T).get,a.keyframeMetadata=h),c=h((e-_)/(b-_)))),y=o.s||a.e,O=1===a.h?a.s[m]:a.s[m]+(y[m]-a.s[m])*c,"multidimensional"===this.propType?n[m]=O:n=O}return t.lastIndex=p,n}function r(e){var t=e[0]*degToRads,n=e[1]*degToRads,r=e[2]*degToRads,i=Math.cos(t/2),a=Math.cos(n/2),o=Math.cos(r/2),s=Math.sin(t/2),l=Math.sin(n/2),u=Math.sin(r/2);return[s*l*o+i*a*u,s*a*o+i*l*u,i*l*o-s*a*u,i*a*o-s*l*u]}function i(){var t=this.comp.renderedFrame-this.offsetTime,n=this.keyframes[0].t-this.offsetTime,r=this.keyframes[this.keyframes.length-1].t-this.offsetTime;if(!(t===this._caching.lastFrame||this._caching.lastFrame!==e&&(this._caching.lastFrame>=r&&t>=r||this._caching.lastFrame=t&&(this._caching._lastKeyframeIndex=-1,this._caching.lastIndex=0);var i=this.interpolateValue(t,this._caching);this.pv=i}return this._caching.lastFrame=t,this.pv}function a(e){var n;if("unidimensional"===this.propType)n=e*this.mult,t(this.v-n)>1e-5&&(this.v=n,this._mdf=!0);else for(var r=0,i=this.v.length;r1e-5&&(this.v[r]=n,this._mdf=!0),r+=1}function o(){if(this.elem.globalData.frameId!==this.frameId&&this.effectsSequence.length)if(this.lock)this.setVValue(this.pv);else{var e;this.lock=!0,this._mdf=this._isFirstFrame;var t=this.effectsSequence.length,n=this.kf?this.pv:this.data.k;for(e=0;e=this._maxLength&&this.doubleArrayLength(),n){case"v":a=this.v;break;case"i":a=this.i;break;case"o":a=this.o;break;default:a=[]}(!a[r]||a[r]&&!i)&&(a[r]=pointPool.newElement()),a[r][0]=e,a[r][1]=t},ShapePath.prototype.setTripleAt=function(e,t,n,r,i,a,o,s){this.setXYAt(e,t,"v",o,s),this.setXYAt(n,r,"o",o,s),this.setXYAt(i,a,"i",o,s)},ShapePath.prototype.reverse=function(){var e=new ShapePath;e.setPathData(this.c,this._length);var t=this.v,n=this.o,r=this.i,i=0;this.c&&(e.setTripleAt(t[0][0],t[0][1],r[0][0],r[0][1],n[0][0],n[0][1],0,!1),i=1);var a,o=this._length-1,s=this._length;for(a=i;a=h[h.length-1].t-this.offsetTime)r=h[h.length-1].s?h[h.length-1].s[0]:h[h.length-2].e[0],a=!0;else{for(var p,m,v,g=f,y=h.length-1,b=!0;b&&(p=h[g],!((m=h[g+1]).t-this.offsetTime>e));)g=m.t-this.offsetTime)c=1;else if(er&&t>r)||(this._caching.lastIndex=i0||e>-1e-6&&e<0?r(1e4*e)/1e4:e}function I(){var e=this.props;return"matrix("+$(e[0])+","+$(e[1])+","+$(e[4])+","+$(e[5])+","+$(e[12])+","+$(e[13])+")"}return function(){this.reset=i,this.rotate=a,this.rotateX=o,this.rotateY=s,this.rotateZ=l,this.skew=c,this.skewFromAxis=d,this.shear=u,this.scale=f,this.setTransform=h,this.translate=p,this.transform=m,this.applyToPoint=_,this.applyToX=x,this.applyToY=w,this.applyToZ=A,this.applyToPointArray=C,this.applyToTriplePoints=P,this.applyToPointStringified=T,this.toCSS=O,this.to2dCSS=I,this.clone=y,this.cloneFromProps=b,this.equals=g,this.inversePoints=S,this.inversePoint=E,this.getInverseMatrix=k,this._t=this.transform,this.isIdentity=v,this._identity=!0,this._identityCalculated=!1,this.props=createTypedArray("float32",16),this.reset()}}();function _typeof$3(e){return _typeof$3="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof$3(e)}var lottie={},standalone="__[STANDALONE]__",animationData="__[ANIMATIONDATA]__",renderer="";function setLocation(e){setLocationHref(e)}function searchAnimations(){!0===standalone?animationManager.searchAnimations(animationData,standalone,renderer):animationManager.searchAnimations()}function setSubframeRendering(e){setSubframeEnabled(e)}function setPrefix(e){setIdPrefix(e)}function loadAnimation(e){return!0===standalone&&(e.animationData=JSON.parse(animationData)),animationManager.loadAnimation(e)}function setQuality(e){if("string"===typeof e)switch(e){case"high":setDefaultCurveSegments(200);break;default:case"medium":setDefaultCurveSegments(50);break;case"low":setDefaultCurveSegments(10)}else!isNaN(e)&&e>1&&setDefaultCurveSegments(e);getDefaultCurveSegments()>=50?roundValues(!1):roundValues(!0)}function inBrowser(){return"undefined"!==typeof navigator}function installPlugin(e,t){"expressions"===e&&setExpressionsPlugin(t)}function getFactory(e){switch(e){case"propertyFactory":return PropertyFactory;case"shapePropertyFactory":return ShapePropertyFactory;case"matrix":return Matrix;default:return null}}function checkReady(){"complete"===document.readyState&&(clearInterval(readyStateCheckInterval),searchAnimations())}function getQueryVariable(e){for(var t=queryString.split("&"),n=0;n=1?a.push({s:e-1,e:t-1}):(a.push({s:e,e:1}),a.push({s:0,e:t-1}));var o,s,l=[],u=a.length;for(o=0;or+n||(c=s.s*i<=r?0:(s.s*i-r)/n,d=s.e*i>=r+n?1:(s.e*i-r)/n,l.push([c,d]))}return l.length||l.push([0,0]),l},TrimModifier.prototype.releasePathsData=function(e){var t,n=e.length;for(t=0;t1?1+a:this.s.v<0?0+a:this.s.v+a)>(n=this.e.v>1?1+a:this.e.v<0?0+a:this.e.v+a)){var o=t;t=n,n=o}t=1e-4*Math.round(1e4*t),n=1e-4*Math.round(1e4*n),this.sValue=t,this.eValue=n}else t=this.sValue,n=this.eValue;var s,l,u,c,d,f=this.shapes.length,h=0;if(n===t)for(i=0;i=0;i-=1)if((p=this.shapes[i]).shape._mdf){for((m=p.localShapeCollection).releaseShapes(),2===this.m&&f>1?(g=this.calculateShapeEdges(t,n,p.totalShapeLength,_,h),_+=p.totalShapeLength):g=[[y,b]],l=g.length,s=0;s=1?v.push({s:p.totalShapeLength*(y-1),e:p.totalShapeLength*(b-1)}):(v.push({s:p.totalShapeLength*y,e:p.totalShapeLength}),v.push({s:0,e:p.totalShapeLength*(b-1)}));var x=this.addShapes(p,v[0]);if(v[0].s!==v[0].e){if(v.length>1)if(p.shape.paths.shapes[p.shape.paths._length-1].c){var w=x.pop();this.addPaths(x,m),x=this.addShapes(p,v[1],w)}else this.addPaths(x,m),x=this.addShapes(p,v[1]);this.addPaths(x,m)}}p.shape.paths=m}}},TrimModifier.prototype.addPaths=function(e,t){var n,r=e.length;for(n=0;nt.e){n.c=!1;break}t.s<=p&&t.e>=p+o.addedLength?(this.addSegment(f[r].v[i-1],f[r].o[i-1],f[r].i[i],f[r].v[i],n,s,v),v=!1):(u=bez.getNewSegment(f[r].v[i-1],f[r].v[i],f[r].o[i-1],f[r].i[i],(t.s-p)/o.addedLength,(t.e-p)/o.addedLength,l[i-1]),this.addSegmentFromArray(u,n,s,v),v=!1,n.c=!1),p+=o.addedLength,s+=1}if(f[r].c&&l.length){if(o=l[i-1],p<=t.e){var g=l[i-1].addedLength;t.s<=p&&t.e>=p+g?(this.addSegment(f[r].v[i-1],f[r].o[i-1],f[r].i[0],f[r].v[0],n,s,v),v=!1):(u=bez.getNewSegment(f[r].v[i-1],f[r].v[0],f[r].o[i-1],f[r].i[0],(t.s-p)/g,(t.e-p)/g,l[i-1]),this.addSegmentFromArray(u,n,s,v),v=!1,n.c=!1)}else n.c=!1;p+=o.addedLength,s+=1}if(n._length&&(n.setXYAt(n.v[c][0],n.v[c][1],"i",c),n.setXYAt(n.v[n._length-1][0],n.v[n._length-1][1],"o",n._length-1)),p>t.e)break;r=this.p.keyframes[this.p.keyframes.length-1].t?(r=this.p.getValueAtTime(this.p.keyframes[this.p.keyframes.length-1].t/n,0),i=this.p.getValueAtTime((this.p.keyframes[this.p.keyframes.length-1].t-.05)/n,0)):(r=this.p.pv,i=this.p.getValueAtTime((this.p._caching.lastFrame+this.p.offsetTime-.01)/n,this.p.offsetTime));else if(this.px&&this.px.keyframes&&this.py.keyframes&&this.px.getValueAtTime&&this.py.getValueAtTime){r=[],i=[];var a=this.px,o=this.py;a._caching.lastFrame+a.offsetTime<=a.keyframes[0].t?(r[0]=a.getValueAtTime((a.keyframes[0].t+.01)/n,0),r[1]=o.getValueAtTime((o.keyframes[0].t+.01)/n,0),i[0]=a.getValueAtTime(a.keyframes[0].t/n,0),i[1]=o.getValueAtTime(o.keyframes[0].t/n,0)):a._caching.lastFrame+a.offsetTime>=a.keyframes[a.keyframes.length-1].t?(r[0]=a.getValueAtTime(a.keyframes[a.keyframes.length-1].t/n,0),r[1]=o.getValueAtTime(o.keyframes[o.keyframes.length-1].t/n,0),i[0]=a.getValueAtTime((a.keyframes[a.keyframes.length-1].t-.01)/n,0),i[1]=o.getValueAtTime((o.keyframes[o.keyframes.length-1].t-.01)/n,0)):(r=[a.pv,o.pv],i[0]=a.getValueAtTime((a._caching.lastFrame+a.offsetTime-.01)/n,a.offsetTime),i[1]=o.getValueAtTime((o._caching.lastFrame+o.offsetTime-.01)/n,o.offsetTime))}else r=i=e;this.v.rotate(-Math.atan2(r[1]-i[1],r[0]-i[0]))}this.data.p&&this.data.p.s?this.data.p.z?this.v.translate(this.px.v,this.py.v,-this.pz.v):this.v.translate(this.px.v,this.py.v,0):this.v.translate(this.p.v[0],this.p.v[1],-this.p.v[2])}this.frameId=this.elem.globalData.frameId}},precalculateMatrix:function(){if(!this.a.k&&(this.pre.translate(-this.a.v[0],-this.a.v[1],this.a.v[2]),this.appliedTransformations=1,!this.s.effectsSequence.length)){if(this.pre.scale(this.s.v[0],this.s.v[1],this.s.v[2]),this.appliedTransformations=2,this.sk){if(this.sk.effectsSequence.length||this.sa.effectsSequence.length)return;this.pre.skewFromAxis(-this.sk.v,this.sa.v),this.appliedTransformations=3}this.r?this.r.effectsSequence.length||(this.pre.rotate(-this.r.v),this.appliedTransformations=4):this.rz.effectsSequence.length||this.ry.effectsSequence.length||this.rx.effectsSequence.length||this.or.effectsSequence.length||(this.pre.rotateZ(-this.rz.v).rotateY(this.ry.v).rotateX(this.rx.v).rotateZ(-this.or.v[2]).rotateY(this.or.v[1]).rotateX(this.or.v[0]),this.appliedTransformations=4)}},autoOrient:function(){}},extendPrototype([DynamicPropertyContainer],t),t.prototype.addDynamicProperty=function(e){this._addDynamicProperty(e),this.elem.addDynamicProperty(e),this._isDirty=!0},t.prototype._addDynamicProperty=DynamicPropertyContainer.prototype.addDynamicProperty,{getTransformProperty:function(e,n,r){return new t(e,n,r)}}}();function RepeaterModifier(){}function RoundCornersModifier(){}function getFontProperties(e){for(var t=e.fStyle?e.fStyle.split(" "):[],n="normal",r="normal",i=t.length,a=0;a0;)n-=1,this._elements.unshift(t[n]);this.dynamicProperties.length?this.k=!0:this.getValue(!0)},RepeaterModifier.prototype.resetElements=function(e){var t,n=e.length;for(t=0;t0?Math.floor(f):Math.ceil(f),m=this.pMatrix.props,v=this.rMatrix.props,g=this.sMatrix.props;this.pMatrix.reset(),this.rMatrix.reset(),this.sMatrix.reset(),this.tMatrix.reset(),this.matrix.reset();var y,b,_=0;if(f>0){for(;_p;)this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!0),_-=1;h&&(this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,-h,!0),_-=h)}for(r=1===this.data.m?0:this._currentCopies-1,i=1===this.data.m?1:-1,a=this._currentCopies;a;){if(b=(n=(t=this.elemsData[r].it)[t.length-1].transform.mProps.v.props).length,t[t.length-1].transform.mProps._mdf=!0,t[t.length-1].transform.op._mdf=!0,t[t.length-1].transform.op.v=1===this._currentCopies?this.so.v:this.so.v+(this.eo.v-this.so.v)*(r/(this._currentCopies-1)),0!==_){for((0!==r&&1===i||r!==this._currentCopies-1&&-1===i)&&this.applyTransforms(this.pMatrix,this.rMatrix,this.sMatrix,this.tr,1,!1),this.matrix.transform(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]),this.matrix.transform(g[0],g[1],g[2],g[3],g[4],g[5],g[6],g[7],g[8],g[9],g[10],g[11],g[12],g[13],g[14],g[15]),this.matrix.transform(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9],m[10],m[11],m[12],m[13],m[14],m[15]),y=0;y0&&(c=!1),c){var d=createTag("style");d.setAttribute("f-forigin",r[n].fOrigin),d.setAttribute("f-origin",r[n].origin),d.setAttribute("f-family",r[n].fFamily),d.type="text/css",d.innerText="@font-face {font-family: "+r[n].fFamily+"; font-style: normal; src: url('"+r[n].fPath+"');}",t.appendChild(d)}}else if("g"===r[n].fOrigin||1===r[n].origin){for(l=document.querySelectorAll('link[f-forigin="g"], link[f-origin="1"]'),u=0;ue?!0!==this.isInRange&&(this.globalData._mdf=!0,this._mdf=!0,this.isInRange=!0,this.show()):!1!==this.isInRange&&(this.globalData._mdf=!0,this.isInRange=!1,this.hide())},renderRenderable:function(){var e,t=this.renderableComponents.length;for(e=0;e0&&(this.maskElement.setAttribute("id",v),this.element.maskedElement.setAttribute(y,"url("+getLocationHref()+"#"+v+")"),a.appendChild(this.maskElement)),this.viewData.length&&this.element.addRenderableComponent(this)}FootageElement.prototype.prepareFrame=function(){},extendPrototype([RenderableElement,BaseElement,FrameElement],FootageElement),FootageElement.prototype.getBaseElement=function(){return null},FootageElement.prototype.renderFrame=function(){},FootageElement.prototype.destroy=function(){},FootageElement.prototype.initExpressions=function(){this.layerInterface=FootageInterface(this)},FootageElement.prototype.getFootageData=function(){return this.footageData},AudioElement.prototype.prepareFrame=function(e){if(this.prepareRenderableFrame(e,!0),this.prepareProperties(e,!0),this.tm._placeholder)this._currentTime=e/this.data.sr;else{var t=this.tm.v;this._currentTime=t}this._volume=this.lv.v[0];var n=this._volume*this._volumeMultiplier;this._previousVolume!==n&&(this._previousVolume=n,this.audio.volume(n))},extendPrototype([RenderableElement,BaseElement,FrameElement],AudioElement),AudioElement.prototype.renderFrame=function(){this.isInRange&&this._canPlay&&(this._isPlaying?(!this.audio.playing()||Math.abs(this._currentTime/this.globalData.frameRate-this.audio.seek())>.1)&&this.audio.seek(this._currentTime/this.globalData.frameRate):(this.audio.play(),this.audio.seek(this._currentTime/this.globalData.frameRate),this._isPlaying=!0))},AudioElement.prototype.show=function(){},AudioElement.prototype.hide=function(){this.audio.pause(),this._isPlaying=!1},AudioElement.prototype.pause=function(){this.audio.pause(),this._isPlaying=!1,this._canPlay=!1},AudioElement.prototype.resume=function(){this._canPlay=!0},AudioElement.prototype.setRate=function(e){this.audio.rate(e)},AudioElement.prototype.volume=function(e){this._volumeMultiplier=e,this._previousVolume=e*this._volume,this.audio.volume(this._previousVolume)},AudioElement.prototype.getBaseElement=function(){return null},AudioElement.prototype.destroy=function(){},AudioElement.prototype.sourceRectAtTime=function(){},AudioElement.prototype.initExpressions=function(){},BaseRenderer.prototype.checkLayers=function(e){var t,n,r=this.layers.length;for(this.completeLayers=!0,t=r-1;t>=0;t-=1)this.elements[t]||(n=this.layers[t]).ip-n.st<=e-this.layers[t].st&&n.op-n.st>e-this.layers[t].st&&this.buildItem(t),this.completeLayers=!!this.elements[t]&&this.completeLayers;this.checkPendingElements()},BaseRenderer.prototype.createItem=function(e){switch(e.ty){case 2:return this.createImage(e);case 0:return this.createComp(e);case 1:return this.createSolid(e);case 3:default:return this.createNull(e);case 4:return this.createShape(e);case 5:return this.createText(e);case 6:return this.createAudio(e);case 13:return this.createCamera(e);case 15:return this.createFootage(e)}},BaseRenderer.prototype.createCamera=function(){throw new Error("You're using a 3d camera. Try the html renderer.")},BaseRenderer.prototype.createAudio=function(e){return new AudioElement(e,this.globalData,this)},BaseRenderer.prototype.createFootage=function(e){return new FootageElement(e,this.globalData,this)},BaseRenderer.prototype.buildAllItems=function(){var e,t=this.layers.length;for(e=0;e1&&(a+=" C"+t.o[r-1][0]+","+t.o[r-1][1]+" "+t.i[0][0]+","+t.i[0][1]+" "+t.v[0][0]+","+t.v[0][1]),n.lastPath!==a){var o="";n.elem&&(t.c&&(o=e.inv?this.solidPath+a:a),n.elem.setAttribute("d",o)),n.lastPath=a}},MaskElement.prototype.destroy=function(){this.element=null,this.globalData=null,this.maskElement=null,this.data=null,this.masksProperties=null};var filtersFactory=function(){var e={createFilter:function(e,t){var n=createNS("filter");return n.setAttribute("id",e),!0!==t&&(n.setAttribute("filterUnits","objectBoundingBox"),n.setAttribute("x","0%"),n.setAttribute("y","0%"),n.setAttribute("width","100%"),n.setAttribute("height","100%")),n},createAlphaToLuminanceFilter:function(){var e=createNS("feColorMatrix");return e.setAttribute("type","matrix"),e.setAttribute("color-interpolation-filters","sRGB"),e.setAttribute("values","0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 1"),e}};return e}(),featureSupport=function(){var e={maskType:!0};return(/MSIE 10/i.test(navigator.userAgent)||/MSIE 9/i.test(navigator.userAgent)||/rv:11.0/i.test(navigator.userAgent)||/Edge\/\d./i.test(navigator.userAgent))&&(e.maskType=!1),e}(),registeredEffects={},idPrefix="filter_result_";function SVGEffects(e){var t,n,r="SourceGraphic",i=e.data.ef?e.data.ef.length:0,a=createElementID(),o=filtersFactory.createFilter(a,!0),s=0;for(this.filters=[],t=0;t=0&&!this.shapeModifiers[e].processShapes(this._isFirstFrame);e-=1);}},searchProcessedElement:function(e){for(var t=this.processedElements,n=0,r=t.length;n.01)return!1;n+=1}return!0},GradientProperty.prototype.checkCollapsable=function(){if(this.o.length/2!==this.c.length/4)return!1;if(this.data.k.k[0].s)for(var e=0,t=this.data.k.k.length;e0;)l=r.transformers[m].mProps._mdf||l,p-=1,m-=1;if(l)for(p=g-r.styles[c].lvl,m=r.transformers.length-1;p>0;)h=r.transformers[m].mProps.v.props,f.transform(h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7],h[8],h[9],h[10],h[11],h[12],h[13],h[14],h[15]),p-=1,m-=1}else f=e;if(o=(d=r.sh.paths)._length,l){for(s="",a=0;a=1?y=.99:y<=-1&&(y=-.99);var b=s*y,_=Math.cos(g+t.a.v)*b+c[0],x=Math.sin(g+t.a.v)*b+c[1];l.setAttribute("fx",_),l.setAttribute("fy",x),u&&!t.g._collapsable&&(t.of.setAttribute("fx",_),t.of.setAttribute("fy",x))}}function l(e,t,n){var r=t.style,i=t.d;i&&(i._mdf||n)&&i.dashStr&&(r.pElem.setAttribute("stroke-dasharray",i.dashStr),r.pElem.setAttribute("stroke-dashoffset",i.dashoffset[0])),t.c&&(t.c._mdf||n)&&r.pElem.setAttribute("stroke","rgb("+bmFloor(t.c.v[0])+","+bmFloor(t.c.v[1])+","+bmFloor(t.c.v[2])+")"),(t.o._mdf||n)&&r.pElem.setAttribute("stroke-opacity",t.o.v),(t.w._mdf||n)&&(r.pElem.setAttribute("stroke-width",t.w.v),r.msElem&&r.msElem.setAttribute("stroke-width",t.w.v))}return{createRenderFunction:function(e){switch(e.ty){case"fl":return a;case"gf":return s;case"gs":return o;case"st":return l;case"sh":case"el":case"rc":case"sr":return i;case"tr":return n;case"no":return r;default:return null}}}}();function SVGShapeElement(e,t,n){this.shapes=[],this.shapesData=e.shapes,this.stylesList=[],this.shapeModifiers=[],this.itemsData=[],this.processedElements=[],this.animatedContents=[],this.initElement(e,t,n),this.prevViewData=[]}function LetterProps(e,t,n,r,i,a){this.o=e,this.sw=t,this.sc=n,this.fc=r,this.m=i,this.p=a,this._mdf={o:!0,sw:!!t,sc:!!n,fc:!!r,m:!0,p:!0}}function TextProperty(e,t){this._frameId=initialDefaultFrame,this.pv="",this.v="",this.kf=!1,this._isFirstFrame=!0,this._mdf=!1,this.data=t,this.elem=e,this.comp=this.elem.comp,this.keysIndex=0,this.canResize=!1,this.minimumFontSize=1,this.effectsSequence=[],this.currentData={ascent:0,boxWidth:this.defaultBoxWidth,f:"",fStyle:"",fWeight:"",fc:"",j:"",justifyOffset:"",l:[],lh:0,lineWidths:[],ls:"",of:"",s:"",sc:"",sw:0,t:0,tr:0,sz:0,ps:null,fillColorAnim:!1,strokeColorAnim:!1,strokeWidthAnim:!1,yOffset:0,finalSize:0,finalText:[],finalLineHeight:0,__complete:!1},this.copyData(this.currentData,this.data.d.k[0].s),this.searchProperty()||this.completeTextData(this.currentData)}extendPrototype([BaseElement,TransformElement,SVGBaseElement,IShapeElement,HierarchyElement,FrameElement,RenderableDOMElement],SVGShapeElement),SVGShapeElement.prototype.initSecondaryElement=function(){},SVGShapeElement.prototype.identityMatrix=new Matrix,SVGShapeElement.prototype.buildExpressionInterface=function(){},SVGShapeElement.prototype.createContent=function(){this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.layerElement,0,[],!0),this.filterUniqueShapes()},SVGShapeElement.prototype.filterUniqueShapes=function(){var e,t,n,r,i=this.shapes.length,a=this.stylesList.length,o=[],s=!1;for(n=0;n1&&s&&this.setShapesAsAnimated(o)}},SVGShapeElement.prototype.setShapesAsAnimated=function(e){var t,n=e.length;for(t=0;t=0;s-=1){if((f=this.searchProcessedElement(e[s]))?t[s]=n[f-1]:e[s]._render=o,"fl"===e[s].ty||"st"===e[s].ty||"gf"===e[s].ty||"gs"===e[s].ty||"no"===e[s].ty)f?t[s].style.closed=!1:t[s]=this.createStyleElement(e[s],i),e[s]._render&&t[s].style.pElem.parentNode!==r&&r.appendChild(t[s].style.pElem),m.push(t[s].style);else if("gr"===e[s].ty){if(f)for(u=t[s].it.length,l=0;l1,this.kf&&this.addEffect(this.getKeyframeValue.bind(this)),this.kf},TextProperty.prototype.addEffect=function(e){this.effectsSequence.push(e),this.elem.addDynamicProperty(this)},TextProperty.prototype.getValue=function(e){if(this.elem.globalData.frameId!==this.frameId&&this.effectsSequence.length||e){this.currentData.t=this.data.d.k[this.keysIndex].s.t;var t=this.currentData,n=this.keysIndex;if(this.lock)this.setCurrentData(this.currentData);else{var r;this.lock=!0,this._mdf=!1;var i=this.effectsSequence.length,a=e||this.data.d.k[this.keysIndex].s;for(r=0;rt);)n+=1;return this.keysIndex!==n&&(this.keysIndex=n),this.data.d.k[this.keysIndex].s},TextProperty.prototype.buildFinalText=function(e){for(var t,n,r=[],i=0,a=e.length,o=!1;i=55296&&t<=56319?(n=e.charCodeAt(i+1))>=56320&&n<=57343?(o||FontManager.isModifier(t,n)?(r[r.length-1]+=e.substr(i,2),o=!1):r.push(e.substr(i,2)),i+=1):r.push(e.charAt(i)):t>56319?(n=e.charCodeAt(i+1),FontManager.isZeroWidthJoiner(t,n)?(o=!0,r[r.length-1]+=e.substr(i,2),i+=1):r.push(e.charAt(i))):FontManager.isZeroWidthJoiner(t)?(r[r.length-1]+=e.charAt(i),o=!0):r.push(e.charAt(i)),i+=1;return r},TextProperty.prototype.completeTextData=function(e){e.__complete=!0;var t,n,r,i,a,o,s,l=this.elem.globalData.fontManager,u=this.data,c=[],d=0,f=u.m.g,h=0,p=0,m=0,v=[],g=0,y=0,b=l.getFontByName(e.f),_=0,x=getFontProperties(b);e.fWeight=x.weight,e.fStyle=x.style,e.finalSize=e.s,e.finalText=this.buildFinalText(e.t),n=e.finalText.length,e.finalLineHeight=e.lh;var w,A=e.tr/1e3*e.finalSize;if(e.sz)for(var k,E,S=!0,P=e.sz[0],C=e.sz[1];S;){k=0,g=0,n=(E=this.buildFinalText(e.t)).length,A=e.tr/1e3*e.finalSize;var T=-1;for(t=0;tP&&" "!==E[t]?(-1===T?n+=1:t=T,k+=e.finalLineHeight||1.2*e.finalSize,E.splice(t,T===t?1:0,"\r"),T=-1,g=0):(g+=_,g+=A);k+=b.ascent*e.finalSize/100,this.canResize&&e.finalSize>this.minimumFontSize&&Cy?g:y,g=-2*A,i="",r=!0,m+=1):i=O,l.chars?(s=l.getCharData(O,b.fStyle,l.getFontByName(e.f).fFamily),_=r?0:s.w*e.finalSize/100):_=l.measureText(i,e.f,e.finalSize)," "===O?$+=_+A:(g+=_+A+$,$=0),c.push({l:_,an:_,add:h,n:r,anIndexes:[],val:i,line:m,animatorJustifyOffset:0}),2==f){if(h+=_,""===i||" "===i||t===n-1){for(""!==i&&" "!==i||(h-=_);p<=t;)c[p].an=h,c[p].ind=d,c[p].extra=_,p+=1;d+=1,h=0}}else if(3==f){if(h+=_,""===i||t===n-1){for(""===i&&(h-=_);p<=t;)c[p].an=h,c[p].ind=d,c[p].extra=_,p+=1;h=0,d+=1}}else c[d].ind=d,c[d].extra=0,d+=1;if(e.l=c,y=g>y?g:y,v.push(g),e.sz)e.boxWidth=e.sz[0],e.justifyOffset=0;else switch(e.boxWidth=y,e.j){case 1:e.justifyOffset=-e.boxWidth;break;case 2:e.justifyOffset=-e.boxWidth/2;break;default:e.justifyOffset=0}e.lineWidths=v;var I,N,D,M,R=u.a;o=R.length;var j=[];for(a=0;a0?i=this.ne.v/100:a=-this.ne.v/100,this.xe.v>0?o=1-this.xe.v/100:s=1+this.xe.v/100;var l=BezierFactory.getBezierEasing(i,a,o,s).get,u=0,c=this.finalS,d=this.finalE,f=this.data.sh;if(2===f)u=l(u=d===c?r>=d?1:0:e(0,t(.5/(d-c)+(r-c)/(d-c),1)));else if(3===f)u=l(u=d===c?r>=d?0:1:1-e(0,t(.5/(d-c)+(r-c)/(d-c),1)));else if(4===f)d===c?u=0:(u=e(0,t(.5/(d-c)+(r-c)/(d-c),1)))<.5?u*=2:u=1-2*(u-.5),u=l(u);else if(5===f){if(d===c)u=0;else{var h=d-c,p=-h/2+(r=t(e(0,r+.5-c),d-c)),m=h/2;u=Math.sqrt(1-p*p/(m*m))}u=l(u)}else 6===f?(d===c?u=0:(r=t(e(0,r+.5-c),d-c),u=(1+Math.cos(Math.PI+2*Math.PI*r/(d-c)))/2),u=l(u)):(r>=n(c)&&(u=e(0,t(r-c<0?t(d,1)-(c-r):d-r,1))),u=l(u));if(100!==this.sm.v){var v=.01*this.sm.v;0===v&&(v=1e-8);var g=.5-.5*v;u1&&(u=1)}return u*this.a.v},getValue:function(e){this.iterateDynamicProperties(),this._mdf=e||this._mdf,this._currentTextLength=this.elem.textProperty.currentData.l.length||0,e&&2===this.data.r&&(this.e.v=this._currentTextLength);var t=2===this.data.r?1:100/this.data.totalChars,n=this.o.v/t,r=this.s.v/t+n,i=this.e.v/t+n;if(r>i){var a=r;r=i,i=a}this.finalS=r,this.finalE=i}},extendPrototype([DynamicPropertyContainer],r),{getTextSelectorProp:function(e,t,n){return new r(e,t,n)}}}();function TextAnimatorDataProperty(e,t,n){var r={propType:!1},i=PropertyFactory.getProp,a=t.a;this.a={r:a.r?i(e,a.r,0,degToRads,n):r,rx:a.rx?i(e,a.rx,0,degToRads,n):r,ry:a.ry?i(e,a.ry,0,degToRads,n):r,sk:a.sk?i(e,a.sk,0,degToRads,n):r,sa:a.sa?i(e,a.sa,0,degToRads,n):r,s:a.s?i(e,a.s,1,.01,n):r,a:a.a?i(e,a.a,1,0,n):r,o:a.o?i(e,a.o,0,.01,n):r,p:a.p?i(e,a.p,1,0,n):r,sw:a.sw?i(e,a.sw,0,0,n):r,sc:a.sc?i(e,a.sc,1,0,n):r,fc:a.fc?i(e,a.fc,1,0,n):r,fh:a.fh?i(e,a.fh,0,0,n):r,fs:a.fs?i(e,a.fs,0,.01,n):r,fb:a.fb?i(e,a.fb,0,.01,n):r,t:a.t?i(e,a.t,0,0,n):r},this.s=TextSelectorProp.getTextSelectorProp(e,t.s,n),this.s.t=t.s.t}function TextAnimatorProperty(e,t,n){this._isFirstFrame=!0,this._hasMaskedPath=!1,this._frameId=-1,this._textData=e,this._renderType=t,this._elem=n,this._animatorsData=createSizedArray(this._textData.a.length),this._pathData={},this._moreOptions={alignment:{}},this.renderedLetters=[],this.lettersChangedFlag=!1,this.initDynamicPropertyContainer(n)}function ITextElement(){}TextAnimatorProperty.prototype.searchProperties=function(){var e,t,n=this._textData.a.length,r=PropertyFactory.getProp;for(e=0;e=s+se||!p?(y=(s+se-u)/l.partialLength,L=h.point[0]+(l.point[0]-h.point[0])*y,F=h.point[1]+(l.point[1]-h.point[1])*y,k.translate(-x[0]*P[i].an*.005,-x[1]*M*.01),c=!1):p&&(u+=l.partialLength,(d+=1)>=p.length&&(d=0,m[f+=1]?p=m[f].points:_.v.c?(d=0,p=m[f=0].points):(u-=l.partialLength,p=null)),p&&(h=l,v=(l=p[d]).partialLength));j=P[i].an/2-P[i].add,k.translate(-j,0,0)}else j=P[i].an/2-P[i].add,k.translate(-j,0,0),k.translate(-x[0]*P[i].an*.005,-x[1]*M*.01,0);for($=0;$e?this.textSpans[e].span:createNS(l?"g":"text"),v<=e){if(o.setAttribute("stroke-linecap","butt"),o.setAttribute("stroke-linejoin","round"),o.setAttribute("stroke-miterlimit","4"),this.textSpans[e].span=o,l){var g=createNS("g");o.appendChild(g),this.textSpans[e].childSpan=g}this.textSpans[e].span=o,this.layerElement.appendChild(o)}o.style.display="inherit"}if(u.reset(),c&&(s[e].n&&(d=-p,f+=n.yOffset,f+=h?1:0,h=!1),this.applyTextPropertiesToMatrix(n,u,s[e].line,d,f),d+=s[e].l||0,d+=p),l){var y;if(1===(m=this.globalData.fontManager.getCharData(n.finalText[e],r.fStyle,this.globalData.fontManager.getFontByName(n.f).fFamily)).t)y=new SVGCompElement(m.data,this.globalData,this);else{var b=emptyShapeData;m.data&&m.data.shapes&&(b=this.buildShapeData(m.data,n.finalSize)),y=new SVGShapeElement(b,this.globalData,this)}if(this.textSpans[e].glyph){var _=this.textSpans[e].glyph;this.textSpans[e].childSpan.removeChild(_.layerElement),_.destroy()}this.textSpans[e].glyph=y,y._debug=!0,y.prepareFrame(0),y.renderFrame(),this.textSpans[e].childSpan.appendChild(y.layerElement),1===m.t&&this.textSpans[e].childSpan.setAttribute("transform","scale("+n.finalSize/100+","+n.finalSize/100+")")}else c&&o.setAttribute("transform","translate("+u.props[12]+","+u.props[13]+")"),o.textContent=s[e].val,o.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve")}c&&o&&o.setAttribute("d","")}else{var x=this.textContainer,w="start";switch(n.j){case 1:w="end";break;case 2:w="middle";break;default:w="start"}x.setAttribute("text-anchor",w),x.setAttribute("letter-spacing",p);var A=this.buildTextContents(n.finalText);for(t=A.length,f=n.ps?n.ps[1]+n.ascent:0,e=0;e=0;t-=1)(this.completeLayers||this.elements[t])&&this.elements[t].prepareFrame(e-this.layers[t].st);if(this.globalData._mdf)for(t=0;t=0;n-=1)(this.completeLayers||this.elements[n])&&(this.elements[n].prepareFrame(this.renderedFrame-this.layers[n].st),this.elements[n]._mdf&&(this._mdf=!0))}},ICompElement.prototype.renderInnerContent=function(){var e,t=this.layers.length;for(e=0;e=0;r-=1)n=e.transforms[r].transform.mProps.v.props,e.finalTransform.transform(n[0],n[1],n[2],n[3],n[4],n[5],n[6],n[7],n[8],n[9],n[10],n[11],n[12],n[13],n[14],n[15]);e._mdf=a},processSequences:function(e){var t,n=this.sequenceList.length;for(t=0;t=0;a-=1){if((l=this.searchProcessedElement(e[a]))?t[a]=n[l-1]:e[a]._shouldRender=r,"fl"===e[a].ty||"st"===e[a].ty||"gf"===e[a].ty||"gs"===e[a].ty)l?t[a].style.closed=!1:t[a]=this.createStyleElement(e[a],p),f.push(t[a].style);else if("gr"===e[a].ty){if(l)for(s=t[a].it.length,o=0;o=0;i-=1)"tr"===t[i].ty?(a=n[i].transform,this.renderShapeTransform(e,a)):"sh"===t[i].ty||"el"===t[i].ty||"rc"===t[i].ty||"sr"===t[i].ty?this.renderPath(t[i],n[i]):"fl"===t[i].ty?this.renderFill(t[i],n[i],a):"st"===t[i].ty?this.renderStroke(t[i],n[i],a):"gf"===t[i].ty||"gs"===t[i].ty?this.renderGradientFill(t[i],n[i],a):"gr"===t[i].ty?this.renderShape(a,t[i].it,n[i].it):t[i].ty;r&&this.drawLayer()},CVShapeElement.prototype.renderStyledShape=function(e,t){if(this._isFirstFrame||t._mdf||e.transforms._mdf){var n,r,i,a=e.trNodes,o=t.paths,s=o._length;a.length=0;var l=e.transforms.finalTransform;for(i=0;i=1?d=.99:d<=-1&&(d=-.99);var f=u*d,h=Math.cos(c+t.a.v)*f+s[0],p=Math.sin(c+t.a.v)*f+s[1];r=o.createRadialGradient(h,p,0,s[0],s[1],u)}var m=e.g.p,v=t.g.c,g=1;for(a=0;as&&"xMidYMid slice"===l||on&&"meet"===a||rn&&"slice"===a)?(e-this.transformCanvas.w*(t/this.transformCanvas.h))/2*this.renderConfig.dpr:"xMax"===s&&(rn&&"slice"===a)?(e-this.transformCanvas.w*(t/this.transformCanvas.h))*this.renderConfig.dpr:0,this.transformCanvas.ty="YMid"===l&&(r>n&&"meet"===a||rn&&"meet"===a||r=0;e-=1)this.elements[e]&&this.elements[e].destroy();this.elements.length=0,this.globalData.canvasContext=null,this.animationItem.container=null,this.destroyed=!0},CanvasRendererBase.prototype.renderFrame=function(e,t){if((this.renderedFrame!==e||!0!==this.renderConfig.clearCanvas||t)&&!this.destroyed&&-1!==e){var n;this.renderedFrame=e,this.globalData.frameNum=e-this.animationItem._isFirstFrame,this.globalData.frameId+=1,this.globalData._mdf=!this.renderConfig.clearCanvas||t,this.globalData.projectInterface.currentFrame=e;var r=this.layers.length;for(this.completeLayers||this.checkLayers(e),n=0;n=0;n-=1)(this.completeLayers||this.elements[n])&&this.elements[n].renderFrame();!0!==this.renderConfig.clearCanvas&&this.restore()}}},CanvasRendererBase.prototype.buildItem=function(e){var t=this.elements;if(!t[e]&&99!==this.layers[e].ty){var n=this.createItem(this.layers[e],this,this.globalData);t[e]=n,n.initExpressions()}},CanvasRendererBase.prototype.checkPendingElements=function(){for(;this.pendingElements.length;)this.pendingElements.pop().checkParenting()},CanvasRendererBase.prototype.hide=function(){this.animationItem.container.style.display="none"},CanvasRendererBase.prototype.show=function(){this.animationItem.container.style.display="block"},extendPrototype([CanvasRendererBase,ICompElement,CVBaseElement],CVCompElement),CVCompElement.prototype.renderInnerContent=function(){var e,t=this.canvasContext;for(t.beginPath(),t.moveTo(0,0),t.lineTo(this.data.w,0),t.lineTo(this.data.w,this.data.h),t.lineTo(0,this.data.h),t.lineTo(0,0),t.clip(),e=this.layers.length-1;e>=0;e-=1)(this.completeLayers||this.elements[e])&&this.elements[e].renderFrame()},CVCompElement.prototype.destroy=function(){var e;for(e=this.layers.length-1;e>=0;e-=1)this.elements[e]&&this.elements[e].destroy();this.layers=null,this.elements=null},CVCompElement.prototype.createComp=function(e){return new CVCompElement(e,this.globalData,this)},extendPrototype([CanvasRendererBase],CanvasRenderer),CanvasRenderer.prototype.createComp=function(e){return new CVCompElement(e,this.globalData,this)},HBaseElement.prototype={checkBlendMode:function(){},initRendererElement:function(){this.baseElement=createTag(this.data.tg||"div"),this.data.hasMask?(this.svgElement=createNS("svg"),this.layerElement=createNS("g"),this.maskedElement=this.layerElement,this.svgElement.appendChild(this.layerElement),this.baseElement.appendChild(this.svgElement)):this.layerElement=this.baseElement,styleDiv(this.baseElement)},createContainerElements:function(){this.renderableEffectsManager=new CVEffects(this),this.transformedElement=this.baseElement,this.maskedElement=this.layerElement,this.data.ln&&this.layerElement.setAttribute("id",this.data.ln),this.data.cl&&this.layerElement.setAttribute("class",this.data.cl),0!==this.data.bm&&this.setBlendMode()},renderElement:function(){var e=this.transformedElement?this.transformedElement.style:{};if(this.finalTransform._matMdf){var t=this.finalTransform.mat.toCSS();e.transform=t,e.webkitTransform=t}this.finalTransform._opMdf&&(e.opacity=this.finalTransform.mProp.o.v)},renderFrame:function(){this.data.hd||this.hidden||(this.renderTransform(),this.renderRenderable(),this.renderElement(),this.renderInnerContent(),this._isFirstFrame&&(this._isFirstFrame=!1))},destroy:function(){this.layerElement=null,this.transformedElement=null,this.matteElement&&(this.matteElement=null),this.maskManager&&(this.maskManager.destroy(),this.maskManager=null)},createRenderableComponents:function(){this.maskManager=new MaskElement(this.data,this,this.globalData)},addEffects:function(){},setMatte:function(){}},HBaseElement.prototype.getBaseElement=SVGBaseElement.prototype.getBaseElement,HBaseElement.prototype.destroyBaseElement=HBaseElement.prototype.destroy,HBaseElement.prototype.buildElementParenting=BaseRenderer.prototype.buildElementParenting,extendPrototype([BaseElement,TransformElement,HBaseElement,HierarchyElement,FrameElement,RenderableDOMElement],HSolidElement),HSolidElement.prototype.createContent=function(){var e;this.data.hasMask?((e=createNS("rect")).setAttribute("width",this.data.sw),e.setAttribute("height",this.data.sh),e.setAttribute("fill",this.data.sc),this.svgElement.setAttribute("width",this.data.sw),this.svgElement.setAttribute("height",this.data.sh)):((e=createTag("div")).style.width=this.data.sw+"px",e.style.height=this.data.sh+"px",e.style.backgroundColor=this.data.sc),this.layerElement.appendChild(e)},extendPrototype([BaseElement,TransformElement,HSolidElement,SVGShapeElement,HBaseElement,HierarchyElement,FrameElement,RenderableElement],HShapeElement),HShapeElement.prototype._renderShapeFrame=HShapeElement.prototype.renderInnerContent,HShapeElement.prototype.createContent=function(){var e;if(this.baseElement.style.fontSize=0,this.data.hasMask)this.layerElement.appendChild(this.shapesContainer),e=this.svgElement;else{e=createNS("svg");var t=this.comp.data?this.comp.data:this.globalData.compSize;e.setAttribute("width",t.w),e.setAttribute("height",t.h),e.appendChild(this.shapesContainer),this.layerElement.appendChild(e)}this.searchShapes(this.shapesData,this.itemsData,this.prevViewData,this.shapesContainer,0,[],!0),this.filterUniqueShapes(),this.shapeCont=e},HShapeElement.prototype.getTransformedPoint=function(e,t){var n,r=e.length;for(n=0;n0&&s<1&&d[f].push(this.calculateF(s,e,t,n,r,f)):(l=a*a-4*o*i)>=0&&((u=(-a+bmSqrt(l))/(2*i))>0&&u<1&&d[f].push(this.calculateF(u,e,t,n,r,f)),(c=(-a-bmSqrt(l))/(2*i))>0&&c<1&&d[f].push(this.calculateF(c,e,t,n,r,f))));this.shapeBoundingBox.left=bmMin.apply(null,d[0]),this.shapeBoundingBox.top=bmMin.apply(null,d[1]),this.shapeBoundingBox.right=bmMax.apply(null,d[0]),this.shapeBoundingBox.bottom=bmMax.apply(null,d[1])},HShapeElement.prototype.calculateF=function(e,t,n,r,i,a){return bmPow(1-e,3)*t[a]+3*bmPow(1-e,2)*e*n[a]+3*(1-e)*bmPow(e,2)*r[a]+bmPow(e,3)*i[a]},HShapeElement.prototype.calculateBoundingBox=function(e,t){var n,r=e.length;for(n=0;nn&&(n=i)}n*=e.mult}else n=e.v*e.mult;t.x-=n,t.xMax+=n,t.y-=n,t.yMax+=n},HShapeElement.prototype.currentBoxContains=function(e){return this.currentBBox.x<=e.x&&this.currentBBox.y<=e.y&&this.currentBBox.width+this.currentBBox.x>=e.x+e.width&&this.currentBBox.height+this.currentBBox.y>=e.y+e.height},HShapeElement.prototype.renderInnerContent=function(){if(this._renderShapeFrame(),!this.hidden&&(this._isFirstFrame||this._mdf)){var e=this.tempBoundingBox,t=999999;if(e.x=t,e.xMax=-t,e.y=t,e.yMax=-t,this.calculateBoundingBox(this.itemsData,e),e.width=e.xMax=0;e-=1){var r=this.hierarchy[e].finalTransform.mProp;this.mat.translate(-r.p.v[0],-r.p.v[1],r.p.v[2]),this.mat.rotateX(-r.or.v[0]).rotateY(-r.or.v[1]).rotateZ(r.or.v[2]),this.mat.rotateX(-r.rx.v).rotateY(-r.ry.v).rotateZ(r.rz.v),this.mat.scale(1/r.s.v[0],1/r.s.v[1],1/r.s.v[2]),this.mat.translate(r.a.v[0],r.a.v[1],r.a.v[2])}if(this.p?this.mat.translate(-this.p.v[0],-this.p.v[1],this.p.v[2]):this.mat.translate(-this.px.v,-this.py.v,this.pz.v),this.a){var i;i=this.p?[this.p.v[0]-this.a.v[0],this.p.v[1]-this.a.v[1],this.p.v[2]-this.a.v[2]]:[this.px.v-this.a.v[0],this.py.v-this.a.v[1],this.pz.v-this.a.v[2]];var a=Math.sqrt(Math.pow(i[0],2)+Math.pow(i[1],2)+Math.pow(i[2],2)),o=[i[0]/a,i[1]/a,i[2]/a],s=Math.sqrt(o[2]*o[2]+o[0]*o[0]),l=Math.atan2(o[1],s),u=Math.atan2(o[0],-o[2]);this.mat.rotateY(u).rotateX(-l)}this.mat.rotateX(-this.rx.v).rotateY(-this.ry.v).rotateZ(this.rz.v),this.mat.rotateX(-this.or.v[0]).rotateY(-this.or.v[1]).rotateZ(this.or.v[2]),this.mat.translate(this.globalData.compSize.w/2,this.globalData.compSize.h/2,0),this.mat.translate(0,0,this.pe.v);var c=!this._prevMat.equals(this.mat);if((c||this.pe._mdf)&&this.comp.threeDElements){var d,f,h;for(t=this.comp.threeDElements.length,e=0;e=e)return this.threeDElements[t].perspectiveElem;t+=1}return null},HybridRendererBase.prototype.createThreeDContainer=function(e,t){var n,r,i=createTag("div");styleDiv(i);var a=createTag("div");if(styleDiv(a),"3d"===t){(n=i.style).width=this.globalData.compSize.w+"px",n.height=this.globalData.compSize.h+"px";var o="50% 50%";n.webkitTransformOrigin=o,n.mozTransformOrigin=o,n.transformOrigin=o;var s="matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)";(r=a.style).transform=s,r.webkitTransform=s}i.appendChild(a);var l={container:a,perspectiveElem:i,startPos:e,endPos:e,type:t};return this.threeDElements.push(l),l},HybridRendererBase.prototype.build3dContainers=function(){var e,t,n=this.layers.length,r="";for(e=0;e=0;e-=1)this.resizerElem.appendChild(this.threeDElements[e].perspectiveElem)},HybridRendererBase.prototype.addTo3dContainer=function(e,t){for(var n=0,r=this.threeDElements.length;no?(e=i/this.globalData.compSize.w,t=i/this.globalData.compSize.w,n=0,r=(a-this.globalData.compSize.h*(i/this.globalData.compSize.w))/2):(e=a/this.globalData.compSize.h,t=a/this.globalData.compSize.h,n=(i-this.globalData.compSize.w*(a/this.globalData.compSize.h))/2,r=0);var s=this.resizerElem.style;s.webkitTransform="matrix3d("+e+",0,0,0,0,"+t+",0,0,0,0,1,0,"+n+","+r+",0,1)",s.transform=s.webkitTransform},HybridRendererBase.prototype.renderFrame=SVGRenderer.prototype.renderFrame,HybridRendererBase.prototype.hide=function(){this.resizerElem.style.display="none"},HybridRendererBase.prototype.show=function(){this.resizerElem.style.display="block"},HybridRendererBase.prototype.initItems=function(){if(this.buildAllItems(),this.camera)this.camera.setup();else{var e,t=this.globalData.compSize.w,n=this.globalData.compSize.h,r=this.threeDElements.length;for(e=0;e=o;)e/=2,t/=2,n>>>=1;return(e+n)/t};return y.int32=function(){return 0|g.g(4)},y.quick=function(){return g.g(4)/4294967296},y.double=y,d(f(g.S),e),(h.pass||p||function(e,n,r,i){return i&&(i.S&&u(i,g),e.state=function(){return u(g,{})}),r?(t.random=e,n):e})(y,v,"global"in h?h.global:this==t,h.state)},d(t.random(),e)}function initialize$2(e){seedRandom([],e)}var propTypes={SHAPE:"shape"};function _typeof(e){return _typeof="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_typeof(e)}var ExpressionManager=function(){var ob={},Math=BMMath,window=null,document=null,XMLHttpRequest=null,fetch=null,frames=null;function $bm_isInstanceOfArray(e){return e.constructor===Array||e.constructor===Float32Array}function isNumerable(e,t){return"number"===e||"boolean"===e||"string"===e||t instanceof Number}function $bm_neg(e){var t=_typeof(e);if("number"===t||"boolean"===t||e instanceof Number)return-e;if($bm_isInstanceOfArray(e)){var n,r=e.length,i=[];for(n=0;nn){var r=n;n=t,t=r}return Math.min(Math.max(e,t),n)}function radiansToDegrees(e){return e/degToRads}var radians_to_degrees=radiansToDegrees;function degreesToRadians(e){return e*degToRads}var degrees_to_radians=radiansToDegrees,helperLengthArray=[0,0,0,0,0,0];function length(e,t){if("number"===typeof e||e instanceof Number)return t=t||0,Math.abs(e-t);var n;t||(t=helperLengthArray);var r=Math.min(e.length,t.length),i=0;for(n=0;n.5?u/(2-o-s):u/(o+s),o){case r:t=(i-a)/u+(i1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function hslToRgb(e){var t,n,r,i=e[0],a=e[1],o=e[2];if(0===a)t=o,r=o,n=o;else{var s=o<.5?o*(1+a):o+a-o*a,l=2*o-s;t=hue2rgb(l,s,i+1/3),n=hue2rgb(l,s,i),r=hue2rgb(l,s,i-1/3)}return[t,n,r,e[3]]}function linear(e,t,n,r,i){if(void 0!==r&&void 0!==i||(r=t,i=n,t=0,n=1),n=n)return i;var o,s=n===t?0:(e-t)/(n-t);if(!r.length)return r+(i-r)*s;var l=r.length,u=createTypedArray("float32",l);for(o=0;o1){for(r=0;r1?t=1:t<0&&(t=0);var o=e(t);if($bm_isInstanceOfArray(i)){var s,l=i.length,u=createTypedArray("float32",l);for(s=0;sdata.k[t].t&&edata.k[t+1].t-e?(n=t+2,r=data.k[t+1].t):(n=t+1,r=data.k[t].t);break}}-1===n&&(n=t+1,r=data.k[t].t)}else n=0,r=0;var a={};return a.index=n,a.time=r/elem.comp.globalData.frameRate,a}function key(e){var t,n,r;if(!data.k.length||"number"===typeof data.k[0])throw new Error("The property has no keyframe at index "+e);e-=1,t={time:data.k[e].t/elem.comp.globalData.frameRate,value:[]};var i=Object.prototype.hasOwnProperty.call(data.k[e],"s")?data.k[e].s:data.k[e-1].e;for(r=i.length,n=0;nu.length-1)&&(t=u.length-1),r=c-(i=u[u.length-1-t].t)),"pingpong"===e){if(Math.floor((l-i)/r)%2!==0)return this.getValueAtTime((r-(l-i)%r+i)/this.comp.globalData.frameRate,0)}else{if("offset"===e){var d=this.getValueAtTime(i/this.comp.globalData.frameRate,0),f=this.getValueAtTime(c/this.comp.globalData.frameRate,0),h=this.getValueAtTime(((l-i)%r+i)/this.comp.globalData.frameRate,0),p=Math.floor((l-i)/r);if(this.pv.length){for(o=(s=new Array(d.length)).length,a=0;a=c)return this.pv;if(n?i=c+(r=t?Math.abs(this.elem.comp.globalData.frameRate*t):Math.max(0,this.elem.data.op-c)):((!t||t>u.length-1)&&(t=u.length-1),r=(i=u[t].t)-c),"pingpong"===e){if(Math.floor((c-l)/r)%2===0)return this.getValueAtTime(((c-l)%r+c)/this.comp.globalData.frameRate,0)}else{if("offset"===e){var d=this.getValueAtTime(c/this.comp.globalData.frameRate,0),f=this.getValueAtTime(i/this.comp.globalData.frameRate,0),h=this.getValueAtTime((r-(c-l)%r+c)/this.comp.globalData.frameRate,0),p=Math.floor((c-l)/r)+1;if(this.pv.length){for(o=(s=new Array(d.length)).length,a=0;a1?(i+e-a)/(t-1):1,s=0,l=0;for(n=this.pv.length?createTypedArray("float32",this.pv.length):0;so){var c=s,d=n.c&&s===l-1?0:s+1,f=(o-u)/a[s].addedLength;r=bez.getPointInSegment(n.v[c],n.v[d],n.o[c],n.i[d],f,a[s]);break}u+=a[s].addedLength,s+=1}return r||(r=n.c?[n.v[0][0],n.v[0][1]]:[n.v[n._length-1][0],n.v[n._length-1][1]]),r},vectorOnPath:function(e,t,n){1==e?e=this.v.c:0==e&&(e=.999);var r=this.pointOnPath(e,t),i=this.pointOnPath(e+.001,t),a=i[0]-r[0],o=i[1]-r[1],s=Math.sqrt(Math.pow(a,2)+Math.pow(o,2));return 0===s?[0,0]:"tangent"===n?[a/s,o/s]:[-o/s,a/s]},tangentOnPath:function(e,t){return this.vectorOnPath(e,t,"tangent")},normalOnPath:function(e,t){return this.vectorOnPath(e,t,"normal")},setGroupProperty:expressionHelpers.setGroupProperty,getValueAtTime:expressionHelpers.getStaticValueAtTime},extendPrototype([u],s),extendPrototype([u],l),l.prototype.getValueAtTime=function(e){return this._cachingAtTime||(this._cachingAtTime={shapeValue:shapePool.clone(this.pv),lastIndex:0,lastTime:initialDefaultFrame}),e*=this.elem.globalData.frameRate,(e-=this.offsetTime)!==this._cachingAtTime.lastTime&&(this._cachingAtTime.lastIndex=this._cachingAtTime.lastTime=u?h<0?r:i:r+f*Math.pow((a-e)/h,1/n),c[d]=o,d+=1,s+=256/255;return c.join(" ")},SVGProLevelsFilter.prototype.renderFrame=function(e){if(e||this.filterManager._mdf){var t,n=this.filterManager.effectElements;this.feFuncRComposed&&(e||n[3].p._mdf||n[4].p._mdf||n[5].p._mdf||n[6].p._mdf||n[7].p._mdf)&&(t=this.getTableValue(n[3].p.v,n[4].p.v,n[5].p.v,n[6].p.v,n[7].p.v),this.feFuncRComposed.setAttribute("tableValues",t),this.feFuncGComposed.setAttribute("tableValues",t),this.feFuncBComposed.setAttribute("tableValues",t)),this.feFuncR&&(e||n[10].p._mdf||n[11].p._mdf||n[12].p._mdf||n[13].p._mdf||n[14].p._mdf)&&(t=this.getTableValue(n[10].p.v,n[11].p.v,n[12].p.v,n[13].p.v,n[14].p.v),this.feFuncR.setAttribute("tableValues",t)),this.feFuncG&&(e||n[17].p._mdf||n[18].p._mdf||n[19].p._mdf||n[20].p._mdf||n[21].p._mdf)&&(t=this.getTableValue(n[17].p.v,n[18].p.v,n[19].p.v,n[20].p.v,n[21].p.v),this.feFuncG.setAttribute("tableValues",t)),this.feFuncB&&(e||n[24].p._mdf||n[25].p._mdf||n[26].p._mdf||n[27].p._mdf||n[28].p._mdf)&&(t=this.getTableValue(n[24].p.v,n[25].p.v,n[26].p.v,n[27].p.v,n[28].p.v),this.feFuncB.setAttribute("tableValues",t)),this.feFuncA&&(e||n[31].p._mdf||n[32].p._mdf||n[33].p._mdf||n[34].p._mdf||n[35].p._mdf)&&(t=this.getTableValue(n[31].p.v,n[32].p.v,n[33].p.v,n[34].p.v,n[35].p.v),this.feFuncA.setAttribute("tableValues",t))}},extendPrototype([SVGComposableEffect],SVGDropShadowEffect),SVGDropShadowEffect.prototype.renderFrame=function(e){if(e||this.filterManager._mdf){if((e||this.filterManager.effectElements[4].p._mdf)&&this.feGaussianBlur.setAttribute("stdDeviation",this.filterManager.effectElements[4].p.v/4),e||this.filterManager.effectElements[0].p._mdf){var t=this.filterManager.effectElements[0].p.v;this.feFlood.setAttribute("flood-color",rgbToHex(Math.round(255*t[0]),Math.round(255*t[1]),Math.round(255*t[2])))}if((e||this.filterManager.effectElements[1].p._mdf)&&this.feFlood.setAttribute("flood-opacity",this.filterManager.effectElements[1].p.v/255),e||this.filterManager.effectElements[2].p._mdf||this.filterManager.effectElements[3].p._mdf){var n=this.filterManager.effectElements[3].p.v,r=(this.filterManager.effectElements[2].p.v-90)*degToRads,i=n*Math.cos(r),a=n*Math.sin(r);this.feOffset.setAttribute("dx",i),this.feOffset.setAttribute("dy",a)}}};var _svgMatteSymbols=[];function SVGMatte3Effect(e,t,n){this.initialized=!1,this.filterManager=t,this.filterElem=e,this.elem=n,n.matteElement=createNS("g"),n.matteElement.appendChild(n.layerElement),n.matteElement.appendChild(n.transformedElement),n.baseElement=n.matteElement}function SVGGaussianBlurEffect(e,t,n,r){e.setAttribute("x","-100%"),e.setAttribute("y","-100%"),e.setAttribute("width","300%"),e.setAttribute("height","300%"),this.filterManager=t;var i=createNS("feGaussianBlur");i.setAttribute("result",r),e.appendChild(i),this.feGaussianBlur=i}return SVGMatte3Effect.prototype.findSymbol=function(e){for(var t=0,n=_svgMatteSymbols.length;t>>0;for(t=0;t0)for(n=0;n=0?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+r}var R=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,j=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,L={},F={};function B(e,t,n,r){var i=r;"string"===typeof r&&(i=function(){return this[r]()}),e&&(F[e]=i),t&&(F[t[0]]=function(){return M(i.apply(this,arguments),t[1],t[2])}),n&&(F[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function V(e){return e.match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"")}function U(e){var t,n,r=e.match(R);for(t=0,n=r.length;t=0&&j.test(e);)e=e.replace(j,r),j.lastIndex=0,n-=1;return e}var H={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function Y(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.match(R).map((function(e){return"MMMM"===e||"MM"===e||"DD"===e||"dddd"===e?e.slice(1):e})).join(""),this._longDateFormat[e])}var W="Invalid date";function K(){return this._invalidDate}var q="%d",Q=/\d{1,2}/;function X(e){return this._ordinal.replace("%d",e)}var J={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function Z(e,t,n,r){var i=this._relativeTime[n];return T(i)?i(e,t,n,r):i.replace(/%d/i,e)}function ee(e,t){var n=this._relativeTime[e>0?"future":"past"];return T(n)?n(t):n.replace(/%s/i,t)}var te={};function ne(e,t){var n=e.toLowerCase();te[n]=te[n+"s"]=te[t]=e}function re(e){return"string"===typeof e?te[e]||te[e.toLowerCase()]:void 0}function ie(e){var t,n,r={};for(n in e)s(e,n)&&(t=re(n))&&(r[t]=e[n]);return r}var ae={};function oe(e,t){ae[e]=t}function se(e){var t,n=[];for(t in e)s(e,t)&&n.push({unit:t,priority:ae[t]});return n.sort((function(e,t){return e.priority-t.priority})),n}function le(e){return e%4===0&&e%100!==0||e%400===0}function ue(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function ce(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=ue(t)),n}function de(e,t){return function(n){return null!=n?(he(this,e,n),r.updateOffset(this,t),this):fe(this,e)}}function fe(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function he(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&le(e.year())&&1===e.month()&&29===e.date()?(n=ce(n),e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),Ze(n,e.month()))):e._d["set"+(e._isUTC?"UTC":"")+t](n))}function pe(e){return T(this[e=re(e)])?this[e]():this}function me(e,t){if("object"===typeof e){var n,r=se(e=ie(e)),i=r.length;for(n=0;n68?1900:2e3)};var vt=de("FullYear",!0);function gt(){return le(this.year())}function yt(e,t,n,r,i,a,o){var s;return e<100&&e>=0?(s=new Date(e+400,t,n,r,i,a,o),isFinite(s.getFullYear())&&s.setFullYear(e)):s=new Date(e,t,n,r,i,a,o),s}function bt(e){var t,n;return e<100&&e>=0?((n=Array.prototype.slice.call(arguments))[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)):t=new Date(Date.UTC.apply(null,arguments)),t}function _t(e,t,n){var r=7+t-n;return-(7+bt(e,0,r).getUTCDay()-t)%7+r-1}function xt(e,t,n,r,i){var a,o,s=1+7*(t-1)+(7+n-r)%7+_t(e,r,i);return s<=0?o=mt(a=e-1)+s:s>mt(e)?(a=e+1,o=s-mt(e)):(a=e,o=s),{year:a,dayOfYear:o}}function wt(e,t,n){var r,i,a=_t(e.year(),t,n),o=Math.floor((e.dayOfYear()-a-1)/7)+1;return o<1?r=o+At(i=e.year()-1,t,n):o>At(e.year(),t,n)?(r=o-At(e.year(),t,n),i=e.year()+1):(i=e.year(),r=o),{week:r,year:i}}function At(e,t,n){var r=_t(e,t,n),i=_t(e+1,t,n);return(mt(e)-r+i)/7}function kt(e){return wt(e,this._week.dow,this._week.doy).week}B("w",["ww",2],"wo","week"),B("W",["WW",2],"Wo","isoWeek"),ne("week","w"),ne("isoWeek","W"),oe("week",5),oe("isoWeek",5),De("w",we),De("ww",we,ye),De("W",we),De("WW",we,ye),Be(["w","ww","W","WW"],(function(e,t,n,r){t[r.substr(0,1)]=ce(e)}));var Et={dow:0,doy:6};function St(){return this._week.dow}function Pt(){return this._week.doy}function Ct(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")}function Tt(e){var t=wt(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")}function Ot(e,t){return"string"!==typeof e?e:isNaN(e)?"number"===typeof(e=t.weekdaysParse(e))?e:null:parseInt(e,10)}function $t(e,t){return"string"===typeof e?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}function It(e,t){return e.slice(t,7).concat(e.slice(0,t))}B("d",0,"do","day"),B("dd",0,0,(function(e){return this.localeData().weekdaysMin(this,e)})),B("ddd",0,0,(function(e){return this.localeData().weekdaysShort(this,e)})),B("dddd",0,0,(function(e){return this.localeData().weekdays(this,e)})),B("e",0,0,"weekday"),B("E",0,0,"isoWeekday"),ne("day","d"),ne("weekday","e"),ne("isoWeekday","E"),oe("day",11),oe("weekday",11),oe("isoWeekday",11),De("d",we),De("e",we),De("E",we),De("dd",(function(e,t){return t.weekdaysMinRegex(e)})),De("ddd",(function(e,t){return t.weekdaysShortRegex(e)})),De("dddd",(function(e,t){return t.weekdaysRegex(e)})),Be(["dd","ddd","dddd"],(function(e,t,n,r){var i=n._locale.weekdaysParse(e,r,n._strict);null!=i?t.d=i:v(n).invalidWeekday=e})),Be(["d","e","E"],(function(e,t,n,r){t[r]=ce(e)}));var Nt="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Dt="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Mt="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Rt=Ne,jt=Ne,Lt=Ne;function Ft(e,t){var n=a(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?It(n,this._week.dow):e?n[e.day()]:n}function Bt(e){return!0===e?It(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort}function Vt(e){return!0===e?It(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin}function Ut(e,t,n){var r,i,a,o=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],r=0;r<7;++r)a=p([2e3,1]).day(r),this._minWeekdaysParse[r]=this.weekdaysMin(a,"").toLocaleLowerCase(),this._shortWeekdaysParse[r]=this.weekdaysShort(a,"").toLocaleLowerCase(),this._weekdaysParse[r]=this.weekdays(a,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=Ue.call(this._weekdaysParse,o))?i:null:"ddd"===t?-1!==(i=Ue.call(this._shortWeekdaysParse,o))?i:null:-1!==(i=Ue.call(this._minWeekdaysParse,o))?i:null:"dddd"===t?-1!==(i=Ue.call(this._weekdaysParse,o))||-1!==(i=Ue.call(this._shortWeekdaysParse,o))||-1!==(i=Ue.call(this._minWeekdaysParse,o))?i:null:"ddd"===t?-1!==(i=Ue.call(this._shortWeekdaysParse,o))||-1!==(i=Ue.call(this._weekdaysParse,o))||-1!==(i=Ue.call(this._minWeekdaysParse,o))?i:null:-1!==(i=Ue.call(this._minWeekdaysParse,o))||-1!==(i=Ue.call(this._weekdaysParse,o))||-1!==(i=Ue.call(this._shortWeekdaysParse,o))?i:null}function zt(e,t,n){var r,i,a;if(this._weekdaysParseExact)return Ut.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),r=0;r<7;r++){if(i=p([2e3,1]).day(r),n&&!this._fullWeekdaysParse[r]&&(this._fullWeekdaysParse[r]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[r]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[r]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[r]||(a="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[r]=new RegExp(a.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[r].test(e))return r;if(n&&"ddd"===t&&this._shortWeekdaysParse[r].test(e))return r;if(n&&"dd"===t&&this._minWeekdaysParse[r].test(e))return r;if(!n&&this._weekdaysParse[r].test(e))return r}}function Gt(e){if(!this.isValid())return null!=e?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(e=Ot(e,this.localeData()),this.add(e-t,"d")):t}function Ht(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")}function Yt(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=$t(e,this.localeData());return this.day(this.day()%7?t:t-7)}return this.day()||7}function Wt(e){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||Qt.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(s(this,"_weekdaysRegex")||(this._weekdaysRegex=Rt),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)}function Kt(e){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||Qt.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(s(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=jt),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function qt(e){return this._weekdaysParseExact?(s(this,"_weekdaysRegex")||Qt.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(s(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Lt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Qt(){function e(e,t){return t.length-e.length}var t,n,r,i,a,o=[],s=[],l=[],u=[];for(t=0;t<7;t++)n=p([2e3,1]).day(t),r=je(this.weekdaysMin(n,"")),i=je(this.weekdaysShort(n,"")),a=je(this.weekdays(n,"")),o.push(r),s.push(i),l.push(a),u.push(r),u.push(i),u.push(a);o.sort(e),s.sort(e),l.sort(e),u.sort(e),this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function Xt(){return this.hours()%12||12}function Jt(){return this.hours()||24}function Zt(e,t){B(e,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)}))}function en(e,t){return t._meridiemParse}function tn(e){return"p"===(e+"").toLowerCase().charAt(0)}B("H",["HH",2],0,"hour"),B("h",["hh",2],0,Xt),B("k",["kk",2],0,Jt),B("hmm",0,0,(function(){return""+Xt.apply(this)+M(this.minutes(),2)})),B("hmmss",0,0,(function(){return""+Xt.apply(this)+M(this.minutes(),2)+M(this.seconds(),2)})),B("Hmm",0,0,(function(){return""+this.hours()+M(this.minutes(),2)})),B("Hmmss",0,0,(function(){return""+this.hours()+M(this.minutes(),2)+M(this.seconds(),2)})),Zt("a",!0),Zt("A",!1),ne("hour","h"),oe("hour",13),De("a",en),De("A",en),De("H",we),De("h",we),De("k",we),De("HH",we,ye),De("hh",we,ye),De("kk",we,ye),De("hmm",Ae),De("hmmss",ke),De("Hmm",Ae),De("Hmmss",ke),Fe(["H","HH"],Ye),Fe(["k","kk"],(function(e,t,n){var r=ce(e);t[Ye]=24===r?0:r})),Fe(["a","A"],(function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e})),Fe(["h","hh"],(function(e,t,n){t[Ye]=ce(e),v(n).bigHour=!0})),Fe("hmm",(function(e,t,n){var r=e.length-2;t[Ye]=ce(e.substr(0,r)),t[We]=ce(e.substr(r)),v(n).bigHour=!0})),Fe("hmmss",(function(e,t,n){var r=e.length-4,i=e.length-2;t[Ye]=ce(e.substr(0,r)),t[We]=ce(e.substr(r,2)),t[Ke]=ce(e.substr(i)),v(n).bigHour=!0})),Fe("Hmm",(function(e,t,n){var r=e.length-2;t[Ye]=ce(e.substr(0,r)),t[We]=ce(e.substr(r))})),Fe("Hmmss",(function(e,t,n){var r=e.length-4,i=e.length-2;t[Ye]=ce(e.substr(0,r)),t[We]=ce(e.substr(r,2)),t[Ke]=ce(e.substr(i))}));var nn=/[ap]\.?m?\.?/i,rn=de("Hours",!0);function an(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"}var on,sn={calendar:N,longDateFormat:H,invalidDate:W,ordinal:q,dayOfMonthOrdinalParse:Q,relativeTime:J,months:et,monthsShort:tt,week:Et,weekdays:Nt,weekdaysMin:Mt,weekdaysShort:Dt,meridiemParse:nn},ln={},un={};function cn(e,t){var n,r=Math.min(e.length,t.length);for(n=0;n0;){if(r=pn(i.slice(0,t).join("-")))return r;if(n&&n.length>=t&&cn(i,n)>=t-1)break;t--}a++}return on}function hn(e){return null!=e.match("^[^/\\\\]*$")}function pn(t){var n=null;if(void 0===ln[t]&&e&&e.exports&&hn(t))try{n=on._abbr,Object(function(){var e=new Error("Cannot find module 'undefined'");throw e.code="MODULE_NOT_FOUND",e}()),mn(n)}catch(r){ln[t]=null}return ln[t]}function mn(e,t){var n;return e&&((n=u(t)?yn(e):vn(e,t))?on=n:"undefined"!==typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),on._abbr}function vn(e,t){if(null!==t){var n,r=sn;if(t.abbr=e,null!=ln[e])C("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),r=ln[e]._config;else if(null!=t.parentLocale)if(null!=ln[t.parentLocale])r=ln[t.parentLocale]._config;else{if(null==(n=pn(t.parentLocale)))return un[t.parentLocale]||(un[t.parentLocale]=[]),un[t.parentLocale].push({name:e,config:t}),null;r=n._config}return ln[e]=new I($(r,t)),un[e]&&un[e].forEach((function(e){vn(e.name,e.config)})),mn(e),ln[e]}return delete ln[e],null}function gn(e,t){if(null!=t){var n,r,i=sn;null!=ln[e]&&null!=ln[e].parentLocale?ln[e].set($(ln[e]._config,t)):(null!=(r=pn(e))&&(i=r._config),t=$(i,t),null==r&&(t.abbr=e),(n=new I(t)).parentLocale=ln[e],ln[e]=n),mn(e)}else null!=ln[e]&&(null!=ln[e].parentLocale?(ln[e]=ln[e].parentLocale,e===mn()&&mn(e)):null!=ln[e]&&delete ln[e]);return ln[e]}function yn(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return on;if(!a(e)){if(t=pn(e))return t;e=[e]}return fn(e)}function bn(){return S(ln)}function _n(e){var t,n=e._a;return n&&-2===v(e).overflow&&(t=n[Ge]<0||n[Ge]>11?Ge:n[He]<1||n[He]>Ze(n[ze],n[Ge])?He:n[Ye]<0||n[Ye]>24||24===n[Ye]&&(0!==n[We]||0!==n[Ke]||0!==n[qe])?Ye:n[We]<0||n[We]>59?We:n[Ke]<0||n[Ke]>59?Ke:n[qe]<0||n[qe]>999?qe:-1,v(e)._overflowDayOfYear&&(tHe)&&(t=He),v(e)._overflowWeeks&&-1===t&&(t=Qe),v(e)._overflowWeekday&&-1===t&&(t=Xe),v(e).overflow=t),e}var xn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,wn=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,An=/Z|[+-]\d\d(?::?\d\d)?/,kn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],En=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Sn=/^\/?Date\((-?\d+)/i,Pn=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Cn={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function Tn(e){var t,n,r,i,a,o,s=e._i,l=xn.exec(s)||wn.exec(s),u=kn.length,c=En.length;if(l){for(v(e).iso=!0,t=0,n=u;tmt(a)||0===e._dayOfYear)&&(v(e)._overflowDayOfYear=!0),n=bt(a,0,e._dayOfYear),e._a[Ge]=n.getUTCMonth(),e._a[He]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=o[t]=r[t];for(;t<7;t++)e._a[t]=o[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[Ye]&&0===e._a[We]&&0===e._a[Ke]&&0===e._a[qe]&&(e._nextDay=!0,e._a[Ye]=0),e._d=(e._useUTC?bt:yt).apply(null,o),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Ye]=24),e._w&&"undefined"!==typeof e._w.d&&e._w.d!==i&&(v(e).weekdayMismatch=!0)}}function Bn(e){var t,n,r,i,a,o,s,l,u;null!=(t=e._w).GG||null!=t.W||null!=t.E?(a=1,o=4,n=jn(t.GG,e._a[ze],wt(qn(),1,4).year),r=jn(t.W,1),((i=jn(t.E,1))<1||i>7)&&(l=!0)):(a=e._locale._week.dow,o=e._locale._week.doy,u=wt(qn(),a,o),n=jn(t.gg,e._a[ze],u.year),r=jn(t.w,u.week),null!=t.d?((i=t.d)<0||i>6)&&(l=!0):null!=t.e?(i=t.e+a,(t.e<0||t.e>6)&&(l=!0)):i=a),r<1||r>At(n,a,o)?v(e)._overflowWeeks=!0:null!=l?v(e)._overflowWeekday=!0:(s=xt(n,r,i,a,o),e._a[ze]=s.year,e._dayOfYear=s.dayOfYear)}function Vn(e){if(e._f!==r.ISO_8601)if(e._f!==r.RFC_2822){e._a=[],v(e).empty=!0;var t,n,i,a,o,s,l,u=""+e._i,c=u.length,d=0;for(l=(i=G(e._f,e._locale).match(R)||[]).length,t=0;t0&&v(e).unusedInput.push(o),u=u.slice(u.indexOf(n)+n.length),d+=n.length),F[a]?(n?v(e).empty=!1:v(e).unusedTokens.push(a),Ve(a,n,e)):e._strict&&!n&&v(e).unusedTokens.push(a);v(e).charsLeftOver=c-d,u.length>0&&v(e).unusedInput.push(u),e._a[Ye]<=12&&!0===v(e).bigHour&&e._a[Ye]>0&&(v(e).bigHour=void 0),v(e).parsedDateParts=e._a.slice(0),v(e).meridiem=e._meridiem,e._a[Ye]=Un(e._locale,e._a[Ye],e._meridiem),null!==(s=v(e).era)&&(e._a[ze]=e._locale.erasConvertYear(s,e._a[ze])),Fn(e),_n(e)}else Mn(e);else Tn(e)}function Un(e,t,n){var r;return null==n?t:null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((r=e.isPM(n))&&t<12&&(t+=12),r||12!==t||(t=0),t):t}function zn(e){var t,n,r,i,a,o,s=!1,l=e._f.length;if(0===l)return v(e).invalidFormat=!0,void(e._d=new Date(NaN));for(i=0;ithis?this:e:y()}));function Jn(e,t){var n,r;if(1===t.length&&a(t[0])&&(t=t[0]),!t.length)return qn();for(n=t[0],r=1;rthis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function wr(){if(!u(this._isDSTShifted))return this._isDSTShifted;var e,t={};return x(t,this),(t=Yn(t))._a?(e=t._isUTC?p(t._a):qn(t._a),this._isDSTShifted=this.isValid()&&ur(t._a,e.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}function Ar(){return!!this.isValid()&&!this._isUTC}function kr(){return!!this.isValid()&&this._isUTC}function Er(){return!!this.isValid()&&this._isUTC&&0===this._offset}r.updateOffset=function(){};var Sr=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Pr=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Cr(e,t){var n,r,i,a=e,o=null;return sr(e)?a={ms:e._milliseconds,d:e._days,M:e._months}:c(e)||!isNaN(+e)?(a={},t?a[t]=+e:a.milliseconds=+e):(o=Sr.exec(e))?(n="-"===o[1]?-1:1,a={y:0,d:ce(o[He])*n,h:ce(o[Ye])*n,m:ce(o[We])*n,s:ce(o[Ke])*n,ms:ce(lr(1e3*o[qe]))*n}):(o=Pr.exec(e))?(n="-"===o[1]?-1:1,a={y:Tr(o[2],n),M:Tr(o[3],n),w:Tr(o[4],n),d:Tr(o[5],n),h:Tr(o[6],n),m:Tr(o[7],n),s:Tr(o[8],n)}):null==a?a={}:"object"===typeof a&&("from"in a||"to"in a)&&(i=$r(qn(a.from),qn(a.to)),(a={}).ms=i.milliseconds,a.M=i.months),r=new or(a),sr(e)&&s(e,"_locale")&&(r._locale=e._locale),sr(e)&&s(e,"_isValid")&&(r._isValid=e._isValid),r}function Tr(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function Or(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $r(e,t){var n;return e.isValid()&&t.isValid()?(t=hr(t,e),e.isBefore(t)?n=Or(e,t):((n=Or(t,e)).milliseconds=-n.milliseconds,n.months=-n.months),n):{milliseconds:0,months:0}}function Ir(e,t){return function(n,r){var i;return null===r||isNaN(+r)||(C(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),i=n,n=r,r=i),Nr(this,Cr(n,r),e),this}}function Nr(e,t,n,i){var a=t._milliseconds,o=lr(t._days),s=lr(t._months);e.isValid()&&(i=null==i||i,s&&ut(e,fe(e,"Month")+s*n),o&&he(e,"Date",fe(e,"Date")+o*n),a&&e._d.setTime(e._d.valueOf()+a*n),i&&r.updateOffset(e,o||s))}Cr.fn=or.prototype,Cr.invalid=ar;var Dr=Ir(1,"add"),Mr=Ir(-1,"subtract");function Rr(e){return"string"===typeof e||e instanceof String}function jr(e){return A(e)||d(e)||Rr(e)||c(e)||Fr(e)||Lr(e)||null===e||void 0===e}function Lr(e){var t,n,r=o(e)&&!l(e),i=!1,a=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],u=a.length;for(t=0;tn.valueOf():n.valueOf()9999?z(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):T(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",z(n,"Z")):z(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")}function ei(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e,t,n,r,i="moment",a="";return this.isLocal()||(i=0===this.utcOffset()?"moment.utc":"moment.parseZone",a="Z"),e="["+i+'("]',t=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",n="-MM-DD[T]HH:mm:ss.SSS",r=a+'[")]',this.format(e+t+n+r)}function ti(e){e||(e=this.isUtc()?r.defaultFormatUtc:r.defaultFormat);var t=z(this,e);return this.localeData().postformat(t)}function ni(e,t){return this.isValid()&&(A(e)&&e.isValid()||qn(e).isValid())?Cr({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function ri(e){return this.from(qn(),e)}function ii(e,t){return this.isValid()&&(A(e)&&e.isValid()||qn(e).isValid())?Cr({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()}function ai(e){return this.to(qn(),e)}function oi(e){var t;return void 0===e?this._locale._abbr:(null!=(t=yn(e))&&(this._locale=t),this)}r.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",r.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var si=E("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(e){return void 0===e?this.localeData():this.locale(e)}));function li(){return this._locale}var ui=1e3,ci=60*ui,di=60*ci,fi=3506328*di;function hi(e,t){return(e%t+t)%t}function pi(e,t,n){return e<100&&e>=0?new Date(e+400,t,n)-fi:new Date(e,t,n).valueOf()}function mi(e,t,n){return e<100&&e>=0?Date.UTC(e+400,t,n)-fi:Date.UTC(e,t,n)}function vi(e){var t,n;if(void 0===(e=re(e))||"millisecond"===e||!this.isValid())return this;switch(n=this._isUTC?mi:pi,e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=hi(t+(this._isUTC?0:this.utcOffset()*ci),di);break;case"minute":t=this._d.valueOf(),t-=hi(t,ci);break;case"second":t=this._d.valueOf(),t-=hi(t,ui)}return this._d.setTime(t),r.updateOffset(this,!0),this}function gi(e){var t,n;if(void 0===(e=re(e))||"millisecond"===e||!this.isValid())return this;switch(n=this._isUTC?mi:pi,e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=di-hi(t+(this._isUTC?0:this.utcOffset()*ci),di)-1;break;case"minute":t=this._d.valueOf(),t+=ci-hi(t,ci)-1;break;case"second":t=this._d.valueOf(),t+=ui-hi(t,ui)-1}return this._d.setTime(t),r.updateOffset(this,!0),this}function yi(){return this._d.valueOf()-6e4*(this._offset||0)}function bi(){return Math.floor(this.valueOf()/1e3)}function _i(){return new Date(this.valueOf())}function xi(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]}function wi(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}}function Ai(){return this.isValid()?this.toISOString():null}function ki(){return g(this)}function Ei(){return h({},v(this))}function Si(){return v(this).overflow}function Pi(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function Ci(e,t){var n,i,a,o=this._eras||yn("en")._eras;for(n=0,i=o.length;n=0)return l[r]}function Oi(e,t){var n=e.since<=e.until?1:-1;return void 0===t?r(e.since).year():r(e.since).year()+(t-e.offset)*n}function $i(){var e,t,n,r=this.localeData().eras();for(e=0,t=r.length;e(a=At(e,r,i))&&(t=a),Xi.call(this,e,t,n,r,i))}function Xi(e,t,n,r,i){var a=xt(e,t,n,r,i),o=bt(a.year,0,a.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function Ji(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)}B("N",0,0,"eraAbbr"),B("NN",0,0,"eraAbbr"),B("NNN",0,0,"eraAbbr"),B("NNNN",0,0,"eraName"),B("NNNNN",0,0,"eraNarrow"),B("y",["y",1],"yo","eraYear"),B("y",["yy",2],0,"eraYear"),B("y",["yyy",3],0,"eraYear"),B("y",["yyyy",4],0,"eraYear"),De("N",Li),De("NN",Li),De("NNN",Li),De("NNNN",Fi),De("NNNNN",Bi),Fe(["N","NN","NNN","NNNN","NNNNN"],(function(e,t,n,r){var i=n._locale.erasParse(e,r,n._strict);i?v(n).era=i:v(n).invalidEra=e})),De("y",Ce),De("yy",Ce),De("yyy",Ce),De("yyyy",Ce),De("yo",Vi),Fe(["y","yy","yyy","yyyy"],ze),Fe(["yo"],(function(e,t,n,r){var i;n._locale._eraYearOrdinalRegex&&(i=e.match(n._locale._eraYearOrdinalRegex)),n._locale.eraYearOrdinalParse?t[ze]=n._locale.eraYearOrdinalParse(e,i):t[ze]=parseInt(e,10)})),B(0,["gg",2],0,(function(){return this.weekYear()%100})),B(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),zi("gggg","weekYear"),zi("ggggg","weekYear"),zi("GGGG","isoWeekYear"),zi("GGGGG","isoWeekYear"),ne("weekYear","gg"),ne("isoWeekYear","GG"),oe("weekYear",1),oe("isoWeekYear",1),De("G",Te),De("g",Te),De("GG",we,ye),De("gg",we,ye),De("GGGG",Se,_e),De("gggg",Se,_e),De("GGGGG",Pe,xe),De("ggggg",Pe,xe),Be(["gggg","ggggg","GGGG","GGGGG"],(function(e,t,n,r){t[r.substr(0,2)]=ce(e)})),Be(["gg","GG"],(function(e,t,n,i){t[i]=r.parseTwoDigitYear(e)})),B("Q",0,"Qo","quarter"),ne("quarter","Q"),oe("quarter",7),De("Q",ge),Fe("Q",(function(e,t){t[Ge]=3*(ce(e)-1)})),B("D",["DD",2],"Do","date"),ne("date","D"),oe("date",9),De("D",we),De("DD",we,ye),De("Do",(function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient})),Fe(["D","DD"],He),Fe("Do",(function(e,t){t[He]=ce(e.match(we)[0])}));var Zi=de("Date",!0);function ea(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")}B("DDD",["DDDD",3],"DDDo","dayOfYear"),ne("dayOfYear","DDD"),oe("dayOfYear",4),De("DDD",Ee),De("DDDD",be),Fe(["DDD","DDDD"],(function(e,t,n){n._dayOfYear=ce(e)})),B("m",["mm",2],0,"minute"),ne("minute","m"),oe("minute",14),De("m",we),De("mm",we,ye),Fe(["m","mm"],We);var ta=de("Minutes",!1);B("s",["ss",2],0,"second"),ne("second","s"),oe("second",15),De("s",we),De("ss",we,ye),Fe(["s","ss"],Ke);var na,ra,ia=de("Seconds",!1);for(B("S",0,0,(function(){return~~(this.millisecond()/100)})),B(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),B(0,["SSS",3],0,"millisecond"),B(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),B(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),B(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),B(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),B(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),B(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),ne("millisecond","ms"),oe("millisecond",16),De("S",Ee,ge),De("SS",Ee,ye),De("SSS",Ee,be),na="SSSS";na.length<=9;na+="S")De(na,Ce);function aa(e,t){t[qe]=ce(1e3*("0."+e))}for(na="S";na.length<=9;na+="S")Fe(na,aa);function oa(){return this._isUTC?"UTC":""}function sa(){return this._isUTC?"Coordinated Universal Time":""}ra=de("Milliseconds",!1),B("z",0,0,"zoneAbbr"),B("zz",0,0,"zoneName");var la=w.prototype;function ua(e){return qn(1e3*e)}function ca(){return qn.apply(null,arguments).parseZone()}function da(e){return e}la.add=Dr,la.calendar=Ur,la.clone=zr,la.diff=Qr,la.endOf=gi,la.format=ti,la.from=ni,la.fromNow=ri,la.to=ii,la.toNow=ai,la.get=pe,la.invalidAt=Si,la.isAfter=Gr,la.isBefore=Hr,la.isBetween=Yr,la.isSame=Wr,la.isSameOrAfter=Kr,la.isSameOrBefore=qr,la.isValid=ki,la.lang=si,la.locale=oi,la.localeData=li,la.max=Xn,la.min=Qn,la.parsingFlags=Ei,la.set=me,la.startOf=vi,la.subtract=Mr,la.toArray=xi,la.toObject=wi,la.toDate=_i,la.toISOString=Zr,la.inspect=ei,"undefined"!==typeof Symbol&&null!=Symbol.for&&(la[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),la.toJSON=Ai,la.toString=Jr,la.unix=bi,la.valueOf=yi,la.creationData=Pi,la.eraName=$i,la.eraNarrow=Ii,la.eraAbbr=Ni,la.eraYear=Di,la.year=vt,la.isLeapYear=gt,la.weekYear=Gi,la.isoWeekYear=Hi,la.quarter=la.quarters=Ji,la.month=ct,la.daysInMonth=dt,la.week=la.weeks=Ct,la.isoWeek=la.isoWeeks=Tt,la.weeksInYear=Ki,la.weeksInWeekYear=qi,la.isoWeeksInYear=Yi,la.isoWeeksInISOWeekYear=Wi,la.date=Zi,la.day=la.days=Gt,la.weekday=Ht,la.isoWeekday=Yt,la.dayOfYear=ea,la.hour=la.hours=rn,la.minute=la.minutes=ta,la.second=la.seconds=ia,la.millisecond=la.milliseconds=ra,la.utcOffset=mr,la.utc=gr,la.local=yr,la.parseZone=br,la.hasAlignedHourOffset=_r,la.isDST=xr,la.isLocal=Ar,la.isUtcOffset=kr,la.isUtc=Er,la.isUTC=Er,la.zoneAbbr=oa,la.zoneName=sa,la.dates=E("dates accessor is deprecated. Use date instead.",Zi),la.months=E("months accessor is deprecated. Use month instead",ct),la.years=E("years accessor is deprecated. Use year instead",vt),la.zone=E("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",vr),la.isDSTShifted=E("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",wr);var fa=I.prototype;function ha(e,t,n,r){var i=yn(),a=p().set(r,t);return i[n](a,e)}function pa(e,t,n){if(c(e)&&(t=e,e=void 0),e=e||"",null!=t)return ha(e,t,n,"month");var r,i=[];for(r=0;r<12;r++)i[r]=ha(e,r,n,"month");return i}function ma(e,t,n,r){"boolean"===typeof e?(c(t)&&(n=t,t=void 0),t=t||""):(n=t=e,e=!1,c(t)&&(n=t,t=void 0),t=t||"");var i,a=yn(),o=e?a._week.dow:0,s=[];if(null!=n)return ha(t,(n+o)%7,r,"day");for(i=0;i<7;i++)s[i]=ha(t,(i+o)%7,r,"day");return s}function va(e,t){return pa(e,t,"months")}function ga(e,t){return pa(e,t,"monthsShort")}function ya(e,t,n){return ma(e,t,n,"weekdays")}function ba(e,t,n){return ma(e,t,n,"weekdaysShort")}function _a(e,t,n){return ma(e,t,n,"weekdaysMin")}fa.calendar=D,fa.longDateFormat=Y,fa.invalidDate=K,fa.ordinal=X,fa.preparse=da,fa.postformat=da,fa.relativeTime=Z,fa.pastFuture=ee,fa.set=O,fa.eras=Ci,fa.erasParse=Ti,fa.erasConvertYear=Oi,fa.erasAbbrRegex=Ri,fa.erasNameRegex=Mi,fa.erasNarrowRegex=ji,fa.months=at,fa.monthsShort=ot,fa.monthsParse=lt,fa.monthsRegex=ht,fa.monthsShortRegex=ft,fa.week=kt,fa.firstDayOfYear=Pt,fa.firstDayOfWeek=St,fa.weekdays=Ft,fa.weekdaysMin=Vt,fa.weekdaysShort=Bt,fa.weekdaysParse=zt,fa.weekdaysRegex=Wt,fa.weekdaysShortRegex=Kt,fa.weekdaysMinRegex=qt,fa.isPM=tn,fa.meridiem=an,mn("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===ce(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),r.lang=E("moment.lang is deprecated. Use moment.locale instead.",mn),r.langData=E("moment.langData is deprecated. Use moment.localeData instead.",yn);var xa=Math.abs;function wa(){var e=this._data;return this._milliseconds=xa(this._milliseconds),this._days=xa(this._days),this._months=xa(this._months),e.milliseconds=xa(e.milliseconds),e.seconds=xa(e.seconds),e.minutes=xa(e.minutes),e.hours=xa(e.hours),e.months=xa(e.months),e.years=xa(e.years),this}function Aa(e,t,n,r){var i=Cr(t,n);return e._milliseconds+=r*i._milliseconds,e._days+=r*i._days,e._months+=r*i._months,e._bubble()}function ka(e,t){return Aa(this,e,t,1)}function Ea(e,t){return Aa(this,e,t,-1)}function Sa(e){return e<0?Math.floor(e):Math.ceil(e)}function Pa(){var e,t,n,r,i,a=this._milliseconds,o=this._days,s=this._months,l=this._data;return a>=0&&o>=0&&s>=0||a<=0&&o<=0&&s<=0||(a+=864e5*Sa(Ta(s)+o),o=0,s=0),l.milliseconds=a%1e3,e=ue(a/1e3),l.seconds=e%60,t=ue(e/60),l.minutes=t%60,n=ue(t/60),l.hours=n%24,o+=ue(n/24),s+=i=ue(Ca(o)),o-=Sa(Ta(i)),r=ue(s/12),s%=12,l.days=o,l.months=s,l.years=r,this}function Ca(e){return 4800*e/146097}function Ta(e){return 146097*e/4800}function Oa(e){if(!this.isValid())return NaN;var t,n,r=this._milliseconds;if("month"===(e=re(e))||"quarter"===e||"year"===e)switch(t=this._days+r/864e5,n=this._months+Ca(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Ta(this._months)),e){case"week":return t/7+r/6048e5;case"day":return t+r/864e5;case"hour":return 24*t+r/36e5;case"minute":return 1440*t+r/6e4;case"second":return 86400*t+r/1e3;case"millisecond":return Math.floor(864e5*t)+r;default:throw new Error("Unknown unit "+e)}}function $a(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*ce(this._months/12):NaN}function Ia(e){return function(){return this.as(e)}}var Na=Ia("ms"),Da=Ia("s"),Ma=Ia("m"),Ra=Ia("h"),ja=Ia("d"),La=Ia("w"),Fa=Ia("M"),Ba=Ia("Q"),Va=Ia("y");function Ua(){return Cr(this)}function za(e){return e=re(e),this.isValid()?this[e+"s"]():NaN}function Ga(e){return function(){return this.isValid()?this._data[e]:NaN}}var Ha=Ga("milliseconds"),Ya=Ga("seconds"),Wa=Ga("minutes"),Ka=Ga("hours"),qa=Ga("days"),Qa=Ga("months"),Xa=Ga("years");function Ja(){return ue(this.days()/7)}var Za=Math.round,eo={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function to(e,t,n,r,i){return i.relativeTime(t||1,!!n,e,r)}function no(e,t,n,r){var i=Cr(e).abs(),a=Za(i.as("s")),o=Za(i.as("m")),s=Za(i.as("h")),l=Za(i.as("d")),u=Za(i.as("M")),c=Za(i.as("w")),d=Za(i.as("y")),f=a<=n.ss&&["s",a]||a0,f[4]=r,to.apply(null,f)}function ro(e){return void 0===e?Za:"function"===typeof e&&(Za=e,!0)}function io(e,t){return void 0!==eo[e]&&(void 0===t?eo[e]:(eo[e]=t,"s"===e&&(eo.ss=t-1),!0))}function ao(e,t){if(!this.isValid())return this.localeData().invalidDate();var n,r,i=!1,a=eo;return"object"===typeof e&&(t=e,e=!1),"boolean"===typeof e&&(i=e),"object"===typeof t&&(a=Object.assign({},eo,t),null!=t.s&&null==t.ss&&(a.ss=t.s-1)),r=no(this,!i,a,n=this.localeData()),i&&(r=n.pastFuture(+this,r)),n.postformat(r)}var oo=Math.abs;function so(e){return(e>0)-(e<0)||+e}function lo(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n,r,i,a,o,s,l=oo(this._milliseconds)/1e3,u=oo(this._days),c=oo(this._months),d=this.asSeconds();return d?(e=ue(l/60),t=ue(e/60),l%=60,e%=60,n=ue(c/12),c%=12,r=l?l.toFixed(3).replace(/\.?0+$/,""):"",i=d<0?"-":"",a=so(this._months)!==so(d)?"-":"",o=so(this._days)!==so(d)?"-":"",s=so(this._milliseconds)!==so(d)?"-":"",i+"P"+(n?a+n+"Y":"")+(c?a+c+"M":"")+(u?o+u+"D":"")+(t||e||l?"T":"")+(t?s+t+"H":"")+(e?s+e+"M":"")+(l?s+r+"S":"")):"P0D"}var uo=or.prototype;return uo.isValid=ir,uo.abs=wa,uo.add=ka,uo.subtract=Ea,uo.as=Oa,uo.asMilliseconds=Na,uo.asSeconds=Da,uo.asMinutes=Ma,uo.asHours=Ra,uo.asDays=ja,uo.asWeeks=La,uo.asMonths=Fa,uo.asQuarters=Ba,uo.asYears=Va,uo.valueOf=$a,uo._bubble=Pa,uo.clone=Ua,uo.get=za,uo.milliseconds=Ha,uo.seconds=Ya,uo.minutes=Wa,uo.hours=Ka,uo.days=qa,uo.weeks=Ja,uo.months=Qa,uo.years=Xa,uo.humanize=ao,uo.toISOString=lo,uo.toString=lo,uo.toJSON=lo,uo.locale=oi,uo.localeData=li,uo.toIsoString=E("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",lo),uo.lang=si,B("X",0,0,"unix"),B("x",0,0,"valueOf"),De("x",Te),De("X",Ie),Fe("X",(function(e,t,n){n._d=new Date(1e3*parseFloat(e))})),Fe("x",(function(e,t,n){n._d=new Date(ce(e))})),r.version="2.29.4",i(qn),r.fn=la,r.min=Zn,r.max=er,r.now=tr,r.utc=p,r.unix=ua,r.months=va,r.isDate=d,r.locale=mn,r.invalid=y,r.duration=Cr,r.isMoment=A,r.weekdays=ya,r.parseZone=ca,r.localeData=yn,r.isDuration=sr,r.monthsShort=ga,r.weekdaysMin=_a,r.defineLocale=vn,r.updateLocale=gn,r.locales=bn,r.weekdaysShort=ba,r.normalizeUnits=re,r.relativeTimeRounding=ro,r.relativeTimeThreshold=io,r.calendarFormat=Vr,r.prototype=la,r.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},r}()},1843:function(e){"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;function i(e){if(null===e||void 0===e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(i){return!1}}()?Object.assign:function(e,a){for(var o,s,l=i(e),u=1;u