├── .changeset ├── @accounts_module-core-1270-dependencies.md ├── @accounts_module-core-1273-dependencies.md ├── @accounts_rest-express-1273-dependencies.md ├── README.md ├── afraid-rules-heal.md ├── config.json ├── cuddly-readers-trade.md ├── cyan-peas-beg.md ├── empty-lizards-shake.md ├── empty-pianos-hunt.md ├── famous-jobs-build.md ├── fresh-dolphins-fold.md ├── friendly-mugs-raise.md ├── green-geckos-glow.md ├── hot-carrots-accept.md ├── little-cups-change.md ├── lucky-ears-tan.md ├── mighty-badgers-thank.md ├── neat-papayas-hear.md ├── perfect-sloths-hang.md ├── quick-maps-begin.md ├── quiet-dingos-knock.md ├── quiet-icons-breathe.md ├── rotten-baboons-raise.md ├── rotten-dolphins-impress.md ├── sharp-garlics-yawn.md ├── sharp-jeans-begin.md ├── silent-crews-perform.md ├── slow-dots-learn.md ├── small-candles-try.md ├── sweet-coats-move.md ├── sweet-poets-lie.md ├── ten-ghosts-nail.md ├── thin-poems-crash.md ├── thirty-dancers-rhyme.md ├── tidy-cherries-drop.md ├── twelve-hornets-wait.md ├── witty-knives-applaud.md └── young-files-cry.md ├── .eslintrc.js ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 1.Bug_report.md │ ├── 2.Feature_request.md │ └── config.yml ├── semantic.yml └── workflows │ ├── codeql-analysis.yml │ ├── pr.yml │ ├── release-stable.yml │ ├── tests.yml │ └── website.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .yarnrc.yml ├── CONTRIBUTING.md ├── LICENSE ├── MAINTAINERS.md ├── MEETINGS.md ├── README.md ├── docker-compose.yml ├── examples ├── README.md ├── accounts-microservice │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ ├── accounts-microservice.ts │ │ └── app-server.ts │ └── tsconfig.json ├── graphql-server-mikro-orm-postgres │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ ├── entities │ │ │ ├── email.ts │ │ │ └── user.ts │ │ ├── index.ts │ │ └── mikro-orm-config.ts │ └── tsconfig.json ├── graphql-server-typeorm-postgres │ ├── .env │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ ├── connect.ts │ │ └── index.ts │ └── tsconfig.json ├── graphql-server-typescript-apollo │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── graphql-server-typescript-basic │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── graphql-server-typescript │ ├── .DS_Store │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── magic-link-server-typescript │ ├── README.md │ ├── docker-compose.yml │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── react-graphql-typescript │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ └── vite.svg │ ├── src │ │ ├── App.tsx │ │ ├── Home.tsx │ │ ├── Login.tsx │ │ ├── ResetPassword.tsx │ │ ├── Router.tsx │ │ ├── Signup.tsx │ │ ├── TwoFactor.tsx │ │ ├── VerifyEmail.tsx │ │ ├── components │ │ │ └── FormError.tsx │ │ ├── main.tsx │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ ├── utils │ │ │ └── accounts.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── react-rest-typescript │ ├── .env.development │ ├── .env.production │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── README.md │ ├── index.html │ ├── package.json │ ├── public │ │ ├── logo.png │ │ └── vite.svg │ ├── src │ │ ├── App.tsx │ │ ├── ChangePassword.tsx │ │ ├── Email.tsx │ │ ├── Home.tsx │ │ ├── Login.tsx │ │ ├── ResetPassword.tsx │ │ ├── Router.tsx │ │ ├── Security.tsx │ │ ├── Signup.tsx │ │ ├── TwoFactor.tsx │ │ ├── VerifyEmail.tsx │ │ ├── accounts.ts │ │ ├── components │ │ │ ├── AppBar.tsx │ │ │ ├── AuthContext.tsx │ │ │ ├── AuthenticatedContainer.tsx │ │ │ ├── Container.tsx │ │ │ ├── Drawer.tsx │ │ │ ├── FormError.tsx │ │ │ ├── SnackBarContentError.tsx │ │ │ ├── SnackBarContentSuccess.tsx │ │ │ └── UnauthenticatedContainer.tsx │ │ ├── index.tsx │ │ ├── main.tsx │ │ ├── reportWebVitals.ts │ │ └── vite-env.d.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ └── vite.config.ts ├── rest-express-typescript-without-modules │ ├── README.md │ ├── now.json │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json └── rest-express-typescript │ ├── README.md │ ├── now.json │ ├── package.json │ ├── src │ └── index.ts │ └── tsconfig.json ├── lerna.json ├── modules ├── module-core │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── index.ts │ │ ├── resolvers │ │ │ ├── mutation.ts │ │ │ └── query.ts │ │ └── utils │ │ │ ├── authenticated-resolver.ts │ │ │ └── context-builder.ts │ ├── codegen.yml │ ├── introspection.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── models.ts │ │ ├── resolvers │ │ │ ├── mutation.ts │ │ │ └── query.ts │ │ ├── schema.ts │ │ ├── schema │ │ │ ├── mutation.ts │ │ │ ├── query.ts │ │ │ ├── schema-def.ts │ │ │ ├── schema.ts │ │ │ └── types.ts │ │ └── utils │ │ │ ├── authenticated-directive.ts │ │ │ ├── authenticated-resolver.ts │ │ │ ├── context-builder.ts │ │ │ ├── index.ts │ │ │ └── schema-builder.ts │ └── tsconfig.json ├── module-magic-link │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── resolvers │ │ │ └── mutation.ts │ ├── codegen.yml │ ├── introspection.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── models.ts │ │ ├── resolvers │ │ │ └── mutation.ts │ │ ├── schema.ts │ │ └── schema │ │ │ └── mutation.ts │ └── tsconfig.json ├── module-mikro-orm │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── types │ │ │ ├── IContext.ts │ │ │ └── index.ts │ │ └── utils │ │ │ ├── context-builder.ts │ │ │ └── index.ts │ └── tsconfig.json ├── module-mongo │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── module-password │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── resolvers │ │ │ ├── mutation.ts │ │ │ └── query.ts │ ├── codegen.yml │ ├── introspection.json │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── models.ts │ │ ├── resolvers │ │ │ ├── mutation.ts │ │ │ └── query.ts │ │ ├── schema.ts │ │ └── schema │ │ │ ├── mutation.ts │ │ │ ├── query.ts │ │ │ └── types.ts │ └── tsconfig.json └── module-typeorm │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ └── index.ts │ └── tsconfig.json ├── netlify.toml ├── package.json ├── packages ├── apollo-link-accounts │ ├── CHANGELOG.md │ ├── README.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── client-magic-link │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── client-magic-link.ts │ ├── package.json │ ├── src │ │ ├── client-magic-link.ts │ │ └── index.ts │ └── tsconfig.json ├── client-password │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── client-password.ts │ ├── package.json │ ├── src │ │ ├── client-password.ts │ │ ├── index.ts │ │ └── types │ │ │ ├── index.ts │ │ │ └── options.ts │ └── tsconfig.json ├── client │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── accounts-client.ts │ │ └── utils.ts │ ├── package.json │ ├── src │ │ ├── accounts-client.ts │ │ ├── index.ts │ │ ├── token-storage-local.ts │ │ ├── transport-interface.ts │ │ ├── types │ │ │ ├── index.ts │ │ │ ├── options.ts │ │ │ └── token-storage.ts │ │ └── utils.ts │ └── tsconfig.json ├── database-mikro-orm │ ├── README.md │ ├── package.json │ ├── src │ │ ├── entity │ │ │ ├── Email.ts │ │ │ ├── Service.ts │ │ │ ├── Session.ts │ │ │ └── User.ts │ │ ├── index.ts │ │ ├── mikro-orm.ts │ │ └── types │ │ │ ├── Email.symbol.ts │ │ │ ├── Service.symbol.ts │ │ │ ├── Session.symbol.ts │ │ │ ├── User.symbol.ts │ │ │ └── index.ts │ └── tsconfig.json ├── database-mongo-magic-link │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── mongo-magic-link.ts │ │ └── utils.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── mongo-magic-link.ts │ │ └── utils.ts │ └── tsconfig.json ├── database-mongo-password │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── mongo-password.ts │ │ └── utils.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── mongo-password.ts │ │ └── utils.ts │ └── tsconfig.json ├── database-mongo-sessions │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── mongo-sessions.ts │ │ └── utils.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── mongo-sessions.ts │ │ └── utils.ts │ └── tsconfig.json ├── database-mongo │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── database-tests.ts │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── mongo.ts │ │ └── types │ │ │ ├── AccountsMongoConfig.symbol.ts │ │ │ ├── MongoConnection.symbol.ts │ │ │ ├── accounts-mongo-options.ts │ │ │ └── index.ts │ └── tsconfig.json ├── database-redis │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── database-tests.ts │ │ └── redis.ts │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── redis.ts │ │ └── types │ │ │ ├── index.ts │ │ │ └── options.ts │ └── tsconfig.json ├── database-tests │ ├── CHANGELOG.md │ ├── package.json │ ├── src │ │ └── index.ts │ └── tsconfig.json ├── database-typeorm │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── typeorm-magic-link.ts │ │ ├── typeorm-password.ts │ │ └── typeorm-sessions.ts │ ├── package.json │ ├── src │ │ ├── entity │ │ │ ├── User.ts │ │ │ ├── UserEmail.ts │ │ │ ├── UserService.ts │ │ │ └── UserSession.ts │ │ ├── index.ts │ │ ├── typeorm.ts │ │ └── types │ │ │ ├── AccountsTypeORMConfig.symbol.ts │ │ │ ├── User.symbol.ts │ │ │ ├── UserEmail.symbol.ts │ │ │ ├── UserService.symbol.ts │ │ │ ├── UserSession.symbol.ts │ │ │ └── index.ts │ └── tsconfig.json ├── e2e │ ├── __tests__ │ │ ├── core.ts │ │ ├── databases │ │ │ ├── index.ts │ │ │ ├── mongo.ts │ │ │ └── typeorm.ts │ │ ├── password.ts │ │ └── servers │ │ │ ├── index.ts │ │ │ ├── server-graphql.ts │ │ │ └── server-rest.ts │ ├── package.json │ └── tsconfig.json ├── error │ ├── CHANGELOG.md │ ├── __tests__ │ │ ├── accounts-error.ts │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── accounts-error.ts │ │ └── index.ts │ └── tsconfig.json ├── express-session │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── accounts-session.ts │ │ ├── index.ts │ │ └── utils.ts │ ├── package.json │ ├── src │ │ ├── custom.d.ts │ │ ├── index.ts │ │ └── utils │ │ │ └── get-user-agent.ts │ └── tsconfig.json ├── graphql-client │ ├── CHANGELOG.md │ ├── README.md │ ├── codegen.yml │ ├── package.json │ ├── src │ │ ├── GraphQLErrorList.ts │ │ ├── graphql-client.ts │ │ ├── graphql-operations.ts │ │ ├── graphql │ │ │ ├── fragments │ │ │ │ └── userFields.graphql │ │ │ ├── mutations │ │ │ │ ├── add-email.graphql │ │ │ │ ├── authenticate-with-service.graphql │ │ │ │ ├── change-password.graphql │ │ │ │ ├── create-user.graphql │ │ │ │ ├── impersonate.graphql │ │ │ │ ├── login-with-service.graphql │ │ │ │ ├── logout.graphql │ │ │ │ ├── refresh-tokens.graphql │ │ │ │ ├── request-magic-link-email.graphql │ │ │ │ ├── reset-password.graphql │ │ │ │ ├── send-reset-password-email.graphql │ │ │ │ ├── send-verification-email.graphql │ │ │ │ ├── two-factor-set.graphql │ │ │ │ ├── two-factor-unset.graphql │ │ │ │ └── verify-email.graphql │ │ │ └── queries │ │ │ │ ├── get-two-factor-secret.graphql │ │ │ │ └── get-user.graphql │ │ ├── index.ts │ │ └── utils │ │ │ └── replace-user-fragment.ts │ └── tsconfig.json ├── magic-link │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── accounts-magic-link.ts │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── accounts-magic-link.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── types │ │ │ ├── AccountsMagicLinkConfig.symbol.ts │ │ │ ├── error-messages.ts │ │ │ └── index.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ ├── is-email.ts │ │ │ ├── user.ts │ │ │ └── validation.ts │ └── tsconfig.json ├── oauth-instagram │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── accounts-oauth-instagram.ts │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── accounts-oauth-instagram.ts │ │ ├── index.ts │ │ └── types │ │ │ └── configuration.ts │ └── tsconfig.json ├── oauth-twitter │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── accounts-oauth-twitter.ts │ │ ├── index.ts │ │ └── types │ │ │ └── configuration.ts │ └── tsconfig.json ├── oauth │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── accounts-oauth.ts │ │ └── index.ts │ ├── package.json │ ├── src │ │ ├── accounts-oauth.ts │ │ ├── index.ts │ │ └── types │ │ │ ├── OAuthProviders.symbol.ts │ │ │ ├── oauth-provider.ts │ │ │ ├── oauth-providers.ts │ │ │ └── oauth-user.ts │ └── tsconfig.json ├── password │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ └── accounts-password.ts.snap │ │ ├── accounts-password.ts │ │ ├── index.ts │ │ └── utils │ │ │ └── encryption.ts │ ├── package.json │ ├── src │ │ ├── accounts-password.ts │ │ ├── endpoints │ │ │ ├── Request.d.ts │ │ │ ├── express.ts │ │ │ └── index.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── types │ │ │ ├── AccountsPasswordConfig.symbol.ts │ │ │ ├── error-messages.ts │ │ │ └── index.ts │ │ └── utils │ │ │ ├── encryption.ts │ │ │ ├── index.ts │ │ │ ├── is-email.ts │ │ │ ├── user.ts │ │ │ └── validation.ts │ └── tsconfig.json ├── rest-client │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── auth-fetch.ts │ │ └── rest-client.ts │ ├── package.json │ ├── src │ │ ├── accounts-error.ts │ │ ├── auth-fetch.ts │ │ ├── index.ts │ │ └── rest-client.ts │ └── tsconfig.json ├── rest-express │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── endpoints │ │ │ ├── get-user.ts │ │ │ ├── impersonate.ts │ │ │ ├── logout.ts │ │ │ ├── magic-link │ │ │ │ └── request-magic-link-email.ts │ │ │ ├── oauth │ │ │ │ └── provider-callback.ts │ │ │ ├── password │ │ │ │ ├── add-email.ts │ │ │ │ ├── change-password.ts │ │ │ │ ├── register.ts │ │ │ │ ├── reset.ts │ │ │ │ ├── two-factor.ts │ │ │ │ └── verify-email.ts │ │ │ ├── refresh-access-token.ts │ │ │ ├── service-authenticate.ts │ │ │ └── verify-authentication.ts │ │ ├── express-middleware.ts │ │ ├── user-loader.ts │ │ └── utils │ │ │ └── get-user-agent.ts │ ├── package.json │ ├── src │ │ ├── custom.d.ts │ │ ├── endpoints │ │ │ ├── get-user.ts │ │ │ ├── impersonate.ts │ │ │ ├── logout.ts │ │ │ ├── magic-link │ │ │ │ └── request-magic-link-email.ts │ │ │ ├── oauth │ │ │ │ └── provider-callback.ts │ │ │ ├── password │ │ │ │ ├── add-email.ts │ │ │ │ ├── change-password.ts │ │ │ │ ├── register.ts │ │ │ │ ├── reset.ts │ │ │ │ ├── two-factor.ts │ │ │ │ └── verify-email.ts │ │ │ ├── refresh-access-token.ts │ │ │ ├── service-authenticate.ts │ │ │ └── verify-authentication.ts │ │ ├── express-middleware.ts │ │ ├── index.ts │ │ ├── types.ts │ │ ├── user-loader.ts │ │ └── utils │ │ │ ├── get-user-agent.ts │ │ │ ├── matchOrTrow.ts │ │ │ └── send-error.ts │ └── tsconfig.json ├── server │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── account-server.ts │ │ ├── index.ts │ │ └── utils │ │ │ ├── __snapshots__ │ │ │ └── email.ts.snap │ │ │ ├── email.ts │ │ │ └── get-first-user-email.ts │ ├── package.json │ ├── src │ │ ├── accounts-server.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── types │ │ │ ├── AccountsCoreConfig.symbol.ts │ │ │ ├── AuthenticationServices.symbol.ts │ │ │ ├── DatabaseInterfaceSessions.symbol.ts │ │ │ ├── DatabaseInterfaceUser.symbol.ts │ │ │ ├── accounts-server-options.ts │ │ │ ├── authentication-services.ts │ │ │ ├── email-template-type.ts │ │ │ ├── email-templates-type.ts │ │ │ ├── email-type.ts │ │ │ ├── jwt-data.ts │ │ │ ├── jwt-payload.ts │ │ │ ├── prepare-mail-function.ts │ │ │ ├── send-mail-type.ts │ │ │ └── token-creator.ts │ │ └── utils │ │ │ ├── accounts-error.ts │ │ │ ├── email.ts │ │ │ ├── get-first-user-email.ts │ │ │ ├── server-hooks.ts │ │ │ ├── tokens.ts │ │ │ └── validation.ts │ └── tsconfig.json ├── two-factor │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ │ ├── __snapshots__ │ │ │ ├── errors.ts.snap │ │ │ └── two-factor.ts.snap │ │ ├── errors.ts │ │ ├── index.ts │ │ └── two-factor.ts │ ├── package.json │ ├── src │ │ ├── errors.ts │ │ ├── index.ts │ │ ├── two-factor.ts │ │ ├── types │ │ │ ├── error-messages.ts │ │ │ ├── index.ts │ │ │ ├── options.ts │ │ │ └── two-factor-service.ts │ │ └── utils │ │ │ ├── index.ts │ │ │ └── user.ts │ └── tsconfig.json └── types │ ├── CHANGELOG.md │ ├── README.md │ ├── __tests__ │ └── index.ts │ ├── package.json │ ├── src │ ├── index.ts │ └── types │ │ ├── authentication-service.ts │ │ ├── connection-informations.ts │ │ ├── context.ts │ │ ├── create-user-result.ts │ │ ├── create-user.ts │ │ ├── database-interface.ts │ │ ├── database-type.ts │ │ ├── email-record.ts │ │ ├── hook-listener.ts │ │ ├── impersonation-result.ts │ │ ├── login-result.ts │ │ ├── login-user-identity.ts │ │ ├── services │ │ ├── magic-link │ │ │ ├── database-interface.ts │ │ │ └── login-user.ts │ │ └── password │ │ │ ├── create-user.ts │ │ │ ├── database-interface.ts │ │ │ └── login-user.ts │ │ ├── session │ │ ├── database-interface.ts │ │ └── session.ts │ │ ├── token-record.ts │ │ ├── tokens.ts │ │ ├── user.ts │ │ └── user │ │ └── database-interface.ts │ └── tsconfig.json ├── res ├── Design.md ├── notes │ └── modular-auth.md └── packages.jpg ├── tsconfig.json ├── website ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── client.md │ ├── contributing.md │ ├── cookbook │ │ └── react-native.md │ ├── databases │ │ ├── mikro-orm.md │ │ ├── mongo.md │ │ ├── overview.md │ │ ├── redis.md │ │ └── typeorm.md │ ├── email.md │ ├── getting-started.md │ ├── handling-errors.md │ ├── introduction.md │ ├── server.md │ ├── strategies │ │ ├── facebook.md │ │ ├── oauth.md │ │ ├── password-client.md │ │ ├── password.md │ │ └── twitter.md │ └── transports │ │ ├── graphql.md │ │ ├── rest-client.md │ │ └── rest-express.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.js │ │ └── styles.module.css ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.png │ │ └── logo.png └── tsconfig.json └── yarn.lock /.changeset/@accounts_module-core-1270-dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': patch 3 | --- 4 | dependencies updates: 5 | - Updated dependency [`@graphql-tools/utils@10.0.13` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.0.13) (from `10.0.12`, in `dependencies`) 6 | -------------------------------------------------------------------------------- /.changeset/@accounts_module-core-1273-dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': patch 3 | --- 4 | dependencies updates: 5 | - Updated dependency [`@graphql-tools/merge@9.0.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/merge/v/9.0.3) (from `9.0.1`, in `dependencies`) 6 | - Updated dependency [`@graphql-tools/schema@10.0.3` ↗︎](https://www.npmjs.com/package/@graphql-tools/schema/v/10.0.3) (from `10.0.2`, in `dependencies`) 7 | - Updated dependency [`@graphql-tools/utils@10.1.0` ↗︎](https://www.npmjs.com/package/@graphql-tools/utils/v/10.1.0) (from `10.0.13`, in `dependencies`) 8 | -------------------------------------------------------------------------------- /.changeset/@accounts_rest-express-1273-dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/rest-express': patch 3 | --- 4 | dependencies updates: 5 | - Updated dependency [`express@4.18.3` ↗︎](https://www.npmjs.com/package/express/v/4.18.3) (from `4.18.2`, in `dependencies`) 6 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/afraid-rules-heal.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/mikro-orm': patch 3 | '@accounts/typeorm': patch 4 | '@accounts/express-session': patch 5 | '@accounts/magic-link': patch 6 | '@accounts/password': patch 7 | '@accounts/server': patch 8 | --- 9 | 10 | Upgrade lodash to 4.17 11 | -------------------------------------------------------------------------------- /.changeset/cuddly-readers-trade.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/rest-client': patch 3 | --- 4 | 5 | Upgrade node-fetch to 2.7 6 | -------------------------------------------------------------------------------- /.changeset/cyan-peas-beg.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-password': major 3 | --- 4 | 5 | Add @accounts/module-password 6 | -------------------------------------------------------------------------------- /.changeset/empty-pianos-hunt.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-password': major 3 | '@accounts/password': major 4 | '@accounts/rest-express': major 5 | '@accounts/server': major 6 | '@accounts/types': major 7 | --- 8 | 9 | Add option to require email verification 10 | -------------------------------------------------------------------------------- /.changeset/famous-jobs-build.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-magic-link': major 3 | --- 4 | 5 | Add @accounts/module-magic-link 6 | -------------------------------------------------------------------------------- /.changeset/fresh-dolphins-fold.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': minor 3 | '@accounts/module-password': minor 4 | --- 5 | 6 | Return unmasked 401 errors when unauthorized 7 | -------------------------------------------------------------------------------- /.changeset/friendly-mugs-raise.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/express-session': patch 3 | '@accounts/rest-express': patch 4 | --- 5 | 6 | Upgrade express to 4.18 7 | -------------------------------------------------------------------------------- /.changeset/green-geckos-glow.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': major 3 | '@accounts/module-magic-link': major 4 | '@accounts/module-mikro-orm': major 5 | '@accounts/module-mongo': major 6 | '@accounts/module-password': major 7 | '@accounts/module-typeorm': major 8 | '@accounts/mikro-orm': major 9 | '@accounts/mongo': major 10 | '@accounts/typeorm': major 11 | '@accounts/magic-link': major 12 | '@accounts/oauth': major 13 | '@accounts/password': major 14 | '@accounts/server': major 15 | '@accounts/types': major 16 | --- 17 | 18 | Upgrade graphql-modules to v3 alpha 19 | -------------------------------------------------------------------------------- /.changeset/hot-carrots-accept.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': minor 3 | '@accounts/module-magic-link': minor 4 | '@accounts/module-mikro-orm': minor 5 | '@accounts/module-mongo': minor 6 | '@accounts/module-password': minor 7 | '@accounts/module-typeorm': minor 8 | --- 9 | 10 | Upgrade @graphql-tools/merge to v9 11 | -------------------------------------------------------------------------------- /.changeset/little-cups-change.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/oauth-twitter': patch 3 | --- 4 | 5 | Upgrade oauth to 0.10 6 | -------------------------------------------------------------------------------- /.changeset/lucky-ears-tan.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-typeorm': minor 3 | '@accounts/typeorm': minor 4 | --- 5 | 6 | Upgrade typeorm to 0.3.17 7 | -------------------------------------------------------------------------------- /.changeset/mighty-badgers-thank.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': patch 3 | '@accounts/module-magic-link': patch 4 | '@accounts/module-mikro-orm': patch 5 | '@accounts/module-mongo': patch 6 | '@accounts/module-password': patch 7 | '@accounts/module-typeorm': patch 8 | '@accounts/express-session': patch 9 | '@accounts/rest-express': patch 10 | --- 11 | 12 | Upgrade request-ip to 3.3 13 | -------------------------------------------------------------------------------- /.changeset/neat-papayas-hear.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/two-factor': patch 3 | --- 4 | 5 | Upgrade @levminer/speakeasy to 1.4 6 | -------------------------------------------------------------------------------- /.changeset/perfect-sloths-hang.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/password': minor 3 | '@accounts/rest-express': minor 4 | --- 5 | 6 | Implement validation in rest-express and password endpoints 7 | -------------------------------------------------------------------------------- /.changeset/quick-maps-begin.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-mongo': major 3 | --- 4 | 5 | Add @accounts/module-mongo 6 | -------------------------------------------------------------------------------- /.changeset/quiet-dingos-knock.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-password': major 3 | '@accounts/password': major 4 | '@accounts/rest-express': major 5 | '@accounts/server': major 6 | '@accounts/types': major 7 | --- 8 | 9 | Fix ambiguousErrorMessages and enableAutologin relationship 10 | -------------------------------------------------------------------------------- /.changeset/quiet-icons-breathe.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-mikro-orm': major 3 | --- 4 | 5 | Add @accounts/module-mikro-orm 6 | -------------------------------------------------------------------------------- /.changeset/rotten-baboons-raise.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': patch 3 | '@accounts/module-magic-link': patch 4 | '@accounts/module-mikro-orm': patch 5 | '@accounts/module-mongo': patch 6 | '@accounts/module-password': patch 7 | '@accounts/module-typeorm': patch 8 | '@accounts/graphql-client': patch 9 | --- 10 | 11 | Upgrade @graphql-codegen to v5 12 | -------------------------------------------------------------------------------- /.changeset/rotten-dolphins-impress.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': major 3 | --- 4 | 5 | Add @accounts/module-core 6 | -------------------------------------------------------------------------------- /.changeset/sharp-garlics-yawn.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/redis': minor 3 | --- 4 | 5 | Upgraded `ioredis` to v5 6 | -------------------------------------------------------------------------------- /.changeset/sharp-jeans-begin.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/password': minor 3 | --- 4 | 5 | Add express endpoints for email verification and password reset to the password service 6 | -------------------------------------------------------------------------------- /.changeset/silent-crews-perform.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/mikro-orm': major 3 | --- 4 | 5 | Add mikro-orm v6 database adapter 6 | -------------------------------------------------------------------------------- /.changeset/slow-dots-learn.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/typeorm': patch 3 | --- 4 | 5 | Upgrade pg to 8.11 6 | -------------------------------------------------------------------------------- /.changeset/small-candles-try.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': minor 3 | '@accounts/module-magic-link': minor 4 | '@accounts/module-mikro-orm': minor 5 | '@accounts/module-mongo': minor 6 | '@accounts/module-password': minor 7 | '@accounts/module-typeorm': minor 8 | --- 9 | 10 | Upgrade @graphql-tools/utils to v10 11 | -------------------------------------------------------------------------------- /.changeset/sweet-coats-move.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/apollo-link': minor 3 | --- 4 | 5 | Upgrade @apollo/client to 3.8 6 | -------------------------------------------------------------------------------- /.changeset/ten-ghosts-nail.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': minor 3 | --- 4 | 5 | Upgrade @graphql-tools/schema to v10 6 | -------------------------------------------------------------------------------- /.changeset/thin-poems-crash.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': minor 3 | '@accounts/module-magic-link': minor 4 | '@accounts/module-mikro-orm': minor 5 | '@accounts/module-mongo': minor 6 | '@accounts/module-password': minor 7 | '@accounts/module-typeorm': minor 8 | '@accounts/apollo-link': minor 9 | '@accounts/mikro-orm': minor 10 | '@accounts/mongo': minor 11 | '@accounts/typeorm': minor 12 | '@accounts/graphql-client': minor 13 | '@accounts/magic-link': minor 14 | '@accounts/oauth': minor 15 | '@accounts/password': minor 16 | '@accounts/server': minor 17 | '@accounts/types': minor 18 | --- 19 | 20 | Upgrade graphql to v16 21 | -------------------------------------------------------------------------------- /.changeset/thirty-dancers-rhyme.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-core': major 3 | '@accounts/module-magic-link': major 4 | '@accounts/module-mikro-orm': major 5 | '@accounts/module-mongo': major 6 | '@accounts/module-password': major 7 | '@accounts/module-typeorm': major 8 | --- 9 | 10 | Move graphql-api into graphql modules 11 | -------------------------------------------------------------------------------- /.changeset/tidy-cherries-drop.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/client': patch 3 | '@accounts/server': patch 4 | --- 5 | 6 | Upgrade jsonwebtoken to v9 7 | -------------------------------------------------------------------------------- /.changeset/twelve-hornets-wait.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/server': patch 3 | --- 4 | 5 | Upgrade emittery to 0.13 6 | -------------------------------------------------------------------------------- /.changeset/witty-knives-applaud.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/module-typeorm': major 3 | --- 4 | 5 | Add @accounts/module-typeorm 6 | -------------------------------------------------------------------------------- /.changeset/young-files-cry.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@accounts/mongo': minor 3 | '@accounts/mongo-magic-link': minor 4 | '@accounts/mongo-password': minor 5 | '@accounts/mongo-sessions': minor 6 | --- 7 | 8 | Upgrade mongodb to v6 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | plugins: ['@typescript-eslint', 'jest'], 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:jest/recommended', 8 | 'prettier', 9 | ], 10 | parserOptions: { 11 | ecmaVersion: 2018, 12 | sourceType: 'module', 13 | }, 14 | rules: { 15 | '@typescript-eslint/ban-types': 0, 16 | '@typescript-eslint/explicit-function-return-type': 0, 17 | '@typescript-eslint/explicit-module-boundary-types': 0, 18 | '@typescript-eslint/no-explicit-any': 0, 19 | '@typescript-eslint/no-non-null-assertion': 0, 20 | '@typescript-eslint/no-unused-vars': 'error', 21 | '@typescript-eslint/consistent-type-imports': [ 22 | 'error', 23 | { 24 | prefer: 'type-imports', 25 | disallowTypeAnnotations: true, 26 | fixStyle: 'inline-type-imports', 27 | }, 28 | ], 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | open_collective: accounts-js 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1.Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug report 3 | about: Create a bug report for the accounts-js core / examples 4 | labels: 'bug' 5 | --- 6 | 7 | 9 | 10 | # Bug report 11 | 12 | ## Describe the bug 13 | 14 | A clear and concise description of what the bug is. 15 | 16 | ## To Reproduce 17 | 18 | Steps to reproduce the behavior, please provide code snippets or a repository. 19 | 20 | ## Expected behavior 21 | 22 | A clear and concise description of what you expected to happen. 23 | 24 | ## Screenshots 25 | 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | ## System information 29 | 30 | - Version of accounts-js: [e.g. 0.0.24] 31 | 32 | ## Additional context 33 | 34 | Add any other context about the problem here. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2.Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ⚡ Feature request 3 | about: Create a feature request for accounts-js 4 | labels: 'enhancement' 5 | --- 6 | 7 | 9 | 10 | # Feature request 11 | 12 | ## Is your feature request related to a problem? Please describe. 13 | 14 | A clear and concise description of what you want and what your use case is. 15 | 16 | ## Describe the solution you'd like 17 | 18 | A clear and concise description of what you want to happen. 19 | 20 | ## Additional context 21 | 22 | Add any other context or screenshots about the feature request here. 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 🙋 Ask a question 4 | url: https://github.com/accounts-js/accounts/discussions 5 | about: Ask questions and discuss with other community members 6 | -------------------------------------------------------------------------------- /.github/semantic.yml: -------------------------------------------------------------------------------- 1 | titleOnly: true 2 | -------------------------------------------------------------------------------- /.github/workflows/release-stable.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | stable: 9 | uses: darkbasic/shared-config/.github/workflows/release-stable.yml@main 10 | with: 11 | releaseScript: release 12 | nodeVersion: 18 13 | appId: ${{ vars.APP_ID }} 14 | secrets: 15 | npmToken: ${{ secrets.NPM_TOKEN }} 16 | privateKey: ${{ secrets.APP_PRIVATE_KEY }} 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | node_modules/ 3 | coverage/ 4 | npm-debug.log 5 | lerna-debug.log 6 | yarn-error.log 7 | .idea 8 | .vscode 9 | packages/*/package-lock.json 10 | schema.json 11 | .DS_Store 12 | .eslintcache 13 | 14 | build/ 15 | .yarn 16 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | yarn lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage 2 | lib 3 | build 4 | package.json 5 | packages/graphql-api/introspection.json 6 | packages/graphql-api/src/models.ts 7 | packages/graphql-client/src/graphql-operations.ts 8 | website/.docusaurus 9 | website/docs/api 10 | .changeset/*.md 11 | packages/*/CHANGELOG.md 12 | modules/*/introspection.json 13 | modules/*/src/models.ts 14 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 - present. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers Guide 2 | 3 | > This guide is intended for maintainers 4 | 5 | ## Creating a new release 6 | 7 | 1. Merge the changeset pull request 8 | 2. Locally git pull the master branch 9 | 3. Run `pnpm run compile` 10 | 4. Run `pnpx lerna publish from-package` to publish the packages to npm 11 | -------------------------------------------------------------------------------- /MEETINGS.md: -------------------------------------------------------------------------------- 1 | # Community Meetings 2 | 3 | We try to have a meetings any other week! Here we have the rolling meetings notes from each meeting. 4 | If you'd like to change or suggest something, please open an issue on it! 5 | 6 | - December 28th, 2017 (Suggested) - https://docs.google.com/document/d/19QOj1tOxBnbZhDyTMpU4_n_GItddfQ7kUXaneHPgGLc/edit?usp=sharing 7 | 8 | - December 14th, 2017 - https://docs.google.com/document/d/1qjk5hx9Dr-deZgQVh-VSkLXGkaq7r_JPeUhDE_ZOxaw/edit?usp=sharing 9 | 10 | - November 30th, 2017 - https://docs.google.com/document/d/1hPB84T9z68qwautGgtMQUPq2BQjKSrn0Nly6pVcBCHY/edit?usp=sharing 11 | 12 | - November 9th, 2017 - https://docs.google.com/document/d/18pQP5FWXGDLY21g7TNnrEz6-88cBAXr5wRWnzvxbDwE/edit?usp=sharing 13 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | postgres: 4 | image: postgres:10.10 5 | ports: 6 | - '5432:5432' 7 | environment: 8 | POSTGRES_DB: accounts-js-tests-e2e 9 | mongo: 10 | image: mongo:3 11 | platform: linux/amd64 12 | ports: 13 | - '27017:27017' 14 | redis: 15 | image: redis:4 16 | ports: 17 | - '6379:6379' 18 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Accounts-js examples 2 | 3 | This folder provides examples on how to use the [accounts-js](https://github.com/accounts-js/accounts) packages. 4 | 5 | ## Examples 6 | 7 | REST Server + REST client example: 8 | 9 | - Server: [rest-express-typescript](./rest-express-typescript) 10 | - Client: [react-rest-typescript](./react-rest-typescript) 11 | 12 | GraphQL Server + GraphQL Client example: 13 | 14 | - Server: [graphql-server-typescript](./graphql-server-typescript) 15 | - Client: [react-graphql-typescript](./react-graphql-typescript) 16 | 17 | Other examples: 18 | 19 | - Accounts Boost [accounts-boost](./accounts-boost) 20 | - Typeorm + PostgreSQL example [graphql-server-typeorm-postgres](./graphql-server-typeorm-postgres) 21 | -------------------------------------------------------------------------------- /examples/accounts-microservice/README.md: -------------------------------------------------------------------------------- 1 | # accounts-boost examples 2 | 3 | Includes two examples of using `@accounts/boost`. 4 | 5 | `yarn run start:mono` - Starts a GraphQL server which consumes the `@accounts/boost` typeDefs and resolvers when building your app's schema. 6 | 7 | `yarn run start:micro` - Starts a `@accounts/boost` as a GraphQL microservice which is then stitched with your app's schema. 8 | -------------------------------------------------------------------------------- /examples/accounts-microservice/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-mongo-accounts: 4 | image: mongo:3.6.5-jessie 5 | ports: 6 | - '27017:27017' 7 | restart: always 8 | -------------------------------------------------------------------------------- /examples/accounts-microservice/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["./src/**/*"], 12 | "exclude": ["node_modules", "lib"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/graphql-server-mikro-orm-postgres/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-postgres-accounts: 4 | image: postgres:latest 5 | container_name: 'mikro-orm_postgres' 6 | ports: 7 | - '5432:5432' 8 | restart: always 9 | environment: 10 | POSTGRES_PASSWORD: 11 | POSTGRES_USER: postgres 12 | POSTGRES_DB: accounts 13 | SESSION_SECRET: 'very-secret' 14 | POSTGRES_HOST_AUTH_METHOD: 'trust' 15 | -------------------------------------------------------------------------------- /examples/graphql-server-mikro-orm-postgres/src/entities/email.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { 3 | type EmailCtor, 4 | type EmailCtorArgs as AccountsEmailCtorArgs, 5 | getEmailCtor, 6 | } from '@accounts/mikro-orm'; 7 | import { Entity, Property } from '@mikro-orm/core'; 8 | import { type User } from './user'; 9 | 10 | export type EmailCtorArgs = AccountsEmailCtorArgs & { 11 | fullName: string; 12 | }; 13 | 14 | const AccountsEmail: EmailCtor = getEmailCtor({ abstract: true }); 15 | 16 | @Entity() 17 | export class Email extends AccountsEmail { 18 | @Property() 19 | fullName: string; 20 | 21 | constructor({ fullName, ...otherProps }: EmailCtorArgs) { 22 | super(otherProps); 23 | this.fullName = fullName; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/graphql-server-mikro-orm-postgres/src/mikro-orm-config.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { 3 | getEmailSchema, 4 | getServiceSchema, 5 | getSessionSchema, 6 | getUserSchema, 7 | } from '@accounts/mikro-orm'; 8 | import { ReflectMetadataProvider } from '@mikro-orm/core'; 9 | import { User, AccountsUser } from './entities/user'; 10 | import { Email } from './entities/email'; 11 | import { PostgreSqlDriver } from '@mikro-orm/postgresql'; 12 | 13 | export default { 14 | metadataProvider: ReflectMetadataProvider, 15 | cache: { enabled: false }, 16 | entities: [ 17 | User, 18 | Email, 19 | getUserSchema({ AccountsUser, EmailEntity: Email, abstract: true }), 20 | getEmailSchema({ UserEntity: User, abstract: true }), 21 | getServiceSchema({ UserEntity: User }), 22 | getSessionSchema({ UserEntity: User }), 23 | ], 24 | dbName: 'accounts', 25 | user: 'postgres', 26 | password: 'very-secret', 27 | driver: PostgreSqlDriver, 28 | forceUtcTimezone: true, 29 | debug: true, 30 | }; 31 | -------------------------------------------------------------------------------- /examples/graphql-server-mikro-orm-postgres/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es2021", 5 | "lib": ["es2021", "esnext.asynciterable"], 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "importHelpers": true, 10 | "esModuleInterop": true, 11 | "skipLibCheck": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true 14 | }, 15 | "include": ["./src/**/*"], 16 | "exclude": ["node_modules", "lib"] 17 | } 18 | -------------------------------------------------------------------------------- /examples/graphql-server-typeorm-postgres/.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://postgres@localhost:5432/postgres 2 | ACCOUNTS_SECRET=very-secret 3 | -------------------------------------------------------------------------------- /examples/graphql-server-typeorm-postgres/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-postgres-accounts: 4 | image: postgres:latest 5 | container_name: 'my_postgres' 6 | ports: 7 | - '5432:5432' 8 | restart: always 9 | environment: 10 | POSTGRES_PASSWORD: 11 | POSTGRES_USER: postgres 12 | POSTGRES_DB: accounts 13 | SESSION_SECRET: 'very-secret' 14 | POSTGRES_HOST_AUTH_METHOD: 'trust' 15 | -------------------------------------------------------------------------------- /examples/graphql-server-typeorm-postgres/src/connect.ts: -------------------------------------------------------------------------------- 1 | import { createConnection } from 'typeorm'; 2 | import { entities } from '@accounts/typeorm'; 3 | 4 | export const connect = (url = process.env.DATABASE_URL) => { 5 | return createConnection({ 6 | type: 'postgres', 7 | url, 8 | entities, 9 | synchronize: true, 10 | }).then((connection) => { 11 | return connection; 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /examples/graphql-server-typeorm-postgres/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["./src/**/*"], 12 | "exclude": ["node_modules", "lib"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript-apollo/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-mongo-accounts: 4 | image: mongo:3.6.5-jessie 5 | ports: 6 | - '27017:27017' 7 | restart: always 8 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript-apollo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/graphql-server-typescript-apollo", 3 | "private": true, 4 | "version": "0.32.0", 5 | "main": "lib/index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts", 9 | "build": "yarn run -T tsc", 10 | "test": "yarn run build" 11 | }, 12 | "dependencies": { 13 | "@accounts/module-core": "^0.34.0", 14 | "@accounts/module-mongo": "^0.34.0", 15 | "@accounts/module-password": "^0.34.0", 16 | "@accounts/password": "^0.32.2", 17 | "@accounts/server": "^0.33.1", 18 | "@apollo/server": "4.10.1", 19 | "@apollo/server-plugin-landing-page-graphql-playground": "4.0.1", 20 | "@graphql-tools/merge": "9.0.3", 21 | "@graphql-tools/schema": "10.0.3", 22 | "graphql": "16.8.1", 23 | "graphql-modules": "3.0.0-alpha-20231106133212-0b04b56e", 24 | "graphql-tag": "2.12.6", 25 | "mongoose": "8.2.1", 26 | "tslib": "2.6.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript-apollo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["./src/**/*"], 12 | "exclude": ["node_modules", "lib"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript-basic/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-mongo-accounts: 4 | image: mongo:3.6.5-jessie 5 | ports: 6 | - '27017:27017' 7 | restart: always 8 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript-basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/graphql-server-typescript-basic", 3 | "private": true, 4 | "version": "0.32.0", 5 | "main": "lib/index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts", 9 | "build": "yarn run -T tsc", 10 | "test": "yarn run build" 11 | }, 12 | "dependencies": { 13 | "@accounts/module-core": "^0.34.0", 14 | "@accounts/module-mongo": "^0.34.0", 15 | "@accounts/module-password": "^0.34.0", 16 | "@accounts/password": "^0.32.2", 17 | "@accounts/server": "^0.33.1", 18 | "@graphql-tools/merge": "9.0.3", 19 | "@graphql-tools/schema": "10.0.3", 20 | "graphql": "16.8.1", 21 | "graphql-http": "1.22.0", 22 | "graphql-modules": "3.0.0-alpha-20231106133212-0b04b56e", 23 | "graphql-tag": "2.12.6", 24 | "mongoose": "8.2.1", 25 | "tslib": "2.6.2" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript-basic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["./src/**/*"], 12 | "exclude": ["node_modules", "lib"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accounts-js/accounts/67c77b06d2f2ee88c08174084ba17b1819656bc0/examples/graphql-server-typescript/.DS_Store -------------------------------------------------------------------------------- /examples/graphql-server-typescript/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-mongo-accounts: 4 | image: mongo:3.6.5-jessie 5 | ports: 6 | - '27017:27017' 7 | restart: always 8 | -------------------------------------------------------------------------------- /examples/graphql-server-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["./src/**/*"], 12 | "exclude": ["node_modules", "lib"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/magic-link-server-typescript/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | db-mongo-accounts: 4 | image: mongo:3.6.5-jessie 5 | ports: 6 | - '27017:27017' 7 | restart: always 8 | -------------------------------------------------------------------------------- /examples/magic-link-server-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/magic-link-server-typescript", 3 | "private": true, 4 | "version": "0.32.0", 5 | "main": "lib/index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts", 9 | "build": "yarn run -T tsc", 10 | "test": "yarn run build" 11 | }, 12 | "dependencies": { 13 | "@accounts/magic-link": "^0.1.1", 14 | "@accounts/mongo": "^0.34.1", 15 | "@accounts/server": "^0.33.1", 16 | "mongoose": "8.2.1", 17 | "tslib": "2.6.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/magic-link-server-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true 10 | }, 11 | "include": ["./src/**/*"], 12 | "exclude": ["node_modules", "lib"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/README.md: -------------------------------------------------------------------------------- 1 | # react-graphql-typescript 2 | 3 | This example demonstrate how to use [accounts-js](https://github.com/accounts-js/accounts). 4 | 5 | ## Setup example 6 | 7 | In order to be able to run this example on your machine you first need to do the following steps: 8 | 9 | - Clone the repository `git clone git@github.com:accounts-js/accounts.git` 10 | - Install project dependencies: `yarn install` 11 | - Compile the packages `yarn run compile` 12 | - Go to the example folder `cd examples/react-graphql-typescript` 13 | 14 | ## Getting Started 15 | 16 | If you haven't started the example server side, [go ahead to start it first](../graphql-server-typescript). 17 | 18 | Start the app. 19 | 20 | ```bash 21 | yarn run start 22 | ``` 23 | 24 | Open a browser and navigate to [http://localhost:3000](http://localhost:3000). 25 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { ApolloProvider } from '@apollo/client'; 2 | import { apolloClient } from './utils/accounts'; 3 | import Router from './Router'; 4 | 5 | function App() { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | export default App; 14 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/src/components/FormError.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import { makeStyles } from '@mui/styles'; 3 | 4 | const useStyles = makeStyles({ 5 | formError: { 6 | color: 'red', 7 | }, 8 | }); 9 | 10 | interface Props { 11 | error: string; 12 | } 13 | 14 | const FormError = ({ error }: Props) => { 15 | const classes = useStyles(); 16 | 17 | return {error}; 18 | }; 19 | 20 | export default FormError; 21 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | import reportWebVitals from './reportWebVitals'; 5 | 6 | ReactDOM.createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | 10 | ); 11 | 12 | // If you want to start measuring performance in your app, pass a function 13 | // to log results (for example: reportWebVitals(console.log)) 14 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 15 | reportWebVitals(); 16 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /examples/react-graphql-typescript/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | resolve: { 8 | preserveSymlinks: true, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/.env.development: -------------------------------------------------------------------------------- 1 | VITE_REACT_APP_API_URL=http://localhost:4000 2 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/.env.production: -------------------------------------------------------------------------------- 1 | VITE_REACT_APP_API_URL=$REACT_APP_API_URL 2 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/README.md: -------------------------------------------------------------------------------- 1 | # react-rest-typescript 2 | 3 | This example demonstrate how to use [accounts-js](https://github.com/accounts-js/accounts) with React and REST. 4 | 5 | In order to get the example running you also need to start the [REST server](https://github.com/accounts-js/accounts/tree/master/examples/rest-express-typescript). 6 | 7 | ## Setup example 8 | 9 | In order to be able to run this example on your machine you first need to do the following steps: 10 | 11 | - Clone the repository `git clone git@github.com:accounts-js/accounts.git` 12 | - Install project dependencies: `yarn install` 13 | - Compile the packages `yarn run compile` 14 | - Go to the example folder `cd examples/react-rest-typescript` 15 | 16 | ## Getting Started 17 | 18 | Start the app. 19 | 20 | ``` 21 | yarn run start 22 | ``` 23 | 24 | Open a browser and navigate to [http://localhost:3000](http://localhost:3000). 25 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accounts-js/accounts/67c77b06d2f2ee88c08174084ba17b1819656bc0/examples/react-rest-typescript/public/logo.png -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | createTheme, 3 | ThemeProvider, 4 | Theme, 5 | StyledEngineProvider, 6 | adaptV4Theme, 7 | } from '@mui/material'; 8 | import Router from './Router'; 9 | 10 | declare module '@mui/styles/defaultTheme' { 11 | // eslint-disable-next-line @typescript-eslint/no-empty-interface 12 | interface DefaultTheme extends Theme {} 13 | } 14 | 15 | const theme = createTheme( 16 | adaptV4Theme({ 17 | palette: { 18 | primary: { 19 | main: '#5e4b8e', 20 | }, 21 | secondary: { 22 | main: '#5cbdbc', 23 | }, 24 | }, 25 | }) 26 | ); 27 | 28 | function App() { 29 | return ( 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/Security.tsx: -------------------------------------------------------------------------------- 1 | import { Typography, Divider } from '@mui/material'; 2 | import makeStyles from '@mui/styles/makeStyles'; 3 | import { TwoFactor } from './TwoFactor'; 4 | import { ChangePassword } from './ChangePassword'; 5 | import { AuthenticatedContainer } from './components/AuthenticatedContainer'; 6 | 7 | const useStyles = makeStyles((theme) => ({ 8 | divider: { 9 | marginTop: theme.spacing(2), 10 | }, 11 | })); 12 | 13 | export const Security = () => { 14 | const classes = useStyles(); 15 | 16 | return ( 17 | 18 | Security 19 | 20 | 21 | 22 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/accounts.ts: -------------------------------------------------------------------------------- 1 | import { AccountsClient } from '@accounts/client'; 2 | import { AccountsClientPassword } from '@accounts/client-password'; 3 | import { RestClient } from '@accounts/rest-client'; 4 | 5 | const accountsRest = new RestClient({ 6 | apiHost: import.meta.env.VITE_REACT_APP_API_URL!, 7 | rootPath: '/accounts', 8 | }); 9 | const accountsClient = new AccountsClient({}, accountsRest); 10 | const accountsPassword = new AccountsClientPassword(accountsClient); 11 | 12 | export { accountsClient, accountsRest, accountsPassword }; 13 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/components/Container.tsx: -------------------------------------------------------------------------------- 1 | import { Container as MuiContainer } from '@mui/material'; 2 | 3 | import makeStyles from '@mui/styles/makeStyles'; 4 | 5 | const useStyles = makeStyles((theme) => ({ 6 | container: { 7 | paddingTop: theme.spacing(3), 8 | paddingBottom: theme.spacing(3), 9 | [theme.breakpoints.down('sm')]: { 10 | marginTop: 64, 11 | }, 12 | }, 13 | })); 14 | 15 | interface ContainerProps { 16 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 17 | children: any; 18 | maxWidth?: 'sm' | 'md'; 19 | } 20 | 21 | export const Container = ({ children, maxWidth }: ContainerProps) => { 22 | const classes = useStyles(); 23 | 24 | return ( 25 | 26 | {children} 27 | 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/components/FormError.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@mui/material'; 2 | import { makeStyles } from '@mui/styles'; 3 | 4 | const useStyles = makeStyles({ 5 | formError: { 6 | color: 'red', 7 | }, 8 | }); 9 | 10 | interface Props { 11 | error: string; 12 | } 13 | 14 | const FormError = ({ error }: Props) => { 15 | const classes = useStyles(); 16 | 17 | return {error}; 18 | }; 19 | 20 | export default FormError; 21 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/components/SnackBarContentError.tsx: -------------------------------------------------------------------------------- 1 | import { SnackbarContent } from '@mui/material'; 2 | 3 | import makeStyles from '@mui/styles/makeStyles'; 4 | 5 | const useStyles = makeStyles((theme) => ({ 6 | message: { 7 | display: 'flex', 8 | alignItems: 'center', 9 | }, 10 | error: { 11 | backgroundColor: theme.palette.error.dark, 12 | }, 13 | })); 14 | 15 | interface SnackBarContentErrorProps { 16 | message?: string; 17 | } 18 | 19 | export const SnackBarContentError = ({ message }: SnackBarContentErrorProps) => { 20 | const classes = useStyles(); 21 | 22 | return ( 23 | 28 | {message} 29 | 30 | } 31 | /> 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/components/SnackBarContentSuccess.tsx: -------------------------------------------------------------------------------- 1 | import { SnackbarContent } from '@mui/material'; 2 | import makeStyles from '@mui/styles/makeStyles'; 3 | import { green } from '@mui/material/colors'; 4 | 5 | const useStyles = makeStyles({ 6 | message: { 7 | display: 'flex', 8 | alignItems: 'center', 9 | }, 10 | error: { 11 | backgroundColor: green[600], 12 | }, 13 | }); 14 | 15 | interface SnackBarContentSuccessProps { 16 | message?: string; 17 | } 18 | 19 | export const SnackBarContentSuccess = ({ message }: SnackBarContentSuccessProps) => { 20 | const classes = useStyles(); 21 | 22 | return ( 23 | 28 | {message} 29 | 30 | } 31 | /> 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/components/UnauthenticatedContainer.tsx: -------------------------------------------------------------------------------- 1 | import { Container } from '@mui/material'; 2 | 3 | import makeStyles from '@mui/styles/makeStyles'; 4 | 5 | const useStyles = makeStyles((theme) => ({ 6 | root: { 7 | display: 'flex', 8 | }, 9 | container: { 10 | paddingTop: theme.spacing(3), 11 | paddingBottom: theme.spacing(3), 12 | [theme.breakpoints.up('sm')]: { 13 | display: 'flex', 14 | height: '100vh', 15 | alignItems: 'center', 16 | }, 17 | }, 18 | })); 19 | 20 | interface UnauthenticatedContainerProps { 21 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 22 | children: any; 23 | } 24 | 25 | export const UnauthenticatedContainer = ({ children }: UnauthenticatedContainerProps) => { 26 | const classes = useStyles(); 27 | 28 | return ( 29 |
30 | 31 | {children} 32 | 33 |
34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | import reportWebVitals from './reportWebVitals'; 5 | 6 | ReactDOM.createRoot(document.getElementById('root')!).render( 7 | 8 | 9 | 10 | ); 11 | 12 | // If you want to start measuring performance in your app, pass a function 13 | // to log results (for example: reportWebVitals(console.log)) 14 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 15 | reportWebVitals(); 16 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /examples/react-rest-typescript/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | resolve: { 8 | preserveSymlinks: true, 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /examples/rest-express-typescript-without-modules/README.md: -------------------------------------------------------------------------------- 1 | # rest-express-typescript 2 | 3 | This example demonstrate how to use [accounts-js](https://github.com/accounts-js/accounts). 4 | 5 | You must have a mongodb server running before starting the server. 6 | 7 | ## Setup example 8 | 9 | In order to be able to run this example on your machine you first need to do the following steps: 10 | 11 | - Clone the repository `git clone git@github.com:accounts-js/accounts.git` 12 | - Install project dependencies: `yarn install` 13 | - Compile the packages `yarn run compile` 14 | - Go to the example folder `cd examples/rest-express-typescript` 15 | 16 | ## Getting Started 17 | 18 | Start the app. 19 | 20 | ``` 21 | yarn run start 22 | ``` 23 | 24 | Open a browser and navigate to [http://localhost:4000](http://localhost:4000). 25 | -------------------------------------------------------------------------------- /examples/rest-express-typescript-without-modules/now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "rest-express-typescript", 4 | "builds": [ 5 | { 6 | "src": "lib/index.js", 7 | "use": "@now/node-server" 8 | } 9 | ], 10 | "routes": [ 11 | { 12 | "src": ".*", 13 | "dest": "/lib/index.js" 14 | } 15 | ], 16 | "env": { 17 | "MONGO_URL": "@accounts-js-rest-express" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/rest-express-typescript-without-modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/rest-express-typescript-without-modules", 3 | "private": true, 4 | "version": "0.32.0", 5 | "main": "lib/index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts", 9 | "build": "yarn run -T tsc", 10 | "test": "yarn run build" 11 | }, 12 | "dependencies": { 13 | "@accounts/mongo": "^0.34.1", 14 | "@accounts/password": "^0.32.2", 15 | "@accounts/rest-express": "^0.33.1", 16 | "@accounts/server": "^0.33.1", 17 | "body-parser": "1.20.2", 18 | "cors": "2.8.5", 19 | "express": "4.18.3", 20 | "mongoose": "8.2.1", 21 | "tslib": "2.6.2" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/rest-express-typescript-without-modules/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "skipLibCheck": true, 9 | "isolatedModules": true, 10 | "esModuleInterop": true 11 | }, 12 | "include": ["./src/**/*"] 13 | } 14 | -------------------------------------------------------------------------------- /examples/rest-express-typescript/README.md: -------------------------------------------------------------------------------- 1 | # rest-express-typescript 2 | 3 | This example demonstrate how to use [accounts-js](https://github.com/accounts-js/accounts). 4 | 5 | You must have a mongodb server running before starting the server. 6 | 7 | ## Setup example 8 | 9 | In order to be able to run this example on your machine you first need to do the following steps: 10 | 11 | - Clone the repository `git clone git@github.com:accounts-js/accounts.git` 12 | - Install project dependencies: `yarn install` 13 | - Compile the packages `yarn run compile` 14 | - Go to the example folder `cd examples/rest-express-typescript` 15 | 16 | ## Getting Started 17 | 18 | Start the app. 19 | 20 | ``` 21 | yarn run start 22 | ``` 23 | 24 | Open a browser and navigate to [http://localhost:4000](http://localhost:4000). 25 | -------------------------------------------------------------------------------- /examples/rest-express-typescript/now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "rest-express-typescript", 4 | "builds": [ 5 | { 6 | "src": "lib/index.js", 7 | "use": "@now/node-server" 8 | } 9 | ], 10 | "routes": [ 11 | { 12 | "src": ".*", 13 | "dest": "/lib/index.js" 14 | } 15 | ], 16 | "env": { 17 | "MONGO_URL": "@accounts-js-rest-express" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/rest-express-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@examples/rest-express-typescript", 3 | "private": true, 4 | "version": "0.32.0", 5 | "main": "lib/index.js", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "NODE_ENV=development yarn run -T nodemon -w src -x ts-node src/index.ts", 9 | "build": "yarn run -T tsc", 10 | "test": "yarn run build" 11 | }, 12 | "dependencies": { 13 | "@accounts/module-core": "^0.34.0", 14 | "@accounts/module-mongo": "^0.34.0", 15 | "@accounts/module-password": "^0.34.0", 16 | "@accounts/mongo": "^0.34.1", 17 | "@accounts/password": "^0.32.2", 18 | "@accounts/rest-express": "^0.33.1", 19 | "@accounts/server": "^0.33.1", 20 | "body-parser": "1.20.2", 21 | "cors": "2.8.5", 22 | "express": "4.18.3", 23 | "mongoose": "8.2.1", 24 | "tslib": "2.6.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/rest-express-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./lib", 4 | "target": "es5", 5 | "lib": ["es2015", "esnext.asynciterable"], 6 | "sourceMap": true, 7 | "importHelpers": true, 8 | "skipLibCheck": true, 9 | "isolatedModules": true, 10 | "esModuleInterop": true 11 | }, 12 | "include": ["./src/**/*"] 13 | } 14 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "version": "0.32.0" 4 | } 5 | -------------------------------------------------------------------------------- /modules/module-core/__tests__/resolvers/query.ts: -------------------------------------------------------------------------------- 1 | import { Query } from '../../src/resolvers/query'; 2 | 3 | describe('accounts resolvers query', () => { 4 | const user = { id: 'idTest' }; 5 | 6 | describe('getUser', () => { 7 | it('should return null if context is empty', async () => { 8 | const res = await Query.getUser!({}, {}, {} as any, {} as any); 9 | expect(res).toBeNull(); 10 | }); 11 | 12 | it('should return user', async () => { 13 | const res = await Query.getUser!({}, {}, { user } as any, {} as any); 14 | expect(res).toEqual(user); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /modules/module-core/__tests__/utils/authenticated-resolver.ts: -------------------------------------------------------------------------------- 1 | import { authenticated } from '../../src/utils/authenticated-resolver'; 2 | 3 | describe('authenticated-resolver', () => { 4 | it('should throw if no user in context', async () => { 5 | const spy = jest.fn(); 6 | await expect(authenticated(spy)({}, {}, {}, {})).rejects.toThrow('Unauthorized'); 7 | expect(spy).not.toHaveBeenCalled(); 8 | }); 9 | 10 | it('should call spy if user is in the context', async () => { 11 | const spy = jest.fn(); 12 | await authenticated(spy)({}, {}, { userId: 'userId', user: {} }, {}); 13 | expect(spy).toHaveBeenCalled(); 14 | }); 15 | 16 | it('should call spy if no user and skipJSAccountsVerification is true', async () => { 17 | const spy = jest.fn(); 18 | await authenticated(spy)({}, {}, { skipJSAccountsVerification: true }, {}); 19 | expect(spy).toHaveBeenCalled(); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /modules/module-core/codegen.yml: -------------------------------------------------------------------------------- 1 | overwrite: true 2 | schema: ./src/schema.ts 3 | require: ts-node/register/transpile-only 4 | generates: 5 | introspection.json: 6 | plugins: 7 | - introspection 8 | config: 9 | minify: true 10 | ./src/models.ts: 11 | config: 12 | noNamespaces: true 13 | noSchemaStitching: true 14 | makeResolverTypeCallable: true 15 | contextType: ./#AccountsContextGraphQLModules 16 | plugins: 17 | - add: 18 | content: '/* eslint-disable */' 19 | - typescript 20 | - typescript-resolvers 21 | - typescript-operations 22 | -------------------------------------------------------------------------------- /modules/module-core/src/resolvers/query.ts: -------------------------------------------------------------------------------- 1 | import { type QueryResolvers } from '../models'; 2 | 3 | export const Query: QueryResolvers = { 4 | getUser: (_, __, context) => context.user || null, 5 | }; 6 | -------------------------------------------------------------------------------- /modules/module-core/src/schema.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { createApplication } from 'graphql-modules'; 3 | import { createAccountsCoreModule } from '.'; 4 | import { 5 | AuthenticationServicesToken, 6 | DatabaseInterfaceUserToken, 7 | DatabaseInterfaceSessionsToken, 8 | } from '@accounts/server'; 9 | 10 | const { schema } = createApplication({ 11 | modules: [createAccountsCoreModule({ tokenSecret: 'my-secret' })], 12 | providers: [ 13 | { 14 | provide: DatabaseInterfaceUserToken, 15 | useValue: {}, 16 | }, 17 | { 18 | provide: DatabaseInterfaceSessionsToken, 19 | useValue: {}, 20 | }, 21 | { 22 | provide: AuthenticationServicesToken, 23 | useValue: {}, 24 | global: true, 25 | }, 26 | ], 27 | }); 28 | 29 | export default schema; 30 | -------------------------------------------------------------------------------- /modules/module-core/src/schema/mutation.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ 4 | rootMutationName, 5 | extendTypeDefs = false, 6 | }: { 7 | rootMutationName?: string; 8 | extendTypeDefs?: boolean; 9 | }) => gql` 10 | ${extendTypeDefs ? 'extend' : ''} type ${rootMutationName || 'Mutation'} { 11 | impersonate(accessToken: String!, impersonated: ImpersonationUserIdentityInput!): ImpersonateReturn 12 | refreshTokens(accessToken: String!, refreshToken: String!): LoginResult 13 | logout: Boolean 14 | 15 | # Example: Login with password 16 | # authenticate(serviceName: "password", params: {password: "", user: {email: ""}}) 17 | authenticate(serviceName: String!, params: AuthenticateParamsInput!): LoginResult 18 | verifyAuthentication(serviceName: String!, params: AuthenticateParamsInput!): Boolean 19 | } 20 | `; 21 | -------------------------------------------------------------------------------- /modules/module-core/src/schema/query.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ 4 | rootQueryName, 5 | extendTypeDefs = false, 6 | }: { 7 | rootQueryName?: string; 8 | extendTypeDefs?: boolean; 9 | }) => gql` 10 | ${extendTypeDefs ? 'extend' : ''} type ${rootQueryName || 'Query'} { 11 | getUser: User 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /modules/module-core/src/schema/schema-def.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ 4 | rootQueryName, 5 | rootMutationName, 6 | withSchemaDefinition, 7 | }: { 8 | rootQueryName?: string; 9 | rootMutationName?: string; 10 | withSchemaDefinition?: boolean; 11 | }) => 12 | withSchemaDefinition 13 | ? [ 14 | gql` 15 | schema { 16 | query: ${rootMutationName || 'Query'} 17 | mutation: ${rootQueryName || 'Mutation'} 18 | } 19 | `, 20 | ] 21 | : []; 22 | -------------------------------------------------------------------------------- /modules/module-core/src/schema/schema.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ userAsInterface }: { userAsInterface?: boolean }) => gql` 4 | ${userAsInterface ? 'interface' : 'type'} User { 5 | id: ID! 6 | emails: [EmailRecord!] 7 | username: String 8 | } 9 | 10 | type EmailRecord { 11 | address: String 12 | verified: Boolean 13 | } 14 | 15 | type Tokens { 16 | refreshToken: String 17 | accessToken: String 18 | } 19 | 20 | type LoginResult { 21 | sessionId: String 22 | tokens: Tokens 23 | user: User 24 | } 25 | `; 26 | -------------------------------------------------------------------------------- /modules/module-core/src/schema/types.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default gql` 4 | type ImpersonateReturn { 5 | authorized: Boolean 6 | tokens: Tokens 7 | user: User 8 | } 9 | 10 | input UserInput { 11 | id: ID 12 | email: String 13 | username: String 14 | } 15 | 16 | input AuthenticateParamsInput { 17 | # Twitter, Instagram 18 | access_token: String 19 | # Twitter 20 | access_token_secret: String 21 | # OAuth 22 | provider: String 23 | # Password 24 | password: String 25 | # Password 26 | user: UserInput 27 | # Two factor 28 | code: String 29 | # Token 30 | token: String 31 | } 32 | 33 | input ImpersonationUserIdentityInput { 34 | userId: String 35 | username: String 36 | email: String 37 | } 38 | `; 39 | -------------------------------------------------------------------------------- /modules/module-core/src/utils/authenticated-resolver.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLError } from 'graphql'; 2 | 3 | export const authenticated = 4 | < 5 | CustomRoot, 6 | CustomArgs, 7 | CustomContext extends { skipJSAccountsVerification?: Boolean; userId?: any; user?: any }, 8 | Info, 9 | ReturnType, 10 | >( 11 | func: ( 12 | root: CustomRoot, 13 | args: CustomArgs, 14 | context: CustomContext, 15 | info: Info 16 | ) => ReturnType | Promise 17 | ) => 18 | async (root: CustomRoot, args: CustomArgs, context: CustomContext, info: Info) => { 19 | if (context && context.skipJSAccountsVerification === true) { 20 | return func(root, args, context, info); 21 | } 22 | if (!context.userId && !context.user) { 23 | throw new GraphQLError('Unauthorized', { 24 | extensions: { 25 | code: 'UNAUTHENTICATED', 26 | http: { status: 401 }, 27 | }, 28 | }); 29 | } 30 | return func(root, args, context, info); 31 | }; 32 | -------------------------------------------------------------------------------- /modules/module-core/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './authenticated-directive'; 2 | export * from './authenticated-resolver'; 3 | export * from './context-builder'; 4 | export * from './schema-builder'; 5 | -------------------------------------------------------------------------------- /modules/module-core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /modules/module-magic-link/codegen.yml: -------------------------------------------------------------------------------- 1 | overwrite: true 2 | schema: ./src/schema.ts 3 | require: ts-node/register/transpile-only 4 | generates: 5 | introspection.json: 6 | plugins: 7 | - introspection 8 | config: 9 | minify: true 10 | ./src/models.ts: 11 | config: 12 | noNamespaces: true 13 | noSchemaStitching: true 14 | makeResolverTypeCallable: true 15 | contextType: '@accounts/module-core#AccountsContextGraphQLModules' 16 | plugins: 17 | - add: 18 | content: '/* eslint-disable */' 19 | - typescript 20 | - typescript-resolvers 21 | - typescript-operations 22 | -------------------------------------------------------------------------------- /modules/module-magic-link/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccountsMagicLink, 3 | type AccountsMagicLinkOptions, 4 | AccountsMagicLinkConfigToken, 5 | } from '@accounts/magic-link'; 6 | import { createModule } from 'graphql-modules'; 7 | import getMutationTypeDefs from './schema/mutation'; 8 | import { Mutation } from './resolvers/mutation'; 9 | 10 | export * from './models'; 11 | 12 | export interface AccountsMagicLinkModuleConfig extends AccountsMagicLinkOptions { 13 | rootMutationName?: string; 14 | extendTypeDefs?: boolean; 15 | } 16 | 17 | export const createAccountsMagicLinkModule = (config: AccountsMagicLinkModuleConfig = {}) => 18 | createModule({ 19 | id: 'accounts-magic-link', 20 | typeDefs: [getMutationTypeDefs(config)], 21 | resolvers: { 22 | [config.rootMutationName || 'Mutation']: Mutation, 23 | }, 24 | providers: [ 25 | { 26 | provide: AccountsMagicLinkConfigToken, 27 | useValue: config, 28 | }, 29 | AccountsMagicLink, 30 | ], 31 | }); 32 | -------------------------------------------------------------------------------- /modules/module-magic-link/src/resolvers/mutation.ts: -------------------------------------------------------------------------------- 1 | import { AccountsMagicLink, RequestMagicLinkEmailErrors } from '@accounts/magic-link'; 2 | import { AccountsServer, AccountsJsError } from '@accounts/server'; 3 | import { type MutationResolvers } from '../models'; 4 | 5 | export const Mutation: MutationResolvers = { 6 | requestMagicLinkEmail: async (_, { email }, ctx) => { 7 | const { injector } = ctx; 8 | const accountsServer = injector.get(AccountsServer); 9 | const accountsMagicLink = injector.get(AccountsMagicLink); 10 | 11 | try { 12 | await accountsMagicLink.requestMagicLinkEmail(email); 13 | } catch (error) { 14 | // If ambiguousErrorMessages is true, 15 | // to prevent user enumeration we fail silently in case there is no user attached to this email 16 | if ( 17 | accountsServer.options.ambiguousErrorMessages && 18 | error instanceof AccountsJsError && 19 | error.code === RequestMagicLinkEmailErrors.UserNotFound 20 | ) { 21 | return null; 22 | } 23 | throw error; 24 | } 25 | 26 | return null; 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /modules/module-magic-link/src/schema.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { createApplication } from 'graphql-modules'; 3 | import { createAccountsCoreModule } from '@accounts/module-core'; 4 | import { 5 | AuthenticationServicesToken, 6 | DatabaseInterfaceUserToken, 7 | DatabaseInterfaceSessionsToken, 8 | } from '@accounts/server'; 9 | import { createAccountsMagicLinkModule } from '.'; 10 | 11 | const { schema } = createApplication({ 12 | modules: [ 13 | createAccountsCoreModule({ tokenSecret: 'my-secret' }), 14 | createAccountsMagicLinkModule(), 15 | ], 16 | providers: [ 17 | { 18 | provide: DatabaseInterfaceUserToken, 19 | useValue: {}, 20 | }, 21 | { 22 | provide: DatabaseInterfaceSessionsToken, 23 | useValue: {}, 24 | }, 25 | { 26 | provide: AuthenticationServicesToken, 27 | useValue: {}, 28 | global: true, 29 | }, 30 | ], 31 | }); 32 | 33 | export default schema; 34 | -------------------------------------------------------------------------------- /modules/module-magic-link/src/schema/mutation.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ 4 | rootMutationName, 5 | extendTypeDefs = true, 6 | }: { 7 | rootMutationName?: string; 8 | extendTypeDefs?: boolean; 9 | }) => gql` 10 | ${extendTypeDefs ? 'extend' : ''} type ${rootMutationName || 'Mutation'} { 11 | requestMagicLinkEmail(email: String!): Boolean 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /modules/module-magic-link/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /modules/module-mikro-orm/src/types/IContext.ts: -------------------------------------------------------------------------------- 1 | import { type IContext as AccountsContext } from '@accounts/types'; 2 | import { type Connection, type EntityManager, type IDatabaseDriver } from '@mikro-orm/core'; 3 | import { type IUser } from '@accounts/mikro-orm'; 4 | 5 | export interface IContext = IUser> 6 | extends Omit { 7 | user?: User; 8 | em?: EntityManager>; 9 | } 10 | -------------------------------------------------------------------------------- /modules/module-mikro-orm/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './IContext'; 2 | -------------------------------------------------------------------------------- /modules/module-mikro-orm/src/utils/context-builder.ts: -------------------------------------------------------------------------------- 1 | import { type IUser } from '@accounts/mikro-orm'; 2 | import { context as contextBase } from '@accounts/module-core'; 3 | import { type Connection, type EntityManager, type IDatabaseDriver } from '@mikro-orm/core'; 4 | import { type IContext } from '../types'; 5 | 6 | export const context = async < 7 | User extends IUser = IUser, 8 | Ctx extends { em?: EntityManager> } = object, 9 | >( 10 | ...args: Parameters, Ctx>> 11 | ): ReturnType, Ctx>> => contextBase(...args); 12 | -------------------------------------------------------------------------------- /modules/module-mikro-orm/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './context-builder'; 2 | -------------------------------------------------------------------------------- /modules/module-mikro-orm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /modules/module-mongo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /modules/module-password/codegen.yml: -------------------------------------------------------------------------------- 1 | overwrite: true 2 | schema: ./src/schema.ts 3 | require: ts-node/register/transpile-only 4 | generates: 5 | introspection.json: 6 | plugins: 7 | - introspection 8 | config: 9 | minify: true 10 | ./src/models.ts: 11 | config: 12 | noNamespaces: true 13 | noSchemaStitching: true 14 | makeResolverTypeCallable: true 15 | contextType: '@accounts/module-core#AccountsContextGraphQLModules' 16 | plugins: 17 | - add: 18 | content: '/* eslint-disable */' 19 | - typescript 20 | - typescript-resolvers 21 | - typescript-operations 22 | -------------------------------------------------------------------------------- /modules/module-password/src/resolvers/query.ts: -------------------------------------------------------------------------------- 1 | import { GraphQLError } from 'graphql'; 2 | import { type QueryResolvers } from '../models'; 3 | import { AccountsPassword } from '@accounts/password'; 4 | 5 | export const Query: QueryResolvers = { 6 | twoFactorSecret: async (_, args, ctx) => { 7 | const { user, injector } = ctx; 8 | 9 | // Make sure user is logged in 10 | if (!(user && user.id)) { 11 | throw new GraphQLError('Unauthorized', { 12 | extensions: { 13 | code: 'UNAUTHENTICATED', 14 | http: { status: 401 }, 15 | }, 16 | }); 17 | } 18 | 19 | // https://github.com/speakeasyjs/speakeasy/blob/master/index.js#L517 20 | const secret = injector.get(AccountsPassword).twoFactor.getNewAuthSecret(); 21 | return secret; 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /modules/module-password/src/schema.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import { createApplication } from 'graphql-modules'; 3 | import { createAccountsCoreModule } from '@accounts/module-core'; 4 | import { 5 | AuthenticationServicesToken, 6 | DatabaseInterfaceUserToken, 7 | DatabaseInterfaceSessionsToken, 8 | } from '@accounts/server'; 9 | import { createAccountsPasswordModule } from '.'; 10 | 11 | const { schema } = createApplication({ 12 | modules: [createAccountsCoreModule({ tokenSecret: 'my-secret' }), createAccountsPasswordModule()], 13 | providers: [ 14 | { 15 | provide: DatabaseInterfaceUserToken, 16 | useValue: {}, 17 | }, 18 | { 19 | provide: DatabaseInterfaceSessionsToken, 20 | useValue: {}, 21 | }, 22 | { 23 | provide: AuthenticationServicesToken, 24 | useValue: {}, 25 | global: true, 26 | }, 27 | ], 28 | }); 29 | 30 | export default schema; 31 | -------------------------------------------------------------------------------- /modules/module-password/src/schema/mutation.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ 4 | rootMutationName, 5 | extendTypeDefs = true, 6 | }: { 7 | rootMutationName?: string; 8 | extendTypeDefs?: boolean; 9 | }) => gql` 10 | ${extendTypeDefs ? 'extend' : ''} type ${rootMutationName || 'Mutation'} { 11 | # Creates a user with a password, returns the id corresponding db ids, such as number IDs, ObjectIDs or UUIDs 12 | createUser(user: CreateUserInput!): CreateUserResult 13 | verifyEmail(token: String!): Boolean 14 | resetPassword(token: String!, newPassword: String!): LoginResult 15 | sendVerificationEmail(email: String!): Boolean 16 | sendResetPasswordEmail(email: String!): Boolean 17 | addEmail(newEmail: String!): Boolean 18 | changePassword(oldPassword: String!, newPassword: String!): Boolean 19 | twoFactorSet(secret: TwoFactorSecretKeyInput!, code: String!): Boolean 20 | twoFactorUnset(code: String!): Boolean 21 | } 22 | `; 23 | -------------------------------------------------------------------------------- /modules/module-password/src/schema/query.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default ({ 4 | rootQueryName, 5 | extendTypeDefs = true, 6 | }: { 7 | rootQueryName?: string; 8 | extendTypeDefs?: boolean; 9 | }) => gql` 10 | ${extendTypeDefs ? 'extend' : ''} type ${rootQueryName || 'Query'} { 11 | twoFactorSecret: TwoFactorSecretKey 12 | } 13 | `; 14 | -------------------------------------------------------------------------------- /modules/module-password/src/schema/types.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export default gql` 4 | type CreateUserResult { 5 | # Will be returned only if ambiguousErrorMessages is set to false or requireEmailVerification is set to false. 6 | userId: ID 7 | # Will be returned only if enableAutologin is set to true and requireEmailVerification is set to false. 8 | loginResult: LoginResult 9 | } 10 | 11 | type TwoFactorSecretKey { 12 | ascii: String 13 | base32: String 14 | hex: String 15 | qr_code_ascii: String 16 | qr_code_hex: String 17 | qr_code_base32: String 18 | google_auth_qr: String 19 | otpauth_url: String 20 | } 21 | 22 | input TwoFactorSecretKeyInput { 23 | ascii: String 24 | base32: String 25 | hex: String 26 | qr_code_ascii: String 27 | qr_code_hex: String 28 | qr_code_base32: String 29 | google_auth_qr: String 30 | otpauth_url: String 31 | } 32 | 33 | input CreateUserInput { 34 | username: String 35 | email: String 36 | password: String 37 | } 38 | `; 39 | -------------------------------------------------------------------------------- /modules/module-password/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /modules/module-typeorm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | base = "." 3 | publish = "website/build" 4 | command = "yarn install && yarn workspace accounts-js run build" 5 | 6 | [build.environment] 7 | NODE_VERSION = "18" 8 | NPM_FLAGS = "--version" 9 | -------------------------------------------------------------------------------- /packages/apollo-link-accounts/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/apollo-link 2 | 3 | ## 0.32.1 4 | ### Patch Changes 5 | 6 | 7 | 8 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 9 | -------------------------------------------------------------------------------- /packages/apollo-link-accounts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@accounts/apollo-link", 3 | "version": "0.32.1", 4 | "description": "Apollo link for account-js", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "scripts": { 11 | "clean": "yarn run -T rimraf lib", 12 | "start": "yarn run -T tsc --watch", 13 | "precompile": "yarn run clean", 14 | "compile": "yarn run -T tsc", 15 | "prepublishOnly": "yarn run compile" 16 | }, 17 | "files": [ 18 | "src", 19 | "lib" 20 | ], 21 | "repository": { 22 | "type": "git", 23 | "url": "https://github.com/accounts-js/accounts/tree/master/packages/apollo-link" 24 | }, 25 | "license": "MIT", 26 | "peerDependencies": { 27 | "@apollo/client": "^3.0.0", 28 | "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0" 29 | }, 30 | "dependencies": { 31 | "tslib": "2.6.2" 32 | }, 33 | "devDependencies": { 34 | "@accounts/client": "^0.33.1", 35 | "@apollo/client": "3.9.6", 36 | "graphql": "16.8.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/apollo-link-accounts/src/index.ts: -------------------------------------------------------------------------------- 1 | import { type ApolloLink } from '@apollo/client/core'; 2 | import { setContext } from '@apollo/client/link/context'; 3 | import { type AccountsClient } from '@accounts/client'; 4 | 5 | type AccountsClientFactory = () => AccountsClient | Promise; 6 | 7 | export const accountsLink = (accountsClientFactory: AccountsClientFactory): ApolloLink => { 8 | return setContext(async (req, { headers: headersWithoutTokens }) => { 9 | const accountsClient = await accountsClientFactory(); 10 | const headers = { ...headersWithoutTokens }; 11 | 12 | /** 13 | * We have to check this condition to avoid an infinite loop 14 | * during the refresh token operation 15 | */ 16 | if (req.operationName !== 'refreshTokens') { 17 | const tokens = await accountsClient.refreshSession(); 18 | if (tokens) { 19 | headers.Authorization = 'Bearer ' + tokens.accessToken; 20 | } 21 | } 22 | 23 | return { 24 | headers, 25 | }; 26 | }); 27 | }; 28 | -------------------------------------------------------------------------------- /packages/apollo-link-accounts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true, 6 | "target": "es5", 7 | "lib": ["es2019", "dom"] 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/client-magic-link/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/client-magic-link 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/client-magic-link)](https://www.npmjs.com/package/@accounts/client-magic-link) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/client-magic-link)](https://www.npmjs.com/package/@accounts/client-magic-link) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/strategies/magic-link-client) 11 | - [API documentation](https://www.accountsjs.com/docs/api/client-magic-link/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/client-magic-link 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/client-magic-link/src/client-magic-link.ts: -------------------------------------------------------------------------------- 1 | import { type AccountsClient } from '@accounts/client'; 2 | import { type LoginResult, type LoginUserMagicLinkService } from '@accounts/types'; 3 | 4 | export class AccountsClientMagicLink { 5 | private client: AccountsClient; 6 | 7 | constructor(client: AccountsClient) { 8 | if (!client) { 9 | throw new Error('A valid client instance is required'); 10 | } 11 | this.client = client; 12 | } 13 | 14 | /** 15 | * Log the user in with a token. 16 | */ 17 | public async login(user: LoginUserMagicLinkService): Promise { 18 | return this.client.loginWithService('magic-link', user); 19 | } 20 | 21 | /** 22 | * Request a new login link. 23 | * @param {string} email - The email address to send a login link. 24 | */ 25 | public requestMagicLinkEmail(email: string): Promise { 26 | return this.client.transport.requestMagicLinkEmail(email); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/client-magic-link/src/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountsClientMagicLink } from './client-magic-link'; 2 | -------------------------------------------------------------------------------- /packages/client-magic-link/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true, 6 | "target": "es5" 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/client-password/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/client-password 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 8 | 9 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 10 | - @accounts/client@0.33.1 11 | - @accounts/types@0.33.1 12 | 13 | ## 0.32.1 14 | 15 | ### Patch Changes 16 | 17 | - Updated dependencies [[`22056642`](https://github.com/accounts-js/accounts/commit/220566425755a7015569d8e518095701ff7122e2)]: 18 | - @accounts/client@0.33.0 19 | - @accounts/types@0.33.0 20 | -------------------------------------------------------------------------------- /packages/client-password/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/client-password 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/client-password)](https://www.npmjs.com/package/@accounts/client-password) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/client-password)](https://www.npmjs.com/package/@accounts/client-password) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/strategies/password-client) 11 | - [API documentation](https://www.accountsjs.com/docs/api/client-password/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/client-password 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/client-password/src/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountsClientPassword } from './client-password'; 2 | -------------------------------------------------------------------------------- /packages/client-password/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './options'; 2 | -------------------------------------------------------------------------------- /packages/client-password/src/types/options.ts: -------------------------------------------------------------------------------- 1 | export interface AccountsClientPasswordOptions { 2 | /** 3 | * Use this option if you want to customize the hashing method. 4 | * By default accounts-js will hash the password using SHA256. 5 | */ 6 | hashPassword?(password: string): string; 7 | } 8 | -------------------------------------------------------------------------------- /packages/client-password/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true, 6 | "target": "es5" 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/client/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/client 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/client)](https://www.npmjs.com/package/@accounts/client) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/client)](https://www.npmjs.com/package/@accounts/client) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | Client library to interact with an accounts-js server. 9 | 10 | ## Documentation 11 | 12 | - [API documentation](https://www.accountsjs.com/docs/api/client/globals) 13 | 14 | ## Installation 15 | 16 | ``` 17 | yarn add @accounts/client 18 | ``` 19 | 20 | ## Contributing 21 | 22 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 23 | -------------------------------------------------------------------------------- /packages/client/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import { jwtDecode } from 'jwt-decode'; 2 | import { isTokenExpired } from '../src/utils'; 3 | 4 | jest.mock('jwt-decode'); 5 | 6 | describe('utils', () => { 7 | afterEach(() => { 8 | jest.clearAllMocks(); 9 | }); 10 | 11 | describe('isTokenExpired', () => { 12 | it('return true if token is expired', () => { 13 | (jwtDecode as jest.Mock).mockImplementationOnce(() => ({ 14 | exp: 1, 15 | })); 16 | const res = isTokenExpired('token'); 17 | expect(res).toBeTruthy(); 18 | expect(jwtDecode).toHaveBeenCalledWith('token'); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /packages/client/src/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountsClient } from './accounts-client'; 2 | export { AccountsClientOptions } from './types'; 3 | export { TransportInterface } from './transport-interface'; 4 | -------------------------------------------------------------------------------- /packages/client/src/token-storage-local.ts: -------------------------------------------------------------------------------- 1 | import { type TokenStorage } from './types'; 2 | 3 | export const tokenStorageLocal: TokenStorage = { 4 | setItem(key: string, value: string): void { 5 | return localStorage.setItem(key, value); 6 | }, 7 | 8 | getItem(key: string): string | null { 9 | return localStorage.getItem(key); 10 | }, 11 | 12 | removeItem(key: string): void { 13 | return localStorage.removeItem(key); 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/client/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountsClientOptions } from './options'; 2 | export { TokenStorage } from './token-storage'; 3 | -------------------------------------------------------------------------------- /packages/client/src/types/options.ts: -------------------------------------------------------------------------------- 1 | import { type TokenStorage } from '.'; 2 | 3 | export interface AccountsClientOptions { 4 | /** 5 | * Storage that accounts-js will use to store the tokens. 6 | * Default: 'localStorage'. 7 | */ 8 | tokenStorage?: TokenStorage; 9 | /** 10 | * Token that will prefix the storage key. 11 | * Default: 'accounts'. 12 | */ 13 | tokenStoragePrefix?: string; 14 | /** 15 | * Token that will separate the storage key and value. 16 | * Default: ':'. 17 | */ 18 | tokenStorageSeparator?: string; 19 | } 20 | -------------------------------------------------------------------------------- /packages/client/src/types/token-storage.ts: -------------------------------------------------------------------------------- 1 | type ValueOrPromise = T | Promise; 2 | 3 | export interface TokenStorage { 4 | setItem(key: string, value: string): ValueOrPromise; 5 | getItem(key: string): ValueOrPromise; 6 | removeItem(key: string): ValueOrPromise; 7 | } 8 | -------------------------------------------------------------------------------- /packages/client/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { jwtDecode } from 'jwt-decode'; 2 | 3 | interface JwtDecodeData { 4 | exp: number; 5 | iat: number; 6 | } 7 | 8 | export const isTokenExpired = (token: string): boolean => { 9 | const currentTime = Date.now() / 1000; 10 | const decodedToken = jwtDecode(token); 11 | return decodedToken.exp < currentTime; 12 | }; 13 | -------------------------------------------------------------------------------- /packages/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true, 6 | "target": "es5", 7 | "lib": ["es2019", "dom"] 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/database-mikro-orm/src/types/Email.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type Email } from '../entity/Email'; 3 | 4 | export const EmailToken = new InjectionToken>('EmailToken'); 5 | -------------------------------------------------------------------------------- /packages/database-mikro-orm/src/types/Service.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type Service } from '../entity/Service'; 3 | 4 | export const ServiceToken = new InjectionToken>('ServiceToken'); 5 | -------------------------------------------------------------------------------- /packages/database-mikro-orm/src/types/Session.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type Session } from '../entity/Session'; 3 | 4 | export const SessionToken = new InjectionToken>('SessionToken'); 5 | -------------------------------------------------------------------------------- /packages/database-mikro-orm/src/types/User.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type IUser } from '../entity/User'; 3 | 4 | export const UserToken = new InjectionToken>('UserToken'); 5 | -------------------------------------------------------------------------------- /packages/database-mikro-orm/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './User.symbol'; 2 | export * from './Email.symbol'; 3 | export * from './Service.symbol'; 4 | export * from './Session.symbol'; 5 | -------------------------------------------------------------------------------- /packages/database-mikro-orm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "rootDir": "./src", 7 | "outDir": "./lib", 8 | "importHelpers": true 9 | }, 10 | "exclude": ["node_modules", "__tests__", "lib"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/database-mongo-magic-link/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import { ObjectId } from 'mongodb'; 2 | import { toMongoID } from '../src/utils'; 3 | 4 | describe('toMongoID', () => { 5 | it('should convert to ObjectId if param is a string', () => { 6 | expect(typeof toMongoID('589871d1c9393d445745a57c')).toBe('object'); 7 | }); 8 | 9 | it('should do nothing if passing an ObjectId', () => { 10 | const id = new ObjectId('589871d1c9393d445745a57c'); 11 | expect(toMongoID(new ObjectId('589871d1c9393d445745a57c'))).toEqual(id); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/database-mongo-magic-link/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mongo-magic-link'; 2 | -------------------------------------------------------------------------------- /packages/database-mongo-magic-link/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { ObjectId } from 'mongodb'; 2 | 3 | export const toMongoID = (objectId: string | ObjectId) => { 4 | if (typeof objectId === 'string') { 5 | return new ObjectId(objectId); 6 | } 7 | return objectId; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/database-mongo-magic-link/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/database-mongo-password/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import { ObjectId } from 'mongodb'; 2 | import { toMongoID } from '../src/utils'; 3 | 4 | describe('toMongoID', () => { 5 | it('should convert to ObjectId if param is a string', () => { 6 | expect(typeof toMongoID('589871d1c9393d445745a57c')).toBe('object'); 7 | }); 8 | 9 | it('should do nothing if passing an ObjectId', () => { 10 | const id = new ObjectId('589871d1c9393d445745a57c'); 11 | expect(toMongoID(new ObjectId('589871d1c9393d445745a57c'))).toEqual(id); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/database-mongo-password/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mongo-password'; 2 | -------------------------------------------------------------------------------- /packages/database-mongo-password/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { ObjectId } from 'mongodb'; 2 | 3 | export const toMongoID = (objectId: string | ObjectId) => { 4 | if (typeof objectId === 'string') { 5 | return new ObjectId(objectId); 6 | } 7 | return objectId; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/database-mongo-password/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/database-mongo-sessions/__tests__/utils.ts: -------------------------------------------------------------------------------- 1 | import { ObjectId } from 'mongodb'; 2 | import { toMongoID } from '../src/utils'; 3 | 4 | describe('toMongoID', () => { 5 | it('should convert to ObjectId if param is a string', () => { 6 | expect(typeof toMongoID('589871d1c9393d445745a57c')).toBe('object'); 7 | }); 8 | 9 | it('should do nothing if passing an ObjectId', () => { 10 | const id = new ObjectId('589871d1c9393d445745a57c'); 11 | expect(toMongoID(new ObjectId('589871d1c9393d445745a57c'))).toEqual(id); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/database-mongo-sessions/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './mongo-sessions'; 2 | -------------------------------------------------------------------------------- /packages/database-mongo-sessions/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { ObjectId } from 'mongodb'; 2 | 3 | export const toMongoID = (objectId: string | ObjectId) => { 4 | if (typeof objectId === 'string') { 5 | return new ObjectId(objectId); 6 | } 7 | return objectId; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/database-mongo-sessions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/database-mongo/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/mongo 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/mongo)](https://www.npmjs.com/package/@accounts/mongo) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/mongo)](https://www.npmjs.com/package/@accounts/mongo) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | A accounts-js database adapter for [MongoDB](https://www.mongodb.com/) 9 | 10 | ## Documentation 11 | 12 | - [Website documentation](https://www.accountsjs.com/docs/databases/mongo) 13 | - [API documentation](https://www.accountsjs.com/docs/api/database-mongo/globals) 14 | 15 | ## Installation 16 | 17 | ``` 18 | yarn add @accounts/mongo 19 | ``` 20 | 21 | ## Contributing 22 | 23 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 24 | -------------------------------------------------------------------------------- /packages/database-mongo/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Mongo } from './mongo'; 2 | 3 | export * from './types'; 4 | 5 | export { Mongo }; 6 | export default Mongo; 7 | -------------------------------------------------------------------------------- /packages/database-mongo/src/types/AccountsMongoConfig.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type AccountsMongoOptions } from './accounts-mongo-options'; 3 | 4 | export const AccountsMongoConfigToken = new InjectionToken( 5 | 'AccountsMongoConfig' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/database-mongo/src/types/MongoConnection.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type Db } from 'mongodb'; 3 | 4 | export const MongoConnectionToken = new InjectionToken('MongoConnection'); 5 | -------------------------------------------------------------------------------- /packages/database-mongo/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './accounts-mongo-options'; 2 | export * from './AccountsMongoConfig.symbol'; 3 | export * from './MongoConnection.symbol'; 4 | -------------------------------------------------------------------------------- /packages/database-mongo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/database-redis/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/redis 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 8 | 9 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 10 | - @accounts/types@0.33.1 11 | 12 | ## 0.32.1 13 | 14 | ### Patch Changes 15 | 16 | - Updated dependencies [[`22056642`](https://github.com/accounts-js/accounts/commit/220566425755a7015569d8e518095701ff7122e2)]: 17 | - @accounts/types@0.33.0 18 | -------------------------------------------------------------------------------- /packages/database-redis/__tests__/redis.ts: -------------------------------------------------------------------------------- 1 | import { RedisSessions } from '../src/redis'; 2 | 3 | describe('Redis', () => { 4 | describe('#constructor', () => { 5 | it('should throw with an invalid database connection object', () => { 6 | expect(() => new RedisSessions(null as any)).toThrow('A database connection is required'); 7 | }); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/database-redis/src/index.ts: -------------------------------------------------------------------------------- 1 | export { RedisSessions } from './redis'; 2 | export { AccountsRedisOptions } from './types'; 3 | -------------------------------------------------------------------------------- /packages/database-redis/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountsRedisOptions } from './options'; 2 | -------------------------------------------------------------------------------- /packages/database-redis/src/types/options.ts: -------------------------------------------------------------------------------- 1 | export interface AccountsRedisOptions { 2 | /** 3 | * The users collection name. 4 | * Default 'users'. 5 | */ 6 | userCollectionName?: string; 7 | /** 8 | * The sessions collection name. 9 | * Default 'sessions'. 10 | */ 11 | sessionCollectionName?: string; 12 | /** 13 | * The timestamps for the users and sessions collection. 14 | * Default 'createdAt' and 'updatedAt'. 15 | */ 16 | timestamps?: { 17 | createdAt: string; 18 | updatedAt: string; 19 | }; 20 | /** 21 | * Function that generate the id for new objects. 22 | * Default to shortid npm package `shortid.generate()` 23 | */ 24 | idProvider?: () => string; 25 | /** 26 | * Function that generate the date for the timestamps. 27 | * Default to `(date?: Date) => (date ? date.getTime() : Date.now())`. 28 | */ 29 | dateProvider?: (date?: Date) => any; 30 | } 31 | -------------------------------------------------------------------------------- /packages/database-redis/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/database-tests/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/database-tests 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 8 | 9 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 10 | - @accounts/types@0.33.1 11 | 12 | ## 0.32.1 13 | 14 | ### Patch Changes 15 | 16 | - Updated dependencies [[`22056642`](https://github.com/accounts-js/accounts/commit/220566425755a7015569d8e518095701ff7122e2)]: 17 | - @accounts/types@0.33.0 18 | -------------------------------------------------------------------------------- /packages/database-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@accounts/database-tests", 3 | "private": true, 4 | "version": "0.32.2", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "scripts": { 8 | "clean": "yarn run -T rimraf lib", 9 | "start": "yarn run -T tsc --watch", 10 | "precompile": "yarn run clean", 11 | "compile": "yarn run -T tsc", 12 | "prepublishOnly": "yarn run compile" 13 | }, 14 | "files": [ 15 | "src", 16 | "lib" 17 | ], 18 | "jest": { 19 | "testEnvironment": "node", 20 | "preset": "ts-jest" 21 | }, 22 | "dependencies": { 23 | "tslib": "2.6.2" 24 | }, 25 | "author": "Leo Pradel", 26 | "license": "MIT" 27 | } 28 | -------------------------------------------------------------------------------- /packages/database-tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "target": "esnext", 6 | "importHelpers": true 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/entity/UserEmail.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Column, ManyToOne, Unique, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { User } from './User'; 3 | 4 | @Entity() 5 | export class UserEmail { 6 | @PrimaryGeneratedColumn('uuid') 7 | public id!: string; 8 | 9 | @ManyToOne(() => User, (user) => user.emails, { onDelete: 'CASCADE' }) 10 | public user!: User; 11 | 12 | @Unique(['address']) 13 | @Column() 14 | public address!: string; 15 | 16 | @Column({ default: false }) 17 | public verified!: boolean; 18 | 19 | @Column({ nullable: true }) 20 | public userId!: string; 21 | } 22 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/entity/UserService.ts: -------------------------------------------------------------------------------- 1 | import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'; 2 | import { User } from './User'; 3 | 4 | @Entity() 5 | export class UserService { 6 | @PrimaryGeneratedColumn('uuid') 7 | public id!: string; 8 | 9 | @ManyToOne(() => User, (user) => user.services, { onDelete: 'CASCADE' }) 10 | public user!: User; 11 | 12 | @Column() 13 | public name!: string; 14 | 15 | @Column({ nullable: true }) 16 | public token?: string; 17 | 18 | @Column('jsonb', { nullable: true }) 19 | public options: { bcrypt: string } | any; 20 | 21 | @Column({ nullable: true }) 22 | public serviceId!: string; 23 | 24 | @Column({ nullable: true }) 25 | public userId!: string; 26 | } 27 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/entity/UserSession.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | Column, 4 | ManyToOne, 5 | PrimaryGeneratedColumn, 6 | UpdateDateColumn, 7 | CreateDateColumn, 8 | } from 'typeorm'; 9 | import { User } from './User'; 10 | 11 | @Entity() 12 | export class UserSession { 13 | @PrimaryGeneratedColumn('uuid') 14 | public id!: string; 15 | 16 | @ManyToOne(() => User, (user) => user.sessions, { onDelete: 'CASCADE' }) 17 | public user!: User; 18 | 19 | @Column() 20 | public token!: string; 21 | 22 | @Column() 23 | public valid!: boolean; 24 | 25 | @Column({ type: 'text', nullable: true }) 26 | public userAgent?: string | null; 27 | 28 | @Column({ type: 'text', nullable: true }) 29 | public ip?: string | null; 30 | 31 | @Column('jsonb', { nullable: true }) 32 | public extra?: object; 33 | 34 | @CreateDateColumn() 35 | public createdAt!: string; 36 | 37 | @UpdateDateColumn() 38 | public updatedAt!: string; 39 | 40 | @Column({ nullable: true }) 41 | public userId!: string; 42 | } 43 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AccountsTypeorm } from './typeorm'; 2 | import { User } from './entity/User'; 3 | import { UserEmail } from './entity/UserEmail'; 4 | import { UserService } from './entity/UserService'; 5 | import { UserSession } from './entity/UserSession'; 6 | import { 7 | AccountsTypeORMConfigToken, 8 | AccountsTypeormOptions, 9 | UserEmailToken, 10 | UserServiceToken, 11 | UserSessionToken, 12 | UserToken, 13 | } from './types'; 14 | 15 | const entities = [User, UserEmail, UserService, UserSession]; 16 | 17 | export { 18 | AccountsTypeorm, 19 | User, 20 | UserEmail, 21 | UserService, 22 | UserSession, 23 | entities, 24 | UserToken, 25 | UserEmailToken, 26 | UserServiceToken, 27 | UserSessionToken, 28 | AccountsTypeORMConfigToken, 29 | AccountsTypeormOptions, 30 | }; 31 | export default AccountsTypeorm; 32 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/types/AccountsTypeORMConfig.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type AccountsTypeormOptions } from '.'; 3 | 4 | export const AccountsTypeORMConfigToken = new InjectionToken( 5 | 'AccountsTypeORMConfigToken' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/types/User.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type User } from '../entity/User'; 3 | 4 | export const UserToken = new InjectionToken('UserToken'); 5 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/types/UserEmail.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type UserEmail } from '../entity/UserEmail'; 3 | 4 | export const UserEmailToken = new InjectionToken('UserEmailToken'); 5 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/types/UserService.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type UserService } from '../entity/UserService'; 3 | 4 | export const UserServiceToken = new InjectionToken('UserServiceToken'); 5 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/types/UserSession.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type UserSession } from '../entity/UserSession'; 3 | 4 | export const UserSessionToken = new InjectionToken('UserSessionToken'); 5 | -------------------------------------------------------------------------------- /packages/database-typeorm/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AccountsTypeORMConfig.symbol'; 2 | export * from './User.symbol'; 3 | export * from './UserEmail.symbol'; 4 | export * from './UserService.symbol'; 5 | export * from './UserSession.symbol'; 6 | 7 | export interface AccountsTypeormOptions { 8 | cache?: undefined | number; 9 | // connection?: Connection; 10 | connectionName?: string; 11 | } 12 | -------------------------------------------------------------------------------- /packages/database-typeorm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/e2e/__tests__/databases/index.ts: -------------------------------------------------------------------------------- 1 | import { type DatabaseInterface } from '@accounts/types'; 2 | import { type Module } from 'graphql-modules'; 3 | 4 | export interface DatabaseTestInterface { 5 | databaseModule: Module; 6 | accountsDatabase: DatabaseInterface; 7 | 8 | start: () => Promise; 9 | stop: () => Promise; 10 | } 11 | -------------------------------------------------------------------------------- /packages/e2e/__tests__/databases/mongo.ts: -------------------------------------------------------------------------------- 1 | import mongoose from 'mongoose'; 2 | import { type DatabaseInterface } from '@accounts/types'; 3 | // TODO rename to AccountsMongo ? 4 | import { Mongo } from '@accounts/mongo'; 5 | import { type DatabaseTestInterface } from './index'; 6 | import { createAccountsMongoModule } from '@accounts/module-mongo'; 7 | 8 | const connectionString = 'mongodb://localhost/accounts-js-tests-e2e'; 9 | 10 | export class DatabaseTest implements DatabaseTestInterface { 11 | public databaseModule = createAccountsMongoModule({ dbConn: mongoose.connection }); 12 | public accountsDatabase: DatabaseInterface; 13 | 14 | constructor() { 15 | this.accountsDatabase = new Mongo(mongoose.connection); 16 | } 17 | 18 | public async start() { 19 | (mongoose as any).Promise = global.Promise; 20 | await mongoose.connect(connectionString); 21 | await mongoose.connection.dropDatabase(); 22 | } 23 | 24 | public async stop() { 25 | await mongoose.connection.close(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "./src", 5 | "outDir": "./lib", 6 | "importHelpers": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/error/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/error 2 | 3 | ## 0.32.1 4 | ### Patch Changes 5 | 6 | 7 | 8 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 9 | -------------------------------------------------------------------------------- /packages/error/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import AccountsError from '../src'; 2 | 3 | describe('AccountsError', () => { 4 | it('should have a default export AccountsError', () => { 5 | expect(typeof AccountsError).toBe('function'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/error/src/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './accounts-error'; 2 | -------------------------------------------------------------------------------- /packages/error/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/express-session/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/express-session 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 8 | 9 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 10 | - @accounts/types@0.33.1 11 | 12 | ## 0.32.1 13 | 14 | ### Patch Changes 15 | 16 | - Updated dependencies [[`22056642`](https://github.com/accounts-js/accounts/commit/220566425755a7015569d8e518095701ff7122e2)]: 17 | - @accounts/types@0.33.0 18 | -------------------------------------------------------------------------------- /packages/express-session/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import AccountsSession from '../src'; 2 | 3 | describe('AccountsSession', () => { 4 | it('should have default export AccountsSession', () => { 5 | expect(typeof AccountsSession).toBe('function'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/express-session/src/custom.d.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 2 | import session from 'express-session'; // Because of https://stackoverflow.com/a/51114250 3 | 4 | declare module 'express-session' { 5 | interface SessionData { 6 | [key: string]: any; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/express-session/src/utils/get-user-agent.ts: -------------------------------------------------------------------------------- 1 | import type { Request } from 'express'; 2 | 3 | export const getUserAgent = (req: Request) => { 4 | let userAgent: string = (req.headers['user-agent'] as string) || ''; 5 | if (req.headers['x-ucbrowser-ua']) { 6 | // special case of UC Browser 7 | userAgent = req.headers['x-ucbrowser-ua'] as string; 8 | } 9 | return userAgent; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/express-session/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/graphql-client/codegen.yml: -------------------------------------------------------------------------------- 1 | schema: 2 | - ../../modules/module-core/introspection.json 3 | - ../../modules/module-password/introspection.json 4 | - ../../modules/module-magic-link/introspection.json 5 | documents: ./src/**/*.graphql 6 | generates: 7 | ./src/graphql-operations.ts: 8 | plugins: 9 | - add: 10 | content: '/* eslint-disable */' 11 | - typescript 12 | - typescript-operations 13 | - typed-document-node 14 | -------------------------------------------------------------------------------- /packages/graphql-client/src/GraphQLErrorList.ts: -------------------------------------------------------------------------------- 1 | import { type GraphQLError } from 'graphql/error/GraphQLError'; 2 | 3 | export class GraphQLErrorList extends Error { 4 | public errors: readonly GraphQLError[]; 5 | 6 | constructor(errors: readonly GraphQLError[], message?: string) { 7 | super(); 8 | this.errors = errors; 9 | this.stack = new Error().stack; 10 | 11 | const br = '\r\n'; 12 | const summary = `${errors.length} error${errors.length > 1 ? 's' : ''}${ 13 | message ? ' ' + message : ':' 14 | }`; 15 | const errList = errors.map((err) => `\t- ${err.message}`).join(br); 16 | this.message = `GraphQLErrorList - ${summary}${br}${errList}`; 17 | } 18 | 19 | toString() { 20 | return this.errors.map((err) => err.toString()).join('\r\n'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/fragments/userFields.graphql: -------------------------------------------------------------------------------- 1 | fragment userFields on User { 2 | id 3 | emails { 4 | address 5 | verified 6 | } 7 | username 8 | } 9 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/add-email.graphql: -------------------------------------------------------------------------------- 1 | mutation addEmail($newEmail: String!) { 2 | addEmail(newEmail: $newEmail) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/authenticate-with-service.graphql: -------------------------------------------------------------------------------- 1 | mutation authenticateWithService($serviceName: String!, $params: AuthenticateParamsInput!) { 2 | verifyAuthentication(serviceName: $serviceName, params: $params) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/change-password.graphql: -------------------------------------------------------------------------------- 1 | mutation changePassword($oldPassword: String!, $newPassword: String!) { 2 | changePassword(oldPassword: $oldPassword, newPassword: $newPassword) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/create-user.graphql: -------------------------------------------------------------------------------- 1 | mutation createUser($user: CreateUserInput!) { 2 | createUser(user: $user) { 3 | userId 4 | loginResult { 5 | sessionId 6 | tokens { 7 | refreshToken 8 | accessToken 9 | } 10 | user { 11 | ...userFields 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/impersonate.graphql: -------------------------------------------------------------------------------- 1 | mutation impersonate($accessToken: String!, $impersonated: ImpersonationUserIdentityInput!) { 2 | impersonate(accessToken: $accessToken, impersonated: $impersonated) { 3 | authorized 4 | tokens { 5 | refreshToken 6 | accessToken 7 | } 8 | user { 9 | ...userFields 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/login-with-service.graphql: -------------------------------------------------------------------------------- 1 | mutation authenticate($serviceName: String!, $params: AuthenticateParamsInput!) { 2 | authenticate(serviceName: $serviceName, params: $params) { 3 | sessionId 4 | tokens { 5 | refreshToken 6 | accessToken 7 | } 8 | user { 9 | ...userFields 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/logout.graphql: -------------------------------------------------------------------------------- 1 | mutation logout { 2 | logout 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/refresh-tokens.graphql: -------------------------------------------------------------------------------- 1 | mutation refreshTokens($accessToken: String!, $refreshToken: String!) { 2 | refreshTokens(accessToken: $accessToken, refreshToken: $refreshToken) { 3 | sessionId 4 | tokens { 5 | refreshToken 6 | accessToken 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/request-magic-link-email.graphql: -------------------------------------------------------------------------------- 1 | mutation requestMagicLinkEmail($email: String!) { 2 | requestMagicLinkEmail(email: $email) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/reset-password.graphql: -------------------------------------------------------------------------------- 1 | mutation resetPassword($token: String!, $newPassword: String!) { 2 | resetPassword(token: $token, newPassword: $newPassword) { 3 | sessionId 4 | tokens { 5 | refreshToken 6 | accessToken 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/send-reset-password-email.graphql: -------------------------------------------------------------------------------- 1 | mutation sendResetPasswordEmail($email: String!) { 2 | sendResetPasswordEmail(email: $email) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/send-verification-email.graphql: -------------------------------------------------------------------------------- 1 | mutation sendVerificationEmail($email: String!) { 2 | sendVerificationEmail(email: $email) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/two-factor-set.graphql: -------------------------------------------------------------------------------- 1 | mutation twoFactorSet($secret: TwoFactorSecretKeyInput!, $code: String!) { 2 | twoFactorSet(secret: $secret, code: $code) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/two-factor-unset.graphql: -------------------------------------------------------------------------------- 1 | mutation twoFactorUnset($code: String!) { 2 | twoFactorUnset(code: $code) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/mutations/verify-email.graphql: -------------------------------------------------------------------------------- 1 | mutation verifyEmail($token: String!) { 2 | verifyEmail(token: $token) 3 | } 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/queries/get-two-factor-secret.graphql: -------------------------------------------------------------------------------- 1 | query getTwoFactorSecret { 2 | twoFactorSecret { 3 | ascii 4 | base32 5 | hex 6 | qr_code_ascii 7 | qr_code_hex 8 | qr_code_base32 9 | google_auth_qr 10 | otpauth_url 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/graphql-client/src/graphql/queries/get-user.graphql: -------------------------------------------------------------------------------- 1 | query getUser { 2 | getUser { 3 | ...userFields 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/graphql-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './graphql-client'; 2 | export { default as AccountsGraphQLClient, default } from './graphql-client'; 3 | export * from './GraphQLErrorList'; 4 | -------------------------------------------------------------------------------- /packages/graphql-client/src/utils/replace-user-fragment.ts: -------------------------------------------------------------------------------- 1 | import { type DocumentNode } from 'graphql'; 2 | 3 | /** 4 | * Utility function used to modify the current query Document. 5 | * We remove the existing the user fragment and add the one provided by the user. 6 | * Graphql-codegen add the fragment as the end of the definition array. 7 | */ 8 | export const replaceUserFieldsFragment = ( 9 | document: DocumentNode, 10 | userFieldsFragment: DocumentNode 11 | ) => { 12 | return { 13 | ...document, 14 | definitions: [...document.definitions.slice(0, -1), ...userFieldsFragment.definitions], 15 | }; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/graphql-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true, 6 | "target": "es5" 7 | }, 8 | "include": ["src/**/*.ts"], 9 | "exclude": ["node_modules"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/magic-link/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/magic-link 2 | 3 | ## 0.1.1 4 | 5 | ### Patch Changes 6 | 7 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 8 | 9 | ## 0.1.0 10 | 11 | ### Minor Changes 12 | 13 | - [#1150](https://github.com/accounts-js/accounts/pull/1150) [`22056642`](https://github.com/accounts-js/accounts/commit/220566425755a7015569d8e518095701ff7122e2) Thanks [@larsivi](https://github.com/larsivi)! - Add support for magic-link strategy 🎉. 14 | 15 | Installation: 16 | 17 | ```sh 18 | yarn add @accounts/magic-link 19 | ``` 20 | 21 | Usage: 22 | 23 | ```js 24 | import AccountsMagicLink from '@accounts/magic-link'; 25 | 26 | const accountsMagicLink = new AccountsMagicLink({}); 27 | 28 | const accountsServer = new AccountsServer( 29 | { db: accountsDb, tokenSecret: 'secret' }, 30 | { 31 | magicLink: accountsMagicLink, 32 | } 33 | ); 34 | ``` 35 | -------------------------------------------------------------------------------- /packages/magic-link/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/magic-link 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/magic-link)](https://www.npmjs.com/package/@accounts/magic-link) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/magic-link)](https://www.npmjs.com/package/@accounts/magic-link) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/strategies/magic-link) 11 | - [API documentation](https://www.accountsjs.com/docs/api/magic-link/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/magic-link 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/magic-link/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import AccountsMagicLink from '../src'; 3 | 4 | describe('AccountsMagicLink', () => { 5 | it('should have default export AccountsMagicLink', () => { 6 | expect(typeof AccountsMagicLink).toBe('function'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/magic-link/src/errors.ts: -------------------------------------------------------------------------------- 1 | import { type ErrorMessages } from './types'; 2 | 3 | export const errors: ErrorMessages = { 4 | userNotFound: 'User not found', 5 | unrecognizedOptionsForLogin: 'Unrecognized options for login request', 6 | matchFailed: 'Match failed', 7 | invalidEmail: 'Invalid email', 8 | loginTokenExpired: 'Login token expired', 9 | }; 10 | 11 | export enum MagicLinkAuthenticatorErrors { 12 | LoginTokenExpired = 'LoginTokenExpired', 13 | } 14 | 15 | export enum AuthenticateErrors { 16 | UnrecognizedOptionsForLogin = 'UnrecognizedOptionsForLogin', 17 | MatchFailed = 'MatchFailed', 18 | } 19 | 20 | export enum RequestMagicLinkEmailErrors { 21 | InvalidEmail = 'InvalidEmail', 22 | UserNotFound = 'UserNotFound', 23 | } 24 | -------------------------------------------------------------------------------- /packages/magic-link/src/index.ts: -------------------------------------------------------------------------------- 1 | import AccountsMagicLink, { AccountsMagicLinkOptions } from './accounts-magic-link'; 2 | export * from './types'; 3 | export { 4 | errors, 5 | AuthenticateErrors, 6 | MagicLinkAuthenticatorErrors, 7 | RequestMagicLinkEmailErrors, 8 | } from './errors'; 9 | 10 | export default AccountsMagicLink; 11 | export { AccountsMagicLink, AccountsMagicLinkOptions }; 12 | -------------------------------------------------------------------------------- /packages/magic-link/src/types/AccountsMagicLinkConfig.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type AccountsMagicLinkOptions } from '../accounts-magic-link'; 3 | 4 | export const AccountsMagicLinkConfigToken = new InjectionToken( 5 | 'AccountsMagicLinkConfig' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/magic-link/src/types/error-messages.ts: -------------------------------------------------------------------------------- 1 | export interface ErrorMessages { 2 | /** 3 | * Default to 'User not found' 4 | */ 5 | userNotFound: string; 6 | /** 7 | * Default to 'Unrecognized options for login request' 8 | */ 9 | unrecognizedOptionsForLogin: string; 10 | /** 11 | * Default to 'Match failed' 12 | */ 13 | matchFailed: string; 14 | /** 15 | * Default to 'Invalid email' 16 | */ 17 | invalidEmail: string; 18 | /** 19 | * Default to 'Login token expired' 20 | */ 21 | loginTokenExpired: string; 22 | } 23 | -------------------------------------------------------------------------------- /packages/magic-link/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export { ErrorMessages } from './error-messages'; 2 | export * from './AccountsMagicLinkConfig.symbol'; 3 | -------------------------------------------------------------------------------- /packages/magic-link/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getUserLoginTokens } from './user'; 2 | export { isEmail } from './is-email'; 3 | -------------------------------------------------------------------------------- /packages/magic-link/src/utils/is-email.ts: -------------------------------------------------------------------------------- 1 | export const isEmail = (email?: string) => { 2 | const re = 3 | // eslint-disable-next-line no-useless-escape 4 | /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 5 | return Boolean(email && re.test(email)); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/magic-link/src/utils/user.ts: -------------------------------------------------------------------------------- 1 | import { type User, type TokenRecord } from '@accounts/types'; 2 | 3 | export const getUserLoginTokens = (user: User): TokenRecord[] => { 4 | return user.services?.magicLink?.loginTokens ?? []; 5 | }; 6 | -------------------------------------------------------------------------------- /packages/magic-link/src/utils/validation.ts: -------------------------------------------------------------------------------- 1 | export const isString = (x: any): x is string => { 2 | return typeof x === 'string'; 3 | }; 4 | 5 | export const isObject = (x: any): x is object => { 6 | return x !== null && typeof x === 'object'; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/magic-link/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/oauth-instagram/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/oauth-instagram 2 | 3 | ## 0.32.1 4 | ### Patch Changes 5 | 6 | 7 | 8 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 9 | 10 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 11 | - @accounts/oauth@0.32.2 12 | -------------------------------------------------------------------------------- /packages/oauth-instagram/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/oauth-instagram 2 | -------------------------------------------------------------------------------- /packages/oauth-instagram/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import AccountsOAuthInstagram from '../src'; 2 | 3 | describe('AccountsOAuthInstagram', () => { 4 | it('should have default export AccountsOAuthInstagram', () => { 5 | expect(typeof AccountsOAuthInstagram).toBe('function'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/oauth-instagram/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@accounts/oauth-instagram", 3 | "version": "0.32.1", 4 | "license": "MIT", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "scripts": { 8 | "clean": "yarn run -T rimraf lib", 9 | "start": "yarn run -T tsc --watch", 10 | "precompile": "yarn run clean", 11 | "compile": "yarn run -T tsc", 12 | "prepublishOnly": "yarn run compile", 13 | "testonly": "yarn run -T jest", 14 | "coverage": "yarn run -T jest --coverage" 15 | }, 16 | "files": [ 17 | "src", 18 | "lib" 19 | ], 20 | "jest": { 21 | "testEnvironment": "node", 22 | "preset": "ts-jest" 23 | }, 24 | "dependencies": { 25 | "request": "2.88.2", 26 | "request-promise": "4.2.6", 27 | "tslib": "2.6.2" 28 | }, 29 | "devDependencies": { 30 | "@accounts/oauth": "^0.32.2", 31 | "@types/request-promise": "4.1.51" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/oauth-instagram/src/accounts-oauth-instagram.ts: -------------------------------------------------------------------------------- 1 | import rp from 'request-promise'; 2 | import { type OAuthProvider, type OAuthUser } from '@accounts/oauth'; 3 | import { type Configuration } from './types/configuration'; 4 | 5 | export class AccountsOAuthInstagram implements OAuthProvider { 6 | public getRegistrationPayload?: (oauthUser: OAuthUser) => Promise; 7 | 8 | constructor(config?: Configuration) { 9 | this.getRegistrationPayload = config?.getRegistrationPayload; 10 | } 11 | 12 | public async authenticate(params: any) { 13 | let data = await rp( 14 | `https://api.instagram.com/v1/users/self/?access_token=${params.access_token}` 15 | ); 16 | data = JSON.parse(data).data; 17 | return { 18 | id: data.id, 19 | username: data.username, 20 | profilePicture: data.profile_picture, 21 | accessToken: params.access_token, 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/oauth-instagram/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AccountsOAuthInstagram } from './accounts-oauth-instagram'; 2 | export default AccountsOAuthInstagram; 3 | -------------------------------------------------------------------------------- /packages/oauth-instagram/src/types/configuration.ts: -------------------------------------------------------------------------------- 1 | import { type OAuthUser } from '@accounts/oauth'; 2 | 3 | export interface Configuration { 4 | getRegistrationPayload?: (oauthUser: OAuthUser) => Promise; 5 | } 6 | -------------------------------------------------------------------------------- /packages/oauth-instagram/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth-twitter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/oauth-twitter 2 | 3 | ## 0.32.1 4 | ### Patch Changes 5 | 6 | 7 | 8 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 9 | 10 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 11 | - @accounts/oauth@0.32.2 12 | -------------------------------------------------------------------------------- /packages/oauth-twitter/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/oauth-twitter 2 | -------------------------------------------------------------------------------- /packages/oauth-twitter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@accounts/oauth-twitter", 3 | "version": "0.32.1", 4 | "license": "MIT", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "scripts": { 8 | "clean": "yarn run -T rimraf lib", 9 | "start": "yarn run -T tsc --watch", 10 | "precompile": "yarn run clean", 11 | "compile": "yarn run -T tsc", 12 | "prepublishOnly": "yarn run compile", 13 | "testonly": "yarn run -T jest", 14 | "coverage": "yarn run -T jest --coverage" 15 | }, 16 | "files": [ 17 | "src", 18 | "lib" 19 | ], 20 | "jest": { 21 | "testEnvironment": "node", 22 | "preset": "ts-jest" 23 | }, 24 | "dependencies": { 25 | "oauth": "^0.10.0", 26 | "tslib": "2.6.2" 27 | }, 28 | "devDependencies": { 29 | "@accounts/oauth": "^0.32.2", 30 | "@types/oauth": "0.9.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/oauth-twitter/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AccountsOAuthTwitter } from './accounts-oauth-twitter'; 2 | 3 | export default AccountsOAuthTwitter; 4 | -------------------------------------------------------------------------------- /packages/oauth-twitter/src/types/configuration.ts: -------------------------------------------------------------------------------- 1 | import { type OAuthUser } from '@accounts/oauth'; 2 | 3 | export interface Configuration { 4 | key: string; 5 | secret: string; 6 | getRegistrationPayload?: (oauthUser: OAuthUser) => Promise; 7 | } 8 | -------------------------------------------------------------------------------- /packages/oauth-twitter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/oauth/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/oauth 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 8 | 9 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 10 | - @accounts/types@0.33.1 11 | 12 | ## 0.32.1 13 | 14 | ### Patch Changes 15 | 16 | - Updated dependencies [[`22056642`](https://github.com/accounts-js/accounts/commit/220566425755a7015569d8e518095701ff7122e2)]: 17 | - @accounts/types@0.33.0 18 | -------------------------------------------------------------------------------- /packages/oauth/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/oauth 2 | -------------------------------------------------------------------------------- /packages/oauth/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import AccountsOauth from '../src'; 3 | 4 | describe('AccountsOauth', () => { 5 | it('should have default export AccountsOauth', () => { 6 | expect(typeof AccountsOauth).toBe('function'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/oauth/src/index.ts: -------------------------------------------------------------------------------- 1 | import { AccountsOauth } from './accounts-oauth'; 2 | export default AccountsOauth; 3 | 4 | export { AccountsOauth } from './accounts-oauth'; 5 | export { OAuthProvider } from './types/oauth-provider'; 6 | export { OAuthProviders } from './types/oauth-providers'; 7 | export { OAuthUser } from './types/oauth-user'; 8 | -------------------------------------------------------------------------------- /packages/oauth/src/types/OAuthProviders.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type OAuthProviders } from './oauth-providers'; 3 | 4 | export const OAuthProvidersToken = new InjectionToken('OauthProviders'); 5 | -------------------------------------------------------------------------------- /packages/oauth/src/types/oauth-provider.ts: -------------------------------------------------------------------------------- 1 | import { type OAuthUser } from './oauth-user'; 2 | 3 | /** 4 | * Interface to use for all custom implementations of OAuth providers 5 | */ 6 | export interface OAuthProvider { 7 | /** 8 | * Should return oauth user payload from passed authentication code or token 9 | */ 10 | authenticate: (params: any) => Promise; 11 | /** 12 | * Allows to provide function to create custom payload for user creation method based on data from OAuth API 13 | */ 14 | getRegistrationPayload?: (oauthUser: OAuthUser) => Promise; 15 | } 16 | -------------------------------------------------------------------------------- /packages/oauth/src/types/oauth-providers.ts: -------------------------------------------------------------------------------- 1 | import { type OAuthProvider } from './oauth-provider'; 2 | 3 | export interface OAuthProviders { 4 | [key: string]: (new (args: any) => OAuthProvider) | OAuthProvider | undefined; 5 | } 6 | -------------------------------------------------------------------------------- /packages/oauth/src/types/oauth-user.ts: -------------------------------------------------------------------------------- 1 | export interface OAuthUser { 2 | id: string; 3 | email?: string; 4 | [key: string]: any; 5 | } 6 | -------------------------------------------------------------------------------- /packages/oauth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/password/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @accounts/password 2 | 3 | ## 0.32.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1228](https://github.com/accounts-js/accounts/pull/1228) [`2afcb843`](https://github.com/accounts-js/accounts/commit/2afcb8435615bb8c85bdba39101a2c25a451df12) Thanks [@pozylon](https://github.com/pozylon)! - Fix critical issue with "Two-Factor" not validating TOTP codes correctly due to a flawed version of @levminer/speakeasy 8 | 9 | - Updated dependencies [[`2afcb843`](https://github.com/accounts-js/accounts/commit/2afcb8435615bb8c85bdba39101a2c25a451df12)]: 10 | - @accounts/two-factor@0.32.4 11 | 12 | ## 0.32.1 13 | 14 | ### Patch Changes 15 | 16 | - [#1170](https://github.com/accounts-js/accounts/pull/1170) [`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda) Thanks [@pradel](https://github.com/pradel)! - Upgrade tslib to 2.3.0 17 | 18 | - Updated dependencies [[`e81eb578`](https://github.com/accounts-js/accounts/commit/e81eb578b35906346b6fadd6c5768b82879f6cda)]: 19 | - @accounts/two-factor@0.32.2 20 | -------------------------------------------------------------------------------- /packages/password/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/password 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/password)](https://www.npmjs.com/package/@accounts/password) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/password)](https://www.npmjs.com/package/@accounts/password) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/strategies/password) 11 | - [API documentation](https://www.accountsjs.com/docs/api/password/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/password 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/password/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import AccountsPassword from '../src'; 3 | 4 | describe('AccountsPassword', () => { 5 | it('should have default export AccountsPassword', () => { 6 | expect(typeof AccountsPassword).toBe('function'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/password/__tests__/utils/encryption.ts: -------------------------------------------------------------------------------- 1 | import { bcryptPassword, verifyPassword } from '../../src/utils/encryption'; 2 | 3 | describe('encryption', () => { 4 | describe('bcryptPassword', () => { 5 | it('should return the hashed password', () => { 6 | const password = 'pass'; 7 | expect(bcryptPassword(password)).not.toBe(password); 8 | }); 9 | }); 10 | 11 | describe('verifyPassword', () => { 12 | it('should return true', async () => { 13 | const hashedPassword = await bcryptPassword('pass'); 14 | expect(verifyPassword('pass', hashedPassword)).toBeTruthy(); 15 | }); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/password/src/endpoints/Request.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Express { 2 | export interface Request { 3 | userAgent: string; 4 | ip: string; 5 | infos: { 6 | userAgent: string; 7 | ip: string; 8 | }; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/password/src/endpoints/index.ts: -------------------------------------------------------------------------------- 1 | export * from './express'; 2 | -------------------------------------------------------------------------------- /packages/password/src/index.ts: -------------------------------------------------------------------------------- 1 | import AccountsPassword, { AccountsPasswordOptions } from './accounts-password'; 2 | export * from './types'; 3 | export * from './endpoints'; 4 | export { 5 | AddEmailErrors, 6 | ChangePasswordErrors, 7 | CreateUserErrors, 8 | ResetPasswordErrors, 9 | SendVerificationEmailErrors, 10 | SendResetPasswordEmailErrors, 11 | VerifyEmailErrors, 12 | } from './errors'; 13 | 14 | export default AccountsPassword; 15 | export { AccountsPassword, AccountsPasswordOptions }; 16 | -------------------------------------------------------------------------------- /packages/password/src/types/AccountsPasswordConfig.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type AccountsPasswordOptions } from '../accounts-password'; 3 | 4 | export const AccountsPasswordConfigToken = new InjectionToken( 5 | 'AccountsPasswordConfig' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/password/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export { ErrorMessages } from './error-messages'; 2 | export * from './AccountsPasswordConfig.symbol'; 3 | -------------------------------------------------------------------------------- /packages/password/src/utils/encryption.ts: -------------------------------------------------------------------------------- 1 | import { genSalt, hash, compare } from 'bcryptjs'; 2 | 3 | export const bcryptPassword = async (password: string): Promise => { 4 | const salt = await genSalt(10); 5 | const hashedPassword = await hash(password, salt); 6 | return hashedPassword; 7 | }; 8 | 9 | export const verifyPassword = async (password: string, hash: string): Promise => 10 | compare(password, hash); 11 | -------------------------------------------------------------------------------- /packages/password/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getUserResetTokens, getUserVerificationTokens } from './user'; 2 | export { bcryptPassword, verifyPassword } from './encryption'; 3 | export { isEmail } from './is-email'; 4 | -------------------------------------------------------------------------------- /packages/password/src/utils/is-email.ts: -------------------------------------------------------------------------------- 1 | export const isEmail = (email?: string) => { 2 | const re = 3 | // eslint-disable-next-line no-useless-escape 4 | /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 5 | return Boolean(email && re.test(email)); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/password/src/utils/user.ts: -------------------------------------------------------------------------------- 1 | import { type User, type TokenRecord } from '@accounts/types'; 2 | 3 | export const getUserResetTokens = (user: User): TokenRecord[] => { 4 | return user.services?.password?.reset ?? []; 5 | }; 6 | 7 | export const getUserVerificationTokens = (user: User): TokenRecord[] => { 8 | return user.services?.email?.verificationTokens ?? []; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/password/src/utils/validation.ts: -------------------------------------------------------------------------------- 1 | export const isString = (x: any): x is string => { 2 | return typeof x === 'string'; 3 | }; 4 | 5 | export const isObject = (x: any): x is object => { 6 | return x !== null && typeof x === 'object'; 7 | }; 8 | -------------------------------------------------------------------------------- /packages/password/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/rest-client/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/rest-client 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/rest-client)](https://www.npmjs.com/package/@accounts/rest-client) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/rest-client)](https://www.npmjs.com/package/@accounts/rest-client) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/transports/rest-client) 11 | - [API documentation](https://www.accountsjs.com/docs/api/rest-client/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/rest-client 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/rest-client/src/accounts-error.ts: -------------------------------------------------------------------------------- 1 | export class AccountsJsError extends Error { 2 | public code: string; 3 | 4 | constructor(message: string, code: string) { 5 | super(message); 6 | this.code = code; 7 | Object.setPrototypeOf(this, new.target.prototype); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/rest-client/src/auth-fetch.ts: -------------------------------------------------------------------------------- 1 | import { type AccountsClient } from '@accounts/client'; 2 | 3 | const headers: { [key: string]: string } = { 4 | 'Content-Type': 'application/json', 5 | }; 6 | 7 | export const authFetch = async (accounts: AccountsClient, path: string, request: any) => { 8 | const tokens = await accounts.refreshSession(); 9 | let headersCopy = { ...headers }; 10 | 11 | if (tokens) { 12 | headersCopy.Authorization = 'Bearer ' + tokens.accessToken; 13 | } 14 | 15 | if (request['headers']) { 16 | headersCopy = { 17 | ...headersCopy, 18 | ...request['headers'], 19 | }; 20 | } 21 | 22 | const fetchOptions = { 23 | ...request, 24 | headers: headersCopy, 25 | }; 26 | return fetch(path, fetchOptions); 27 | }; 28 | -------------------------------------------------------------------------------- /packages/rest-client/src/index.ts: -------------------------------------------------------------------------------- 1 | export { RestClient } from './rest-client'; 2 | export { authFetch } from './auth-fetch'; 3 | export { AccountsJsError } from './accounts-error'; 4 | -------------------------------------------------------------------------------- /packages/rest-client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true, 6 | "target": "es5", 7 | "lib": ["es2019", "dom"] 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/rest-express/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/rest-express 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/rest-express)](https://www.npmjs.com/package/@accounts/rest-express) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/rest-express)](https://www.npmjs.com/package/@accounts/rest-express) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/transports/rest-express) 11 | - [API documentation](https://www.accountsjs.com/docs/api/rest-express/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/rest-express 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/rest-express/__tests__/endpoints/get-user.ts: -------------------------------------------------------------------------------- 1 | import { getUser } from '../../src/endpoints/get-user'; 2 | 3 | const res: any = { 4 | json: jest.fn(), 5 | status: jest.fn(() => res), 6 | }; 7 | 8 | describe('getUser', () => { 9 | beforeEach(() => { 10 | jest.clearAllMocks(); 11 | }); 12 | 13 | it('calls getUser and returns the user json response', async () => { 14 | const user = { 15 | id: '1', 16 | }; 17 | const middleware = getUser(); 18 | 19 | const req = { 20 | user, 21 | body: { 22 | accessToken: 'token', 23 | }, 24 | headers: {}, 25 | }; 26 | const reqCopy = { ...req }; 27 | 28 | await middleware(req as any, res); 29 | 30 | expect(req).toEqual(reqCopy); 31 | expect(res.json).toHaveBeenCalledWith(user); 32 | expect(res.status).not.toHaveBeenCalled(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/rest-express/__tests__/utils/get-user-agent.ts: -------------------------------------------------------------------------------- 1 | import { getUserAgent } from '../../src/utils/get-user-agent'; 2 | 3 | describe('getUserAgent', () => { 4 | it('should return header user agent', () => { 5 | const req = { 6 | headers: { 7 | 'user-agent': 'agent', 8 | }, 9 | }; 10 | const userAgent = getUserAgent(req as any); 11 | expect(userAgent).toBe('agent'); 12 | }); 13 | 14 | it('should return header UC Browser user agent', () => { 15 | const req = { 16 | headers: { 17 | 'x-ucbrowser-ua': 'agent', 18 | }, 19 | }; 20 | const userAgent = getUserAgent(req as any); 21 | expect(userAgent).toBe('agent'); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /packages/rest-express/src/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Express { 2 | export interface Request { 3 | userAgent: string; 4 | ip: string; 5 | infos: { 6 | userAgent: string; 7 | ip: string; 8 | }; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/rest-express/src/endpoints/get-user.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | 3 | export const getUser = () => async (req: express.Request, res: express.Response) => { 4 | res.json((req as any).user || null); 5 | }; 6 | -------------------------------------------------------------------------------- /packages/rest-express/src/endpoints/logout.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | import { type AccountsServer } from '@accounts/server'; 3 | import { sendError } from '../utils/send-error'; 4 | 5 | export const logout = 6 | (accountsServer: AccountsServer) => async (req: express.Request, res: express.Response) => { 7 | try { 8 | const { authToken } = req as express.Request & { authToken: string }; 9 | await accountsServer.logout(authToken); 10 | res.json(null); 11 | } catch (err) { 12 | sendError(res, err); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /packages/rest-express/src/endpoints/password/add-email.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | import { type AccountsServer } from '@accounts/server'; 3 | import { type AccountsPassword } from '@accounts/password'; 4 | import { sendError } from '../../utils/send-error'; 5 | import { body } from 'express-validator'; 6 | import { matchOrThrow } from '../../utils/matchOrTrow'; 7 | 8 | export const addEmail = (accountsServer: AccountsServer) => [ 9 | body('newEmail').isEmail(), 10 | async (req: express.Request, res: express.Response) => { 11 | try { 12 | const userId: string | undefined = (req as any).userId; 13 | if (!userId) { 14 | res.status(401); 15 | res.json({ message: 'Unauthorized' }); 16 | return; 17 | } 18 | const { newEmail } = matchOrThrow<{ newEmail: string }>(req); 19 | const accountsPassword = accountsServer.getServices().password as AccountsPassword; 20 | await accountsPassword.addEmail(userId, newEmail); 21 | res.json(null); 22 | } catch (err) { 23 | sendError(res, err); 24 | } 25 | }, 26 | ]; 27 | -------------------------------------------------------------------------------- /packages/rest-express/src/endpoints/refresh-access-token.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | import { type AccountsServer } from '@accounts/server'; 3 | import { sendError } from '../utils/send-error'; 4 | import { body } from 'express-validator'; 5 | import { matchOrThrow } from '../utils/matchOrTrow'; 6 | 7 | export const refreshAccessToken = (accountsServer: AccountsServer) => [ 8 | body('accessToken').isString().notEmpty(), 9 | body('refreshToken').isString().notEmpty(), 10 | async (req: express.Request, res: express.Response) => { 11 | try { 12 | const { accessToken, refreshToken } = matchOrThrow<{ 13 | accessToken: string; 14 | refreshToken: string; 15 | }>(req); 16 | const refreshedSession = await accountsServer.refreshTokens( 17 | accessToken, 18 | refreshToken, 19 | req.infos 20 | ); 21 | res.json(refreshedSession); 22 | } catch (err) { 23 | sendError(res, err); 24 | } 25 | }, 26 | ]; 27 | -------------------------------------------------------------------------------- /packages/rest-express/src/endpoints/service-authenticate.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | import { type AccountsServer } from '@accounts/server'; 3 | import { sendError } from '../utils/send-error'; 4 | import { param } from 'express-validator'; 5 | import { matchOrThrow } from '../utils/matchOrTrow'; 6 | 7 | export const serviceAuthenticate = (accountsServer: AccountsServer) => [ 8 | param('service').isString().notEmpty(), 9 | async (req: express.Request, res: express.Response) => { 10 | try { 11 | const { service } = matchOrThrow<{ service: string }>(req); 12 | const loggedInUser = await accountsServer.loginWithService(service, req.body, req.infos); 13 | res.json(loggedInUser); 14 | } catch (err) { 15 | sendError(res, err); 16 | } 17 | }, 18 | ]; 19 | -------------------------------------------------------------------------------- /packages/rest-express/src/endpoints/verify-authentication.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | import { type AccountsServer } from '@accounts/server'; 3 | import { sendError } from '../utils/send-error'; 4 | import { param } from 'express-validator'; 5 | import { matchOrThrow } from '../utils/matchOrTrow'; 6 | 7 | export const serviceVerifyAuthentication = (accountsServer: AccountsServer) => [ 8 | param('service').isString().notEmpty(), 9 | async (req: express.Request, res: express.Response) => { 10 | try { 11 | const { service } = matchOrThrow<{ service: string }>(req); 12 | const isAuthenticated = await accountsServer.authenticateWithService( 13 | service, 14 | req.body, 15 | req.infos 16 | ); 17 | res.json(isAuthenticated); 18 | } catch (err) { 19 | sendError(res, err); 20 | } 21 | }, 22 | ]; 23 | -------------------------------------------------------------------------------- /packages/rest-express/src/index.ts: -------------------------------------------------------------------------------- 1 | import middleware from './express-middleware'; 2 | export { userLoader } from './user-loader'; 3 | export default middleware; 4 | -------------------------------------------------------------------------------- /packages/rest-express/src/types.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | import { type LoginResult } from '@accounts/types'; 3 | 4 | export type OAuthSuccessCallback = ( 5 | req: express.Request, 6 | res: express.Response, 7 | login: LoginResult 8 | ) => void; 9 | export type OAuthErrorCallback = (req: express.Request, res: express.Response, error: any) => void; 10 | export type TransformOAuthResponse = (login: LoginResult) => T; 11 | 12 | export interface AccountsExpressOptions { 13 | path?: string; 14 | onOAuthSuccess?: OAuthSuccessCallback; 15 | onOAuthError?: OAuthErrorCallback; 16 | transformOAuthResponse?: TransformOAuthResponse; 17 | } 18 | -------------------------------------------------------------------------------- /packages/rest-express/src/utils/get-user-agent.ts: -------------------------------------------------------------------------------- 1 | import type * as express from 'express'; 2 | 3 | export const getUserAgent = (req: express.Request) => { 4 | let userAgent: string = (req.headers['user-agent'] as string) || ''; 5 | if (req.headers['x-ucbrowser-ua']) { 6 | // special case of UC Browser 7 | userAgent = req.headers['x-ucbrowser-ua'] as string; 8 | } 9 | return userAgent; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/rest-express/src/utils/matchOrTrow.ts: -------------------------------------------------------------------------------- 1 | import { matchedData, validationResult } from 'express-validator'; 2 | 3 | export function matchOrThrow = Record>( 4 | ...args: Parameters 5 | ): T { 6 | if (!validationResult(args[0]).isEmpty()) { 7 | throw new Error('Validation error'); 8 | } 9 | return matchedData(...args) as T; 10 | } 11 | -------------------------------------------------------------------------------- /packages/rest-express/src/utils/send-error.ts: -------------------------------------------------------------------------------- 1 | export const sendError = (res: any, err: any) => 2 | res.status(400).json({ 3 | message: err.message, 4 | code: err.code, 5 | }); 6 | -------------------------------------------------------------------------------- /packages/rest-express/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/server/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/server 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/server)](https://www.npmjs.com/package/@accounts/server) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/server)](https://www.npmjs.com/package/@accounts/server) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | ## Documentation 9 | 10 | - [Website documentation](https://www.accountsjs.com/docs/server) 11 | - [API documentation](https://www.accountsjs.com/docs/api/server/globals) 12 | 13 | ## Installation 14 | 15 | ``` 16 | yarn add @accounts/server 17 | ``` 18 | 19 | ## Contributing 20 | 21 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 22 | -------------------------------------------------------------------------------- /packages/server/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import 'reflect-metadata'; 2 | import AccountsServer from '../src'; 3 | 4 | describe('AccountsServer', () => { 5 | it('should have default export AccountsServer', () => { 6 | expect(typeof AccountsServer).toBe('function'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/server/__tests__/utils/get-first-user-email.ts: -------------------------------------------------------------------------------- 1 | import { getFirstUserEmail } from '../../src/utils/get-first-user-email'; 2 | 3 | describe('getFirstUserEmail', () => { 4 | it('should throw errors', () => { 5 | const user: any = {}; 6 | const email = 'a@b.test'; 7 | expect(() => getFirstUserEmail(user, email)).toThrow(); 8 | expect(() => getFirstUserEmail(user, '')).toThrow(); 9 | }); 10 | 11 | it('return the correct email', () => { 12 | const email = 'a@b.test'; 13 | const email2 = 'c@d.test'; 14 | const user: any = { 15 | emails: [ 16 | { 17 | address: email, 18 | }, 19 | { 20 | address: email2, 21 | }, 22 | ], 23 | }; 24 | expect(getFirstUserEmail(user, '')).toEqual(email); 25 | expect(getFirstUserEmail(user, email2)).toEqual(email2); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /packages/server/src/types/AccountsCoreConfig.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type AccountsServerOptions } from './accounts-server-options'; 3 | 4 | export const AccountsCoreConfigToken = new InjectionToken( 5 | 'AccountsCoreConfig' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/server/src/types/AuthenticationServices.symbol.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from 'graphql-modules'; 2 | import { type AuthenticationServices } from './authentication-services'; 3 | 4 | export const AuthenticationServicesToken = new InjectionToken( 5 | 'AuthenticationServices' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/server/src/types/DatabaseInterfaceSessions.symbol.ts: -------------------------------------------------------------------------------- 1 | import { type DatabaseInterfaceSessions } from '@accounts/types'; 2 | import { InjectionToken } from 'graphql-modules'; 3 | 4 | export const DatabaseInterfaceSessionsToken = new InjectionToken( 5 | 'DatabaseInterfaceSessions' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/server/src/types/DatabaseInterfaceUser.symbol.ts: -------------------------------------------------------------------------------- 1 | import { type DatabaseInterfaceUser } from '@accounts/types'; 2 | import { InjectionToken } from 'graphql-modules'; 3 | 4 | export const DatabaseInterfaceUserToken = new InjectionToken( 5 | 'DatabaseInterfaceUser' 6 | ); 7 | -------------------------------------------------------------------------------- /packages/server/src/types/authentication-services.ts: -------------------------------------------------------------------------------- 1 | import { type AuthenticationService, type User } from '@accounts/types'; 2 | 3 | export interface AuthenticationServices { 4 | [key: string]: 5 | | (new (args: any) => AuthenticationService) 6 | | AuthenticationService 7 | | undefined; 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/src/types/email-template-type.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '@accounts/types'; 2 | 3 | export interface EmailTemplateType { 4 | from?: string; 5 | subject: (user?: User) => string; 6 | text: (user: User, url: string) => string; 7 | html?: (user: User, url: string) => string; 8 | } 9 | -------------------------------------------------------------------------------- /packages/server/src/types/email-templates-type.ts: -------------------------------------------------------------------------------- 1 | import { type EmailTemplateType } from './email-template-type'; 2 | 3 | export interface EmailTemplatesType { 4 | from: string; 5 | verifyEmail: EmailTemplateType; 6 | resetPassword: EmailTemplateType; 7 | enrollAccount: EmailTemplateType; 8 | passwordChanged: EmailTemplateType; 9 | magicLink: EmailTemplateType; 10 | } 11 | -------------------------------------------------------------------------------- /packages/server/src/types/email-type.ts: -------------------------------------------------------------------------------- 1 | import { type EmailTemplateType } from './email-template-type'; 2 | 3 | export type EmailType = EmailTemplateType & { to: string }; 4 | -------------------------------------------------------------------------------- /packages/server/src/types/jwt-data.ts: -------------------------------------------------------------------------------- 1 | export interface JwtData { 2 | token: string; 3 | isImpersonated: boolean; 4 | userId: string; 5 | } 6 | -------------------------------------------------------------------------------- /packages/server/src/types/jwt-payload.ts: -------------------------------------------------------------------------------- 1 | import { type JwtData } from './jwt-data'; 2 | 3 | export interface JwtPayload { 4 | data: JwtData; 5 | [key: string]: any; 6 | } 7 | -------------------------------------------------------------------------------- /packages/server/src/types/prepare-mail-function.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '@accounts/types'; 2 | import { type EmailTemplateType } from './email-template-type'; 3 | 4 | export type PrepareMailFunction = ( 5 | to: string, 6 | token: string, 7 | user: User, 8 | pathFragment: string, 9 | emailTemplate: EmailTemplateType, 10 | from: string 11 | ) => object; 12 | -------------------------------------------------------------------------------- /packages/server/src/types/send-mail-type.ts: -------------------------------------------------------------------------------- 1 | export type SendMailType = (mail: any) => Promise; 2 | -------------------------------------------------------------------------------- /packages/server/src/types/token-creator.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '@accounts/types'; 2 | 3 | export interface TokenCreator { 4 | createToken(user: User): Promise; 5 | } 6 | -------------------------------------------------------------------------------- /packages/server/src/utils/accounts-error.ts: -------------------------------------------------------------------------------- 1 | export class AccountsJsError extends Error { 2 | public code: string; 3 | 4 | constructor(message: string, code: string) { 5 | super(message); 6 | this.code = code; 7 | Object.setPrototypeOf(this, new.target.prototype); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/server/src/utils/get-first-user-email.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '@accounts/types'; 2 | 3 | export function getFirstUserEmail(user: User, address: string): string { 4 | // Pick the first email if we weren't passed an email 5 | if (!address) { 6 | if (user.emails && user.emails[0]) { 7 | address = user.emails[0].address; 8 | } else { 9 | throw new Error("User doesn't have an email address"); 10 | } 11 | } 12 | 13 | const validAddresses = user.emails?.map((email) => email.address) ?? []; 14 | const addressIsValid = validAddresses.includes(address); 15 | if (!addressIsValid) { 16 | throw new Error('No such email address for user'); 17 | } 18 | 19 | return address; 20 | } 21 | -------------------------------------------------------------------------------- /packages/server/src/utils/server-hooks.ts: -------------------------------------------------------------------------------- 1 | export const ServerHooks = { 2 | ValidateLogin: 'ValidateLogin', 3 | LoginSuccess: 'LoginSuccess', 4 | LoginError: 'LoginError', 5 | AuthenticateSuccess: 'AuthenticateSuccess', 6 | AuthenticateError: 'AuthenticateError', 7 | LogoutSuccess: 'LogoutSuccess', 8 | LogoutError: 'LogoutError', 9 | CreateUserSuccess: 'CreateUserSuccess', 10 | CreateUserError: 'CreateUserError', 11 | ResumeSessionSuccess: 'ResumeSessionSuccess', 12 | ResumeSessionError: 'ResumeSessionError', 13 | RefreshTokensSuccess: 'RefreshTokensSuccess', 14 | RefreshTokensError: 'RefreshTokensError', 15 | ImpersonationSuccess: 'ImpersonationSuccess', 16 | ImpersonationError: 'ImpersonationError', 17 | ResetPasswordSuccess: 'ResetPasswordSuccess', 18 | ChangePasswordSuccess: 'ChangePasswordSuccess', 19 | }; 20 | -------------------------------------------------------------------------------- /packages/server/src/utils/tokens.ts: -------------------------------------------------------------------------------- 1 | import * as jwt from 'jsonwebtoken'; 2 | import { randomBytes } from 'crypto'; 3 | 4 | /** 5 | * Generate a random token string 6 | */ 7 | export const generateRandomToken = (length = 43): string => randomBytes(length).toString('hex'); 8 | 9 | export const generateAccessToken = ({ 10 | secret, 11 | payload = {}, 12 | config, 13 | }: { 14 | secret: jwt.Secret; 15 | payload?: any; 16 | config: jwt.SignOptions; 17 | }) => jwt.sign(payload, secret, config); 18 | 19 | export const generateRefreshToken = ({ 20 | secret, 21 | payload = {}, 22 | config, 23 | }: { 24 | secret: jwt.Secret; 25 | payload?: any; 26 | config: jwt.SignOptions; 27 | }) => jwt.sign(payload, secret, config); 28 | -------------------------------------------------------------------------------- /packages/server/src/utils/validation.ts: -------------------------------------------------------------------------------- 1 | export const isString = (x: any): x is string => { 2 | return typeof x === 'string'; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "experimentalDecorators": true, 5 | "emitDecoratorMetadata": true, 6 | "outDir": "./lib", 7 | "importHelpers": true 8 | }, 9 | "include": ["src/**/*.ts"], 10 | "exclude": ["node_modules"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/two-factor/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/two-factor 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/two-factor.svg)](https://www.npmjs.com/package/@accounts/two-factor) 4 | ![MIT License](https://img.shields.io/badge/license-MIT-blue.svg) 5 | -------------------------------------------------------------------------------- /packages/two-factor/__tests__/__snapshots__/errors.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`errors should have named export errors 1`] = ` 4 | { 5 | "codeDidNotMatch": "2FA code didn't match", 6 | "codeRequired": "2FA code required", 7 | "userNotFound": "User not found", 8 | "userTwoFactorAlreadySet": "2FA already set", 9 | "userTwoFactorNotSet": "2FA not set", 10 | } 11 | `; 12 | -------------------------------------------------------------------------------- /packages/two-factor/__tests__/errors.ts: -------------------------------------------------------------------------------- 1 | import { errors } from '../src/errors'; 2 | 3 | describe('errors', () => { 4 | it('should have named export errors', () => { 5 | expect(errors).toMatchSnapshot(); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/two-factor/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | import { TwoFactor } from '../src'; 2 | 3 | describe('TwoFactor', () => { 4 | it('should have named export TwoFactor', () => { 5 | expect(typeof TwoFactor).toBe('function'); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /packages/two-factor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@accounts/two-factor", 3 | "version": "0.32.4", 4 | "license": "MIT", 5 | "main": "lib/index.js", 6 | "typings": "lib/index.d.ts", 7 | "publishConfig": { 8 | "access": "public" 9 | }, 10 | "scripts": { 11 | "clean": "yarn run -T rimraf lib", 12 | "start": "yarn run -T tsc --watch", 13 | "precompile": "yarn run clean", 14 | "compile": "yarn run -T tsc", 15 | "prepublishOnly": "yarn run compile", 16 | "test": "yarn run test", 17 | "testonly": "yarn run -T jest", 18 | "coverage": "yarn run -T jest --coverage" 19 | }, 20 | "files": [ 21 | "src", 22 | "lib" 23 | ], 24 | "jest": { 25 | "testEnvironment": "node", 26 | "preset": "ts-jest" 27 | }, 28 | "dependencies": { 29 | "@levminer/speakeasy": "1.4.2", 30 | "tslib": "2.6.2" 31 | }, 32 | "devDependencies": { 33 | "@accounts/types": "^0.33.2" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /packages/two-factor/src/errors.ts: -------------------------------------------------------------------------------- 1 | import { type ErrorMessages } from './types'; 2 | 3 | export const errors: ErrorMessages = { 4 | userNotFound: 'User not found', 5 | codeDidNotMatch: `2FA code didn't match`, 6 | userTwoFactorNotSet: `2FA not set`, 7 | userTwoFactorAlreadySet: `2FA already set`, 8 | codeRequired: '2FA code required', 9 | }; 10 | -------------------------------------------------------------------------------- /packages/two-factor/src/index.ts: -------------------------------------------------------------------------------- 1 | export { TwoFactor } from './two-factor'; 2 | export { AccountsTwoFactorOptions } from './types'; 3 | export { getUserTwoFactorService } from './utils'; 4 | -------------------------------------------------------------------------------- /packages/two-factor/src/types/error-messages.ts: -------------------------------------------------------------------------------- 1 | export interface ErrorMessages { 2 | /** 3 | * Default to 'User not found' 4 | */ 5 | userNotFound: string; 6 | /** 7 | * Default to '2FA code didn't match' 8 | */ 9 | codeDidNotMatch: string; 10 | /** 11 | * Default to '2FA not set' 12 | */ 13 | userTwoFactorNotSet: string; 14 | /** 15 | * Default to '2FA already set' 16 | */ 17 | userTwoFactorAlreadySet: string; 18 | /** 19 | * Default to '2FA code required' 20 | */ 21 | codeRequired: string; 22 | } 23 | -------------------------------------------------------------------------------- /packages/two-factor/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountsTwoFactorOptions } from './options'; 2 | export { TwoFactorService } from './two-factor-service'; 3 | export { ErrorMessages } from './error-messages'; 4 | -------------------------------------------------------------------------------- /packages/two-factor/src/types/options.ts: -------------------------------------------------------------------------------- 1 | import { type ErrorMessages } from './error-messages'; 2 | 3 | export interface AccountsTwoFactorOptions { 4 | /** 5 | * Two factor app name 6 | */ 7 | appName?: string; 8 | /** 9 | * Two factor secret length, default to 20 10 | */ 11 | secretLength?: number; 12 | window?: number; 13 | /** 14 | * Two factor module errors 15 | */ 16 | errors?: ErrorMessages; 17 | } 18 | -------------------------------------------------------------------------------- /packages/two-factor/src/types/two-factor-service.ts: -------------------------------------------------------------------------------- 1 | import { type GeneratedSecret } from '@levminer/speakeasy'; 2 | 3 | export interface TwoFactorService { 4 | secret: GeneratedSecret; 5 | } 6 | -------------------------------------------------------------------------------- /packages/two-factor/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export { getUserTwoFactorService } from './user'; 2 | -------------------------------------------------------------------------------- /packages/two-factor/src/utils/user.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '@accounts/types'; 2 | import { type TwoFactorService } from '../types'; 3 | 4 | /** 5 | * Return the user two factor service object 6 | */ 7 | export const getUserTwoFactorService = (user: User): TwoFactorService | null => { 8 | return user.services?.['two-factor'] ?? null; 9 | }; 10 | -------------------------------------------------------------------------------- /packages/two-factor/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/types/README.md: -------------------------------------------------------------------------------- 1 | # @accounts/types 2 | 3 | [![npm](https://img.shields.io/npm/v/@accounts/types)](https://www.npmjs.com/package/@accounts/types) 4 | [![npm downloads](https://img.shields.io/npm/dm/@accounts/types)](https://www.npmjs.com/package/@accounts/types) 5 | [![codecov](https://img.shields.io/codecov/c/github/accounts-js/accounts)](https://codecov.io/gh/accounts-js/accounts) 6 | [![License](https://img.shields.io/github/license/accounts-js/accounts)](https://github.com/accounts-js/accounts/blob/master/LICENSE) 7 | 8 | This package is a devDependency for most packages of the suite. 9 | 10 | It contains the types used across the accounts-js Suite. 11 | 12 | ## Installation 13 | 14 | ``` 15 | yarn add @accounts/types 16 | ``` 17 | 18 | ## Contributing 19 | 20 | Any contribution is very welcome, read our [contributing guide](https://github.com/accounts-js/accounts/blob/master/CONTRIBUTING.md) to see how to locally setup the repository and see our development process. 21 | -------------------------------------------------------------------------------- /packages/types/__tests__/index.ts: -------------------------------------------------------------------------------- 1 | // import * as src from '../src'; 2 | 3 | it('should not export anything', () => { 4 | // expect(Object.values(src).every((type) => type === undefined)).toBe(true); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/types/src/types/authentication-service.ts: -------------------------------------------------------------------------------- 1 | import { type User } from './user'; 2 | import { type DatabaseInterfaceUser } from './user/database-interface'; 3 | import { type DatabaseInterfaceSessions } from './session/database-interface'; 4 | 5 | // TODO : Fix circular dependency for better type checking 6 | // import AccountsServer from '@accounts/server'; 7 | 8 | export interface AuthenticationService { 9 | server: any; 10 | serviceName: string; 11 | setUserStore(store: DatabaseInterfaceUser): void; 12 | setSessionsStore(store: DatabaseInterfaceSessions): void; 13 | authenticate(params: any): Promise; 14 | } 15 | -------------------------------------------------------------------------------- /packages/types/src/types/connection-informations.ts: -------------------------------------------------------------------------------- 1 | export interface ConnectionInformations { 2 | ip?: string | null; 3 | userAgent?: string | null; 4 | [key: string]: any; 5 | } 6 | -------------------------------------------------------------------------------- /packages/types/src/types/context.ts: -------------------------------------------------------------------------------- 1 | import { type ConnectionInformations } from './connection-informations'; 2 | import { type User } from './user'; 3 | 4 | export interface IContext { 5 | authToken?: string; 6 | user?: IUser; 7 | userId?: string; 8 | userAgent: string | null; 9 | ip: string | null; 10 | infos: ConnectionInformations; 11 | } 12 | -------------------------------------------------------------------------------- /packages/types/src/types/create-user-result.ts: -------------------------------------------------------------------------------- 1 | import { type LoginResult } from './login-result'; 2 | 3 | export interface CreateUserResult { 4 | /** 5 | * Will be returned only if 'ambiguousErrorMessages' is set to false or 'requireEmailVerification' is set to false. 6 | */ 7 | userId?: string; 8 | /** 9 | * Will be returned only if 'enableAutologin' is set to true and 'requireEmailVerification' is set to false. 10 | */ 11 | loginResult?: LoginResult; 12 | } 13 | -------------------------------------------------------------------------------- /packages/types/src/types/create-user.ts: -------------------------------------------------------------------------------- 1 | export interface CreateUser { 2 | username?: string; 3 | email?: string; 4 | [additionalKey: string]: any; 5 | } 6 | -------------------------------------------------------------------------------- /packages/types/src/types/database-interface.ts: -------------------------------------------------------------------------------- 1 | import { type User } from './user'; 2 | import { type DatabaseInterfaceSessions } from './session/database-interface'; 3 | import { type DatabaseInterfaceUser } from './user/database-interface'; 4 | 5 | export interface DatabaseInterface 6 | extends DatabaseInterfaceSessions, 7 | DatabaseInterfaceUser {} 8 | -------------------------------------------------------------------------------- /packages/types/src/types/database-type.ts: -------------------------------------------------------------------------------- 1 | export enum DatabaseType { 2 | User = 'user', 3 | Both = 'db', 4 | Sessions = 'sessions', 5 | } 6 | -------------------------------------------------------------------------------- /packages/types/src/types/email-record.ts: -------------------------------------------------------------------------------- 1 | export interface EmailRecord { 2 | address: string; 3 | verified: boolean; 4 | } 5 | -------------------------------------------------------------------------------- /packages/types/src/types/hook-listener.ts: -------------------------------------------------------------------------------- 1 | export type HookListener = (event?: any) => void; 2 | -------------------------------------------------------------------------------- /packages/types/src/types/impersonation-result.ts: -------------------------------------------------------------------------------- 1 | import { type Tokens } from './tokens'; 2 | import { type User } from './user'; 3 | 4 | export interface ImpersonationUserIdentity { 5 | userId?: string; 6 | username?: string; 7 | email?: string; 8 | } 9 | 10 | export interface ImpersonationResult { 11 | authorized: boolean; 12 | tokens?: Tokens; 13 | user?: User; 14 | } 15 | -------------------------------------------------------------------------------- /packages/types/src/types/login-result.ts: -------------------------------------------------------------------------------- 1 | import { type Tokens } from './tokens'; 2 | import { type User } from './user'; 3 | 4 | export interface LoginResult { 5 | sessionId: string; 6 | tokens: Tokens; 7 | user: User; 8 | } 9 | -------------------------------------------------------------------------------- /packages/types/src/types/login-user-identity.ts: -------------------------------------------------------------------------------- 1 | export interface LoginUserIdentity { 2 | id?: string; 3 | username?: string; 4 | email?: string; 5 | } 6 | -------------------------------------------------------------------------------- /packages/types/src/types/services/magic-link/database-interface.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '../../user'; 2 | 3 | export interface DatabaseInterfaceServiceMagicLink { 4 | findUserByLoginToken(token: string): Promise; 5 | 6 | addLoginToken(userId: string, email: string, token: string): Promise; 7 | 8 | removeAllLoginTokens(userId: string): Promise; 9 | } 10 | -------------------------------------------------------------------------------- /packages/types/src/types/services/magic-link/login-user.ts: -------------------------------------------------------------------------------- 1 | export interface LoginUserMagicLinkService { 2 | token: string; 3 | } 4 | -------------------------------------------------------------------------------- /packages/types/src/types/services/password/create-user.ts: -------------------------------------------------------------------------------- 1 | import { type CreateUser } from '../../create-user'; 2 | 3 | export interface CreateUserServicePassword extends CreateUser { 4 | username?: string; 5 | email?: string; 6 | password: string; 7 | } 8 | -------------------------------------------------------------------------------- /packages/types/src/types/services/password/login-user.ts: -------------------------------------------------------------------------------- 1 | import { type LoginUserIdentity } from '../../login-user-identity'; 2 | 3 | export interface LoginUserPasswordService { 4 | user: string | LoginUserIdentity; 5 | password: string; 6 | // 2FA code 7 | code?: string; 8 | } 9 | -------------------------------------------------------------------------------- /packages/types/src/types/session/database-interface.ts: -------------------------------------------------------------------------------- 1 | import { type Session } from './session'; 2 | import { type ConnectionInformations } from '../connection-informations'; 3 | 4 | export interface DatabaseInterfaceSessions { 5 | findSessionById(sessionId: string): Promise; 6 | 7 | findSessionByToken(token: string): Promise; 8 | 9 | createSession( 10 | userId: string, 11 | token: string, 12 | connection: ConnectionInformations, 13 | extraData?: object 14 | ): Promise; 15 | 16 | updateSession( 17 | sessionId: string, 18 | connection: ConnectionInformations, 19 | newToken?: string 20 | ): Promise; 21 | 22 | invalidateSession(sessionId: string): Promise; 23 | 24 | invalidateAllSessions(userId: string, excludedSessionIds?: string[]): Promise; 25 | } 26 | -------------------------------------------------------------------------------- /packages/types/src/types/session/session.ts: -------------------------------------------------------------------------------- 1 | export interface Session { 2 | id: string; 3 | userId: string; 4 | token: string; 5 | valid: boolean; 6 | userAgent?: string | null; 7 | ip?: string | null; 8 | createdAt: string; 9 | updatedAt: string; 10 | extraData?: { impersonatorUserId?: string }; 11 | } 12 | -------------------------------------------------------------------------------- /packages/types/src/types/token-record.ts: -------------------------------------------------------------------------------- 1 | export interface TokenRecord { 2 | token: string; 3 | address: string; 4 | when: number; 5 | reason: string; 6 | } 7 | -------------------------------------------------------------------------------- /packages/types/src/types/tokens.ts: -------------------------------------------------------------------------------- 1 | export interface Tokens { 2 | accessToken: string; 3 | refreshToken: string; 4 | } 5 | -------------------------------------------------------------------------------- /packages/types/src/types/user.ts: -------------------------------------------------------------------------------- 1 | import { type EmailRecord } from './email-record'; 2 | 3 | export interface User { 4 | username?: string; 5 | emails?: EmailRecord[]; 6 | id: string; 7 | services?: Record; 8 | deactivated: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /packages/types/src/types/user/database-interface.ts: -------------------------------------------------------------------------------- 1 | import { type User } from '../user'; 2 | import { type DatabaseInterfaceServicePassword } from '../services/password/database-interface'; 3 | import { type DatabaseInterfaceServiceMagicLink } from '../services/magic-link/database-interface'; 4 | 5 | export interface DatabaseInterfaceUser 6 | extends DatabaseInterfaceServicePassword, 7 | DatabaseInterfaceServiceMagicLink { 8 | // Find user by identity fields 9 | findUserById(userId: string): Promise; 10 | 11 | // Auth services related operations 12 | findUserByServiceId(serviceName: string, serviceId: string): Promise; 13 | 14 | setService(userId: string, serviceName: string, data: object): Promise; 15 | 16 | unsetService(userId: string, serviceName: string): Promise; 17 | 18 | setUserDeactivated(userId: string, deactivated: boolean): Promise; 19 | } 20 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig", 3 | "compilerOptions": { 4 | "outDir": "./lib", 5 | "importHelpers": true 6 | }, 7 | "include": ["src/**/*.ts"], 8 | "exclude": ["node_modules"] 9 | } 10 | -------------------------------------------------------------------------------- /res/Design.md: -------------------------------------------------------------------------------- 1 | # Design 2 | 3 | The js-accounts organization was setup with the mission of writing a complete and modular accounts system. 4 | 5 | ## Packages structure 6 | 7 | In order to reach those goals, we split the accounts suite into abstraction layers and a number of packages 8 | that each can implement at most one layer. 9 | 10 | Those layers exports contracts in the form of Flow interfaces. 11 | Communication between the layers is done only using those interfaces. 12 | 13 | ![alt text](/res/packages.jpg 'Package structure') 14 | -------------------------------------------------------------------------------- /res/packages.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accounts-js/accounts/67c77b06d2f2ee88c08174084ba17b1819656bc0/res/packages.jpg -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "lib": ["es2023"], 5 | "module": "commonjs", 6 | "moduleResolution": "node", 7 | "sourceMap": true, 8 | "declaration": true, 9 | "pretty": true, 10 | "strict": true, 11 | "esModuleInterop": true, 12 | "emitDecoratorMetadata": true, 13 | "experimentalDecorators": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | # Custom 23 | docs/api 24 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /website/docs/cookbook/react-native.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: react-native 3 | title: react-native 4 | sidebar_label: react-native 5 | --- 6 | 7 | By default accounts-js use the `localStorage` api to store the tokens. 8 | 9 | Since react-native does not have `localStorage`, we can use the [React Native Async Storage](https://github.com/react-native-community/async-storage). 10 | 11 | To setup the client to use the AsyncStorage api you need to apply the following configuration: 12 | 13 | ```javascript 14 | import AsyncStorage from '@react-native-community/async-storage'; 15 | import { AccountsClient } from '@accounts/client'; 16 | 17 | const accounts = new AccountsClient({ 18 | // We tell the accounts-js client to use AsyncStorage to store the tokens 19 | tokenStorage: AsyncStorage, 20 | }); 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/databases/mikro-orm.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: mikro-orm 3 | title: MikroORM 4 | sidebar_label: MikroORM 5 | --- 6 | 7 | Placeholder. 8 | -------------------------------------------------------------------------------- /website/docs/databases/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: overview 3 | title: Overview 4 | sidebar_label: Overview 5 | --- 6 | 7 | The accounts-js database adapters provide a way to interact with any database by implementing the `DatabaseInterface` common interface exported by `@accounts/types`. It means that if we don't provide an official adapter for your database, an adapter can be created to make accounts-js work with your database. 8 | 9 | The following adapters are officially supported: 10 | 11 | - [@accounts/mongo](/docs/databases/mongo) - A database adapter for [MongoDB](https://www.mongodb.com/) 12 | - [@accounts/redis](/docs/databases/redis) - A database adapter for [Redis](https://redis.io/) (session only) 13 | - [@accounts/typeorm](/docs/databases/typeorm) - A database adapter for [PostgreSQL](https://www.postgresql.org/) using [TypeORM](https://typeorm.io/) 14 | -------------------------------------------------------------------------------- /website/docs/strategies/facebook.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Facebook 3 | --- 4 | 5 | [Github](https://github.com/accounts-js/accounts/tree/master/packages/oauth-facebook) | 6 | [npm](https://www.npmjs.com/package/@accounts/oauth-facebook) 7 | 8 | _OAuth Facebook Strategy for accounts-js_ 9 | 10 | ## Install 11 | 12 | ``` 13 | yarn add @accounts/oauth @accounts/oauth-facebook 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```javascript 19 | import AccountsServer from '@accounts/server'; 20 | import AccountsOauth from '@accounts/oauth'; 21 | import AccountsOAuthFacebook from '@accounts/oauth-facebook'; 22 | 23 | const accountsOauth = new AccountsOauth({ 24 | facebook: { 25 | key: 'your-facebook-client-id', 26 | secret: 'your-facebook-client-secret', 27 | }, 28 | )); 29 | 30 | const accountsServer = new AccountsServer(...config, { 31 | password: password, 32 | oauth: accountsOauth, 33 | }); 34 | ``` 35 | -------------------------------------------------------------------------------- /website/docs/strategies/twitter.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Twitter 3 | --- 4 | 5 | [Github](https://github.com/accounts-js/accounts/tree/master/packages/oauth-twitter) | 6 | [npm](https://www.npmjs.com/package/@accounts/oauth-twitter) 7 | 8 | _OAuth Twitter Strategy for accounts-js_ 9 | 10 | ## Install 11 | 12 | ``` 13 | yarn add @accounts/oauth @accounts/oauth-twitter 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```javascript 19 | import AccountsServer from '@accounts/server'; 20 | import AccountsOauth from '@accounts/oauth'; 21 | import AccountsOAuthTwitter from '@accounts/oauth-twitter'; 22 | 23 | const accountsOauth = new AccountsOauth({ 24 | twitter: { 25 | key: 'your-twitter-consumer-key', 26 | secret: 'your-twitter-consumer-secret', 27 | }, 28 | )); 29 | 30 | const accountsServer = new AccountsServer(...config, { 31 | password: password, 32 | oauth: accountsOauth, 33 | }); 34 | ``` 35 | -------------------------------------------------------------------------------- /website/docs/transports/rest-client.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: rest-client 3 | title: Rest Client 4 | sidebar_label: Client 5 | --- 6 | 7 | [Github](https://github.com/accounts-js/accounts/tree/master/packages/rest-client) | 8 | [npm](https://www.npmjs.com/package/@accounts/rest-client) 9 | 10 | _REST client for accounts-js_ 11 | 12 | ### Install 13 | 14 | ``` 15 | yarn add @accounts/rest-client 16 | ``` 17 | 18 | ### Usage 19 | 20 | ```javascript 21 | import { AccountsClient } from '@accounts/client'; 22 | import { RestClient } from '@accounts/rest-client'; 23 | 24 | const accountsRest = new RestClient({ 25 | apiHost: 'http://localhost:4000', 26 | rootPath: '/accounts', 27 | }); 28 | const accounts = new AccountsClient({}, accountsRest); 29 | ``` 30 | 31 | ### Options 32 | 33 | ```javascript 34 | const options = { 35 | apiHost: string, 36 | // Path that prefix the accounts-js routes 37 | rootPath: string, 38 | }; 39 | ``` 40 | -------------------------------------------------------------------------------- /website/docs/transports/rest-express.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: rest-express 3 | title: Rest Express 4 | sidebar_label: Express 5 | --- 6 | 7 | [Github](https://github.com/accounts-js/accounts/tree/master/packages/rest-express) | 8 | [npm](https://www.npmjs.com/package/@accounts/rest-express) 9 | 10 | _REST server for accounts-js_ 11 | 12 | ### Install 13 | 14 | ``` 15 | yarn add @accounts/rest-express 16 | ``` 17 | 18 | ### Usage 19 | 20 | ```javascript 21 | import express from 'express'; 22 | import AccountsServer from '@accounts/server'; 23 | import accountsExpress from '@accounts/rest-express'; 24 | 25 | const accountsServer = new AccountsServer(...); 26 | 27 | const app = express(); 28 | app.use(bodyParser.json()); 29 | app.use(bodyParser.urlencoded({ extended: true })); 30 | 31 | app.use(accountsExpress(accountsServer)); 32 | 33 | app.listen(3000); 34 | ``` 35 | 36 | ### Options 37 | 38 | ```javascript 39 | const options = { 40 | // Path that prefix the express routes for the accounts middleware 41 | path: string, 42 | }; 43 | 44 | app.use(accountsExpress(accountsServer, accountsExpressOptions)); 45 | ``` 46 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | docs: { 3 | Introduction: ['introduction', 'contributing'], 4 | 'Getting started': ['getting-started', 'server', 'handling-errors', 'email', 'client'], 5 | Transports: [ 6 | 'transports/graphql', 7 | { 8 | type: 'category', 9 | label: 'Rest', 10 | items: ['transports/rest-express', 'transports/rest-client'], 11 | }, 12 | ], 13 | Databases: [ 14 | 'databases/overview', 15 | 'databases/mongo', 16 | 'databases/redis', 17 | 'databases/typeorm', 18 | 'databases/mikro-orm', 19 | ], 20 | Strategies: [ 21 | { 22 | type: 'category', 23 | label: 'Password', 24 | items: ['strategies/password', 'strategies/password-client'], 25 | }, 26 | 'strategies/facebook', 27 | 'strategies/oauth', 28 | 'strategies/twitter', 29 | ], 30 | Cookbook: ['cookbook/react-native'], 31 | }, 32 | }; 33 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #77BBBC; 10 | --ifm-color-primary-dark: rgb(33, 175, 144); 11 | --ifm-color-primary-darker: rgb(31, 165, 136); 12 | --ifm-color-primary-darkest: rgb(26, 136, 112); 13 | --ifm-color-primary-light: rgb(70, 203, 174); 14 | --ifm-color-primary-lighter: rgb(102, 212, 189); 15 | --ifm-color-primary-lightest: rgb(146, 224, 208); 16 | --ifm-code-font-size: 95%; 17 | } 18 | 19 | .docusaurus-highlight-code-line { 20 | background-color: rgba(0, 0, 0, 0.1); 21 | display: block; 22 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 23 | padding: 0 var(--ifm-pre-padding); 24 | } 25 | 26 | html[data-theme='dark'] .docusaurus-highlight-code-line { 27 | background-color: rgba(0, 0, 0, 0.3); 28 | } 29 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accounts-js/accounts/67c77b06d2f2ee88c08174084ba17b1819656bc0/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accounts-js/accounts/67c77b06d2f2ee88c08174084ba17b1819656bc0/website/static/img/favicon.png -------------------------------------------------------------------------------- /website/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accounts-js/accounts/67c77b06d2f2ee88c08174084ba17b1819656bc0/website/static/img/logo.png -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | ../tsconfig.json --------------------------------------------------------------------------------