Repository: Volst/graphql-authentication
Branch: master
Commit: a8f3c1a9050f
Files: 94
Total size: 163.0 KB
Directory structure:
gitextract_m2pa_iuq/
├── .editorconfig
├── .gitignore
├── .prettierrc
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── examples/
│ ├── with-prisma/
│ │ ├── .graphqlconfig.yml
│ │ ├── README.md
│ │ ├── datamodel.graphql
│ │ ├── docker-compose.yml
│ │ ├── emails/
│ │ │ ├── inviteUser/
│ │ │ │ ├── html.pug
│ │ │ │ └── subject.pug
│ │ │ ├── passwordReset/
│ │ │ │ ├── html.pug
│ │ │ │ └── subject.pug
│ │ │ └── signupUser/
│ │ │ ├── html.pug
│ │ │ └── subject.pug
│ │ ├── generated/
│ │ │ ├── prisma.graphql
│ │ │ └── prisma.ts
│ │ ├── package.json
│ │ ├── prisma.yml
│ │ ├── schema.graphql
│ │ ├── server.ts
│ │ └── utils.ts
│ ├── with-sequelize/
│ │ ├── README.md
│ │ ├── SequelizeAdapter.js
│ │ ├── database.js
│ │ ├── emails/
│ │ │ ├── inviteUser/
│ │ │ │ ├── html.pug
│ │ │ │ └── subject.pug
│ │ │ ├── passwordReset/
│ │ │ │ ├── html.pug
│ │ │ │ └── subject.pug
│ │ │ └── signupUser/
│ │ │ ├── html.pug
│ │ │ └── subject.pug
│ │ ├── package.json
│ │ ├── schema.graphql
│ │ └── server.js
│ └── with-typeorm/
│ ├── README.md
│ ├── TypeOrmAdapter.ts
│ ├── database.ts
│ ├── emails/
│ │ ├── inviteUser/
│ │ │ ├── html.pug
│ │ │ └── subject.pug
│ │ ├── passwordReset/
│ │ │ ├── html.pug
│ │ │ └── subject.pug
│ │ └── signupUser/
│ │ ├── html.pug
│ │ └── subject.pug
│ ├── entities/
│ │ └── User.ts
│ ├── ormconfig.json
│ ├── package.json
│ ├── schema.graphql
│ ├── server.ts
│ └── tsconfig.json
├── lerna.json
├── live-demo/
│ ├── InMemoryAdapter.js
│ ├── README.md
│ ├── email.js
│ ├── emails/
│ │ ├── inviteUser/
│ │ │ ├── html.pug
│ │ │ └── subject.pug
│ │ ├── passwordReset/
│ │ │ ├── html.pug
│ │ │ └── subject.pug
│ │ └── signupUser/
│ │ ├── html.pug
│ │ └── subject.pug
│ ├── index.js
│ ├── package.json
│ └── schema.graphql
├── package.json
├── packages/
│ ├── graphql-authentication/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── schema.graphql
│ │ ├── src/
│ │ │ ├── Adapter.ts
│ │ │ ├── Config.ts
│ │ │ ├── __tests__/
│ │ │ │ ├── mutations.ts
│ │ │ │ ├── queries.ts
│ │ │ │ └── setup.ts
│ │ │ ├── binding.ts
│ │ │ ├── errors.ts
│ │ │ ├── index.ts
│ │ │ ├── mutations.ts
│ │ │ ├── queries.ts
│ │ │ ├── schema.ts
│ │ │ └── utils.ts
│ │ ├── tsconfig.build.json
│ │ └── tsconfig.json
│ └── graphql-authentication-prisma/
│ ├── README.md
│ ├── package.json
│ ├── src/
│ │ ├── Prisma.ts
│ │ ├── generated/
│ │ │ ├── prisma.graphql
│ │ │ └── prisma.ts
│ │ ├── index.ts
│ │ └── utils.ts
│ ├── tsconfig.build.json
│ └── tsconfig.json
├── tsconfig.base.json
├── tsconfig.json
└── tslint.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
================================================
FILE: .gitignore
================================================
node_modules
dist
*.log
coverage
.env
================================================
FILE: .prettierrc
================================================
{
"singleQuote": true
}
================================================
FILE: .travis.yml
================================================
sudo: false
language:
node_js
node_js:
- '8'
cache:
yarn: true
directories:
- node_modules
script:
cd packages/graphql-authentication && npm run ci
================================================
FILE: CONTRIBUTING.md
================================================
Pull requests and issues are very welcome!
# Prerequisites
- Node v8+
# Getting started
To get started, clone this repository and run `yarn` in the repository root. Note you have to use Yarn, npm will not work correctly.
In the `packages/` folder, pick one of the packages you want to work on. You can run the tests inside a package with `yarn test`.
If you want to use a GraphQL Playground to test something by hand, you can go to `packages/graphql-authentication-prisma/example` and run `docker-compose up -d` in it (this requires you have Docker installed). Then, run `yarn start`.
# Adding a feature or changing behavior
For features or changes, please create a new issue first. Since this is a very opinionated package, it is possible I don’t like the change. By discussing it first you can prevent wasted time. But please do! I am very open to improvements.
# Publishing packages
In the root repository, run `yarn run publish` (note: the `run` part is very important). This will make Lerna publish all the packages. After that, be sure to write a changelog on GitHubs Releases page.
================================================
FILE: LICENSE
================================================
ISC License
Copyright (c) 2018, Volst
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: README.md
================================================
# GraphQL Authentication
**Disclaimer: This repository is not actively maintained!**
_Previously called Prisma Auth_
A very opinionated user authentication package for [GraphQL](https://graphql.org/). It uses old-school email/password authentication.
This package provides **a GraphQL schema and GraphQL resolvers** for everything you need related to authentication. It does not access your data layer (e.g. an ORM); for that you need to write an _adapter_ (which is not hard to do).
If you use Prisma, there is already an adapter for you, **[graphql-authentication-prisma](https://github.com/Volst/graphql-authentication/tree/master/packages/graphql-authentication-prisma)**. You can also checkout the [`examples/`](https://github.com/Volst/graphql-authentication/tree/master/examples) folder with examples on how to write an adapter for Sequelize and TypeORM!
[**👉 Try out the live demo**](https://graphql-authentication-demo.now.sh/)
**Features:**
- Signup with good ol' email/password and confirmation email
- Login
- Invite another user (sends email)
- Password reset
- Change password of current user
- Update current user info
- Support for [graphql-shield](https://github.com/maticzav/graphql-shield) to deal with permissions
# Motivation
Adding user authentication seems simple; there are lots of examples on how to write a "login" and a "signup" resolver. You implement it in your own project and continue working. After a while you'll have users forgetting their password so you need to build something for that. Then you want to be able to invite users, ... you get the idea. In the end you have a lot of boilerplate code related to user authentication.
The intention with this package is **to let you write as less user-related code as possible**, while being flexible enough to support different use cases like open sign up, invitation-only signup, extra fields on the User model etc.
> If this package is too opinionated for you, you could still copy/paste parts of it in your application!
# Install
Node v8+ should be used. Install with Yarn or npm:
```
yarn add graphql-authentication email-templates
npm i graphql-authentication email-templates
```
# Usage
## Using the schema
In your own GraphQL schema you can import all the types this package provides:
```graphql
# import Query.*, Mutation.* from "node_modules/graphql-authentication/schema.graphql"
```
> This only works if you use [graphql-import](https://github.com/prismagraphql/graphql-import). If you are using graphql-yoga this will work out of the box!
Alternatively you can only import the types you want to expose, for example:
```graphql
# import Query.currentUser, Mutation.signupByInvite, Mutation.inviteUser, Mutation.login from "node_modules/graphql-authentication/schema.graphql"
```
## Configuration
We need to add some configuration to get this package to work. The following example uses [graphql-yoga](https://github.com/graphcool/graphql-yoga/), but it should also work with Apollo Server.
```js
import { graphqlAuthenticationConfig } from 'graphql-authentication';
import * as Email from 'email-templates';
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
context: req => ({
...req,
graphqlAuthentication: graphqlAuthenticationConfig({
// Required, see for more info the "Writing an adapter" section on this page
adapter: new GraphqlAuthenticationSequelizeAdapter(),
// Required, used for signing JWT tokens
secret: 'wheredidthesodago',
// Optional, for sending emails with email-templates (https://www.npmjs.com/package/email-templates)
mailer: new Email(),
// Optional, the URL to your frontend which is used in emails
mailAppUrl: 'http://example.com'
})
})
});
```
## Adding the resolvers
You need to expose the resolvers this package provides for you to your own GraphQL server. For example:
```js
import { authQueries, authMutations } from 'graphql-authentication';
const resolvers = {
Query: {
...authQueries
},
Mutation: {
...authMutations
}
};
```
## Emails
Lastly, this project can optionally send emails for you (e.g. the password reset link). [`email-templates`](https://www.npmjs.com/package/email-templates) is used for this. Be sure to configure it in the options:
```js
import * as Email from 'email-templates';
graphqlAuthentication: graphqlAuthenticationConfig({
mailer: new Email()
});
```
However, this package does not provide the email templates itself for you, since these differ too much. You can [**copy the email templates**](https://github.com/Volst/graphql-authentication/tree/master/examples/with-prisma/emails) from our example to get started.
# Documentation
## GraphQL endpoints
Mutations:
- `signUpByInvite`
- `signup`
- `confirmEmail`
- `inviteUser`
- `login`
- `changePassword`
- `updateCurrentUser`
- `trigerPasswordReset`
- `passwordReset`
Queries:
- `currentUser`
For more details take a look at [schema.graphql](./packages/graphql-authentication/schema.graphql).
## Authentication on endpoints
On some of your endpoints you might want to require that the user is logged in, or only allow the user to see the data if they have a specific role. A very powerful package exists for this, [graphql-shield](https://github.com/maticzav/graphql-shield):
```js
import { shield, rule } from 'graphql-shield';
import { isAuthResolver } from 'graphql-authentication';
const isAuth = rule()(isAuthResolver);
const permissions = shield({
Mutation: {
publish: isAuth
}
});
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
middlewares: [permissions]
});
```
Take a look at the [graphql-shield README](https://github.com/maticzav/graphql-shield/blob/master/README.md) to find out more.
## Helper utilities
Get the current user in a resolver (performs a request to your data layer):
```js
import { getUser } from 'graphql-authentication';
const Mutation = {
async publish(parent, data, ctx) {
const user = await getUser(ctx);
console.log('User', user.email);
}
};
```
Get only the current user ID in a resolver (without request to your data layer):
```js
import { getUserId } from 'graphql-authentication';
const Mutation = {
async publish(parent, data, ctx) {
const userId = await getUserId(ctx);
console.log('User', userId);
}
};
```
## Login and session handling
[JWT tokens](https://jwt.io/) are used to handle sessions. In the frontend you can perform a login like this:
```graphql
mutation login($email: String!, $password: String!) {
login(email: $email, password: $password) {
token
user {
# optional
name
}
}
}
```
And then save the token to `localStorage`. Now you need to send the token with every request. If you are using Apollo, [the documentation](https://www.apollographql.com/docs/react/recipes/authentication.html#Header) has a great example on how to do this.
## Adding custom fields to the User type
If you wish to expose some fields on the User type that are not exposed in our [schema.graphql](./packages/graphql-authentication/schema.graphql), you can provide your own User. In your own `schema.graphql`, do something like the following:
```graphql
# import Mutation.* from "node_modules/graphql-authentication/schema.graphql"
type Query {
currentUser: User
}
type User {
id: ID!
email: String!
name: String!
inviteAccepted: Boolean!
emailConfirmed: Boolean!
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
# And finally, our custom field:
isWillingToDance: Boolean!
}
```
If for example you do not want the `joinedAt` field to be exposed, you can simply remove it from your schema.
> `extend type User` would save some copy/pasta here, but unfortunately that doesn't work yet in `graphql-js`. [More info](https://github.com/graphcool/graphql-import/issues/42#issuecomment-357693183).
## Signup only by invite
By default everyone can signup for your project. But what if you want to only allow invite by signup? In this case you need to leave out the `Mutation.signup` import. Example:
```graphql
# import Mutation.signupByInvite, Mutation.inviteUser, Mutation.login, Mutation.changePassword, Mutation.updateCurrentUser, Mutation.triggerPasswordReset, Mutation.passwordReset, from "node_modules/graphql-authentication/schema.graphql"
```
## Making email confirmation required before login
After a user signups via the `signup` endpoint, they will get an email with a link in it to confirm their email. Meanwhile they can still login in the app. This is done to not disturb the users flow too much (e.g. services like Twitter do this too). It is left open to the project to block the user after a while. With the fields `emailConfirmed` and `joinedAt` on the User you can perhaps display a warning in your frontend or disallow certain features.
However, you might want to block the user from logging in at all when their email is not yet confirmed. In this case you need to pass this option:
```js
graphqlAuthentication: graphqlAuthenticationConfig({
requiredConfirmedEmailForLogin: true
});
```
## Custom password validation
The users password is validated with `password.length >= 8` by default. Maybe you want stricter or less stricter validation on this. You will need to pass this option to change it:
```js
graphqlAuthentication: graphqlAuthenticationConfig({
validatePassword: value => value.length >= 10
});
```
## Writing an adapter
An adapter sits between GraphQL Authentication and your own ORM/database thingy. If you are using Prisma, there is already [graphql-authentication-prisma](https://github.com/Volst/graphql-authentication/tree/master/packages/graphql-authentication-prisma) for you.
However, if you don't use Prisma, that's totally fine! Writing an adapter shouldn't take very long.
In [the tests](https://github.com/Volst/graphql-authentication/blob/refactor/packages/graphql-authentication/src/__tests__/setup.ts) there is a good example of an adapter. Also, the [`examples/`](https://github.com/Volst/graphql-authentication/tree/master/examples) folder contains more some custom adapters, like one for Sequelize.
You can keep the adapter class directly in your own project, make a separate npm package for it or write a PR to add it here (please do)!
> TODO: this section needs to be improved
================================================
FILE: examples/with-prisma/.graphqlconfig.yml
================================================
projects:
prisma:
schemaPath: "./generated/prisma.graphql"
extensions:
prisma: prisma.yml
codegen:
generator: prisma-binding
output:
binding: "generated/prisma.ts"
language: typescript
================================================
FILE: examples/with-prisma/README.md
================================================
# Prisma example
This is an example of how to use GraphQL Authentication with [Prisma](https://www.prisma.io/). It uses the adapter package for Prisma, [graphql-authentication-prisma](https://github.com/Volst/graphql-authentication/tree/master/packages/graphql-authentication-prisma).
## Usage
You need to have Docker installed. If you're new to Prisma, you might want to read the [Quickstart](https://www.prismagraphql.com/docs/quickstart/) first.
```
docker-compose up -d # now wait for it to start
yarn prisma deploy
npm i
npm start
```
Go to http://localhost:4000 in your browser and start running some queries and mutations!
================================================
FILE: examples/with-prisma/datamodel.graphql
================================================
type User {
id: ID! @unique
email: String! @unique
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean! @default(value: "true")
emailConfirmed: Boolean! @default(value: "true")
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean! @default(value: "false")
}
================================================
FILE: examples/with-prisma/docker-compose.yml
================================================
version: '3'
services:
prisma:
image: prismagraphql/prisma:1.9
restart: "no"
ports:
- "4466:4466"
environment:
PRISMA_CONFIG: |
port: 4466
managementApiSecret: "mymanagementsecret123"
databases:
default:
connector: mysql
active: true
host: db
port: 3306
user: root
password: prisma
db:
image: mysql:5.7
restart: "no"
environment:
MYSQL_ROOT_PASSWORD: prisma
================================================
FILE: examples/with-prisma/emails/inviteUser/html.pug
================================================
p Hi,
p You are invited to join *your project*!
p
a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept invite.
================================================
FILE: examples/with-prisma/emails/inviteUser/subject.pug
================================================
= `Invited for *your project*!`
================================================
FILE: examples/with-prisma/emails/passwordReset/html.pug
================================================
p Hi,
p You requested a password reset on *your project*.
p
a(href=mailAppUrl + '/login/reset-password/' + email + '/' + resetToken) Reset my password.
================================================
FILE: examples/with-prisma/emails/passwordReset/subject.pug
================================================
= `Confirm your email on *your project*`
================================================
FILE: examples/with-prisma/emails/signupUser/html.pug
================================================
p Hi,
p You have just created an account on *your project*! As a last step, please confirm your email:
p
a(href=mailAppUrl + '/confirm-email/' + email + '/' + emailConfirmToken) Confirm email.
================================================
FILE: examples/with-prisma/emails/signupUser/subject.pug
================================================
= `Confirm your email on *your project*`
================================================
FILE: examples/with-prisma/generated/prisma.graphql
================================================
# source: http://localhost:4466
# timestamp: Mon Jul 16 2018 12:37:56 GMT+0200 (CEST)
type AggregateUser {
count: Int!
}
type BatchPayload {
"""
The number of nodes that have been affected by the Batch operation.
"""
count: Long!
}
scalar DateTime
"""
The `Long` scalar type represents non-fractional signed whole numeric values.
Long can represent values between -(2^63) and 2^63 - 1.
"""
scalar Long
type Mutation {
createUser(data: UserCreateInput!): User!
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
deleteUser(where: UserWhereUniqueInput!): User
upsertUser(
where: UserWhereUniqueInput!
create: UserCreateInput!
update: UserUpdateInput!
): User!
updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
deleteManyUsers(where: UserWhereInput): BatchPayload!
}
enum MutationType {
CREATED
UPDATED
DELETED
}
"""
An object with an ID
"""
interface Node {
"""
The id of the object.
"""
id: ID!
}
"""
Information about pagination in a connection.
"""
type PageInfo {
"""
When paginating forwards, are there more items?
"""
hasNextPage: Boolean!
"""
When paginating backwards, are there more items?
"""
hasPreviousPage: Boolean!
"""
When paginating backwards, the cursor to continue.
"""
startCursor: String
"""
When paginating forwards, the cursor to continue.
"""
endCursor: String
}
type Query {
users(
where: UserWhereInput
orderBy: UserOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): [User]!
user(where: UserWhereUniqueInput!): User
usersConnection(
where: UserWhereInput
orderBy: UserOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): UserConnection!
"""
Fetches an object given its ID
"""
node(
"""
The ID of an object
"""
id: ID!
): Node
}
type Subscription {
user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}
type User implements Node {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
"""
A connection to a list of items.
"""
type UserConnection {
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
"""
A list of edges.
"""
edges: [UserEdge]!
aggregate: AggregateUser!
}
input UserCreateInput {
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean
}
"""
An edge in a connection.
"""
type UserEdge {
"""
The item at the end of the edge.
"""
node: User!
"""
A cursor for use in pagination.
"""
cursor: String!
}
enum UserOrderByInput {
id_ASC
id_DESC
email_ASC
email_DESC
password_ASC
password_DESC
name_ASC
name_DESC
inviteToken_ASC
inviteToken_DESC
inviteAccepted_ASC
inviteAccepted_DESC
emailConfirmed_ASC
emailConfirmed_DESC
emailConfirmToken_ASC
emailConfirmToken_DESC
resetToken_ASC
resetToken_DESC
resetExpires_ASC
resetExpires_DESC
deletedAt_ASC
deletedAt_DESC
lastLogin_ASC
lastLogin_DESC
joinedAt_ASC
joinedAt_DESC
isSuper_ASC
isSuper_DESC
updatedAt_ASC
updatedAt_DESC
createdAt_ASC
createdAt_DESC
}
type UserPreviousValues {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
type UserSubscriptionPayload {
mutation: MutationType!
node: User
updatedFields: [String!]
previousValues: UserPreviousValues
}
input UserSubscriptionWhereInput {
"""
Logical AND on all given filters.
"""
AND: [UserSubscriptionWhereInput!]
"""
Logical OR on all given filters.
"""
OR: [UserSubscriptionWhereInput!]
"""
Logical NOT on all given filters combined by AND.
"""
NOT: [UserSubscriptionWhereInput!]
"""
The subscription event gets dispatched when it's listed in mutation_in
"""
mutation_in: [MutationType!]
"""
The subscription event gets only dispatched when one of the updated fields names is included in this list
"""
updatedFields_contains: String
"""
The subscription event gets only dispatched when all of the field names included in this list have been updated
"""
updatedFields_contains_every: [String!]
"""
The subscription event gets only dispatched when some of the field names included in this list have been updated
"""
updatedFields_contains_some: [String!]
node: UserWhereInput
}
input UserUpdateInput {
email: String
password: String
name: String
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime
isSuper: Boolean
}
input UserWhereInput {
"""
Logical AND on all given filters.
"""
AND: [UserWhereInput!]
"""
Logical OR on all given filters.
"""
OR: [UserWhereInput!]
"""
Logical NOT on all given filters combined by AND.
"""
NOT: [UserWhereInput!]
id: ID
"""
All values that are not equal to given value.
"""
id_not: ID
"""
All values that are contained in given list.
"""
id_in: [ID!]
"""
All values that are not contained in given list.
"""
id_not_in: [ID!]
"""
All values less than the given value.
"""
id_lt: ID
"""
All values less than or equal the given value.
"""
id_lte: ID
"""
All values greater than the given value.
"""
id_gt: ID
"""
All values greater than or equal the given value.
"""
id_gte: ID
"""
All values containing the given string.
"""
id_contains: ID
"""
All values not containing the given string.
"""
id_not_contains: ID
"""
All values starting with the given string.
"""
id_starts_with: ID
"""
All values not starting with the given string.
"""
id_not_starts_with: ID
"""
All values ending with the given string.
"""
id_ends_with: ID
"""
All values not ending with the given string.
"""
id_not_ends_with: ID
email: String
"""
All values that are not equal to given value.
"""
email_not: String
"""
All values that are contained in given list.
"""
email_in: [String!]
"""
All values that are not contained in given list.
"""
email_not_in: [String!]
"""
All values less than the given value.
"""
email_lt: String
"""
All values less than or equal the given value.
"""
email_lte: String
"""
All values greater than the given value.
"""
email_gt: String
"""
All values greater than or equal the given value.
"""
email_gte: String
"""
All values containing the given string.
"""
email_contains: String
"""
All values not containing the given string.
"""
email_not_contains: String
"""
All values starting with the given string.
"""
email_starts_with: String
"""
All values not starting with the given string.
"""
email_not_starts_with: String
"""
All values ending with the given string.
"""
email_ends_with: String
"""
All values not ending with the given string.
"""
email_not_ends_with: String
password: String
"""
All values that are not equal to given value.
"""
password_not: String
"""
All values that are contained in given list.
"""
password_in: [String!]
"""
All values that are not contained in given list.
"""
password_not_in: [String!]
"""
All values less than the given value.
"""
password_lt: String
"""
All values less than or equal the given value.
"""
password_lte: String
"""
All values greater than the given value.
"""
password_gt: String
"""
All values greater than or equal the given value.
"""
password_gte: String
"""
All values containing the given string.
"""
password_contains: String
"""
All values not containing the given string.
"""
password_not_contains: String
"""
All values starting with the given string.
"""
password_starts_with: String
"""
All values not starting with the given string.
"""
password_not_starts_with: String
"""
All values ending with the given string.
"""
password_ends_with: String
"""
All values not ending with the given string.
"""
password_not_ends_with: String
name: String
"""
All values that are not equal to given value.
"""
name_not: String
"""
All values that are contained in given list.
"""
name_in: [String!]
"""
All values that are not contained in given list.
"""
name_not_in: [String!]
"""
All values less than the given value.
"""
name_lt: String
"""
All values less than or equal the given value.
"""
name_lte: String
"""
All values greater than the given value.
"""
name_gt: String
"""
All values greater than or equal the given value.
"""
name_gte: String
"""
All values containing the given string.
"""
name_contains: String
"""
All values not containing the given string.
"""
name_not_contains: String
"""
All values starting with the given string.
"""
name_starts_with: String
"""
All values not starting with the given string.
"""
name_not_starts_with: String
"""
All values ending with the given string.
"""
name_ends_with: String
"""
All values not ending with the given string.
"""
name_not_ends_with: String
inviteToken: String
"""
All values that are not equal to given value.
"""
inviteToken_not: String
"""
All values that are contained in given list.
"""
inviteToken_in: [String!]
"""
All values that are not contained in given list.
"""
inviteToken_not_in: [String!]
"""
All values less than the given value.
"""
inviteToken_lt: String
"""
All values less than or equal the given value.
"""
inviteToken_lte: String
"""
All values greater than the given value.
"""
inviteToken_gt: String
"""
All values greater than or equal the given value.
"""
inviteToken_gte: String
"""
All values containing the given string.
"""
inviteToken_contains: String
"""
All values not containing the given string.
"""
inviteToken_not_contains: String
"""
All values starting with the given string.
"""
inviteToken_starts_with: String
"""
All values not starting with the given string.
"""
inviteToken_not_starts_with: String
"""
All values ending with the given string.
"""
inviteToken_ends_with: String
"""
All values not ending with the given string.
"""
inviteToken_not_ends_with: String
inviteAccepted: Boolean
"""
All values that are not equal to given value.
"""
inviteAccepted_not: Boolean
emailConfirmed: Boolean
"""
All values that are not equal to given value.
"""
emailConfirmed_not: Boolean
emailConfirmToken: String
"""
All values that are not equal to given value.
"""
emailConfirmToken_not: String
"""
All values that are contained in given list.
"""
emailConfirmToken_in: [String!]
"""
All values that are not contained in given list.
"""
emailConfirmToken_not_in: [String!]
"""
All values less than the given value.
"""
emailConfirmToken_lt: String
"""
All values less than or equal the given value.
"""
emailConfirmToken_lte: String
"""
All values greater than the given value.
"""
emailConfirmToken_gt: String
"""
All values greater than or equal the given value.
"""
emailConfirmToken_gte: String
"""
All values containing the given string.
"""
emailConfirmToken_contains: String
"""
All values not containing the given string.
"""
emailConfirmToken_not_contains: String
"""
All values starting with the given string.
"""
emailConfirmToken_starts_with: String
"""
All values not starting with the given string.
"""
emailConfirmToken_not_starts_with: String
"""
All values ending with the given string.
"""
emailConfirmToken_ends_with: String
"""
All values not ending with the given string.
"""
emailConfirmToken_not_ends_with: String
resetToken: String
"""
All values that are not equal to given value.
"""
resetToken_not: String
"""
All values that are contained in given list.
"""
resetToken_in: [String!]
"""
All values that are not contained in given list.
"""
resetToken_not_in: [String!]
"""
All values less than the given value.
"""
resetToken_lt: String
"""
All values less than or equal the given value.
"""
resetToken_lte: String
"""
All values greater than the given value.
"""
resetToken_gt: String
"""
All values greater than or equal the given value.
"""
resetToken_gte: String
"""
All values containing the given string.
"""
resetToken_contains: String
"""
All values not containing the given string.
"""
resetToken_not_contains: String
"""
All values starting with the given string.
"""
resetToken_starts_with: String
"""
All values not starting with the given string.
"""
resetToken_not_starts_with: String
"""
All values ending with the given string.
"""
resetToken_ends_with: String
"""
All values not ending with the given string.
"""
resetToken_not_ends_with: String
resetExpires: DateTime
"""
All values that are not equal to given value.
"""
resetExpires_not: DateTime
"""
All values that are contained in given list.
"""
resetExpires_in: [DateTime!]
"""
All values that are not contained in given list.
"""
resetExpires_not_in: [DateTime!]
"""
All values less than the given value.
"""
resetExpires_lt: DateTime
"""
All values less than or equal the given value.
"""
resetExpires_lte: DateTime
"""
All values greater than the given value.
"""
resetExpires_gt: DateTime
"""
All values greater than or equal the given value.
"""
resetExpires_gte: DateTime
deletedAt: DateTime
"""
All values that are not equal to given value.
"""
deletedAt_not: DateTime
"""
All values that are contained in given list.
"""
deletedAt_in: [DateTime!]
"""
All values that are not contained in given list.
"""
deletedAt_not_in: [DateTime!]
"""
All values less than the given value.
"""
deletedAt_lt: DateTime
"""
All values less than or equal the given value.
"""
deletedAt_lte: DateTime
"""
All values greater than the given value.
"""
deletedAt_gt: DateTime
"""
All values greater than or equal the given value.
"""
deletedAt_gte: DateTime
lastLogin: DateTime
"""
All values that are not equal to given value.
"""
lastLogin_not: DateTime
"""
All values that are contained in given list.
"""
lastLogin_in: [DateTime!]
"""
All values that are not contained in given list.
"""
lastLogin_not_in: [DateTime!]
"""
All values less than the given value.
"""
lastLogin_lt: DateTime
"""
All values less than or equal the given value.
"""
lastLogin_lte: DateTime
"""
All values greater than the given value.
"""
lastLogin_gt: DateTime
"""
All values greater than or equal the given value.
"""
lastLogin_gte: DateTime
joinedAt: DateTime
"""
All values that are not equal to given value.
"""
joinedAt_not: DateTime
"""
All values that are contained in given list.
"""
joinedAt_in: [DateTime!]
"""
All values that are not contained in given list.
"""
joinedAt_not_in: [DateTime!]
"""
All values less than the given value.
"""
joinedAt_lt: DateTime
"""
All values less than or equal the given value.
"""
joinedAt_lte: DateTime
"""
All values greater than the given value.
"""
joinedAt_gt: DateTime
"""
All values greater than or equal the given value.
"""
joinedAt_gte: DateTime
isSuper: Boolean
"""
All values that are not equal to given value.
"""
isSuper_not: Boolean
}
input UserWhereUniqueInput {
id: ID
email: String
}
================================================
FILE: examples/with-prisma/generated/prisma.ts
================================================
import { GraphQLResolveInfo, GraphQLSchema } from 'graphql';
import { IResolvers } from 'graphql-tools/dist/Interfaces';
import { Options } from 'graphql-binding';
import { makePrismaBindingClass, BasePrismaOptions } from 'prisma-binding';
export interface Query {
users: <T = User[]>(
args: {
where?: UserWhereInput;
orderBy?: UserOrderByInput;
skip?: Int;
after?: String;
before?: String;
first?: Int;
last?: Int;
},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
user: <T = User | null>(
args: { where: UserWhereUniqueInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
usersConnection: <T = UserConnection>(
args: {
where?: UserWhereInput;
orderBy?: UserOrderByInput;
skip?: Int;
after?: String;
before?: String;
first?: Int;
last?: Int;
},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
node: <T = Node | null>(
args: { id: ID_Output },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
}
export interface Mutation {
createUser: <T = User>(
args: { data: UserCreateInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
updateUser: <T = User | null>(
args: { data: UserUpdateInput; where: UserWhereUniqueInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
deleteUser: <T = User | null>(
args: { where: UserWhereUniqueInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
upsertUser: <T = User>(
args: {
where: UserWhereUniqueInput;
create: UserCreateInput;
update: UserUpdateInput;
},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
updateManyUsers: <T = BatchPayload>(
args: { data: UserUpdateInput; where?: UserWhereInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
deleteManyUsers: <T = BatchPayload>(
args: { where?: UserWhereInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
}
export interface Subscription {
user: <T = UserSubscriptionPayload | null>(
args: { where?: UserSubscriptionWhereInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<AsyncIterator<T>>;
}
export interface Exists {
User: (where?: UserWhereInput) => Promise<boolean>;
}
export interface Prisma {
query: Query;
mutation: Mutation;
subscription: Subscription;
exists: Exists;
request: <T = any>(
query: string,
variables?: { [key: string]: any }
) => Promise<T>;
delegate(
operation: 'query' | 'mutation',
fieldName: string,
args: {
[key: string]: any;
},
infoOrQuery?: GraphQLResolveInfo | string,
options?: Options
): Promise<any>;
delegateSubscription(
fieldName: string,
args?: {
[key: string]: any;
},
infoOrQuery?: GraphQLResolveInfo | string,
options?: Options
): Promise<AsyncIterator<any>>;
getAbstractResolvers(filterSchema?: GraphQLSchema | string): IResolvers;
}
export interface BindingConstructor<T> {
new (options: BasePrismaOptions): T;
}
/**
* Type Defs
*/
const typeDefs = `type AggregateUser {
count: Int!
}
type BatchPayload {
"""The number of nodes that have been affected by the Batch operation."""
count: Long!
}
scalar DateTime
"""
The \`Long\` scalar type represents non-fractional signed whole numeric values.
Long can represent values between -(2^63) and 2^63 - 1.
"""
scalar Long
type Mutation {
createUser(data: UserCreateInput!): User!
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
deleteUser(where: UserWhereUniqueInput!): User
upsertUser(where: UserWhereUniqueInput!, create: UserCreateInput!, update: UserUpdateInput!): User!
updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
deleteManyUsers(where: UserWhereInput): BatchPayload!
}
enum MutationType {
CREATED
UPDATED
DELETED
}
"""An object with an ID"""
interface Node {
"""The id of the object."""
id: ID!
}
"""Information about pagination in a connection."""
type PageInfo {
"""When paginating forwards, are there more items?"""
hasNextPage: Boolean!
"""When paginating backwards, are there more items?"""
hasPreviousPage: Boolean!
"""When paginating backwards, the cursor to continue."""
startCursor: String
"""When paginating forwards, the cursor to continue."""
endCursor: String
}
type Query {
users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
user(where: UserWhereUniqueInput!): User
usersConnection(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): UserConnection!
"""Fetches an object given its ID"""
node(
"""The ID of an object"""
id: ID!
): Node
}
type Subscription {
user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}
type User implements Node {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
"""A connection to a list of items."""
type UserConnection {
"""Information to aid in pagination."""
pageInfo: PageInfo!
"""A list of edges."""
edges: [UserEdge]!
aggregate: AggregateUser!
}
input UserCreateInput {
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean
}
"""An edge in a connection."""
type UserEdge {
"""The item at the end of the edge."""
node: User!
"""A cursor for use in pagination."""
cursor: String!
}
enum UserOrderByInput {
id_ASC
id_DESC
email_ASC
email_DESC
password_ASC
password_DESC
name_ASC
name_DESC
inviteToken_ASC
inviteToken_DESC
inviteAccepted_ASC
inviteAccepted_DESC
emailConfirmed_ASC
emailConfirmed_DESC
emailConfirmToken_ASC
emailConfirmToken_DESC
resetToken_ASC
resetToken_DESC
resetExpires_ASC
resetExpires_DESC
deletedAt_ASC
deletedAt_DESC
lastLogin_ASC
lastLogin_DESC
joinedAt_ASC
joinedAt_DESC
isSuper_ASC
isSuper_DESC
updatedAt_ASC
updatedAt_DESC
createdAt_ASC
createdAt_DESC
}
type UserPreviousValues {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
type UserSubscriptionPayload {
mutation: MutationType!
node: User
updatedFields: [String!]
previousValues: UserPreviousValues
}
input UserSubscriptionWhereInput {
"""Logical AND on all given filters."""
AND: [UserSubscriptionWhereInput!]
"""Logical OR on all given filters."""
OR: [UserSubscriptionWhereInput!]
"""Logical NOT on all given filters combined by AND."""
NOT: [UserSubscriptionWhereInput!]
"""
The subscription event gets dispatched when it's listed in mutation_in
"""
mutation_in: [MutationType!]
"""
The subscription event gets only dispatched when one of the updated fields names is included in this list
"""
updatedFields_contains: String
"""
The subscription event gets only dispatched when all of the field names included in this list have been updated
"""
updatedFields_contains_every: [String!]
"""
The subscription event gets only dispatched when some of the field names included in this list have been updated
"""
updatedFields_contains_some: [String!]
node: UserWhereInput
}
input UserUpdateInput {
email: String
password: String
name: String
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime
isSuper: Boolean
}
input UserWhereInput {
"""Logical AND on all given filters."""
AND: [UserWhereInput!]
"""Logical OR on all given filters."""
OR: [UserWhereInput!]
"""Logical NOT on all given filters combined by AND."""
NOT: [UserWhereInput!]
id: ID
"""All values that are not equal to given value."""
id_not: ID
"""All values that are contained in given list."""
id_in: [ID!]
"""All values that are not contained in given list."""
id_not_in: [ID!]
"""All values less than the given value."""
id_lt: ID
"""All values less than or equal the given value."""
id_lte: ID
"""All values greater than the given value."""
id_gt: ID
"""All values greater than or equal the given value."""
id_gte: ID
"""All values containing the given string."""
id_contains: ID
"""All values not containing the given string."""
id_not_contains: ID
"""All values starting with the given string."""
id_starts_with: ID
"""All values not starting with the given string."""
id_not_starts_with: ID
"""All values ending with the given string."""
id_ends_with: ID
"""All values not ending with the given string."""
id_not_ends_with: ID
email: String
"""All values that are not equal to given value."""
email_not: String
"""All values that are contained in given list."""
email_in: [String!]
"""All values that are not contained in given list."""
email_not_in: [String!]
"""All values less than the given value."""
email_lt: String
"""All values less than or equal the given value."""
email_lte: String
"""All values greater than the given value."""
email_gt: String
"""All values greater than or equal the given value."""
email_gte: String
"""All values containing the given string."""
email_contains: String
"""All values not containing the given string."""
email_not_contains: String
"""All values starting with the given string."""
email_starts_with: String
"""All values not starting with the given string."""
email_not_starts_with: String
"""All values ending with the given string."""
email_ends_with: String
"""All values not ending with the given string."""
email_not_ends_with: String
password: String
"""All values that are not equal to given value."""
password_not: String
"""All values that are contained in given list."""
password_in: [String!]
"""All values that are not contained in given list."""
password_not_in: [String!]
"""All values less than the given value."""
password_lt: String
"""All values less than or equal the given value."""
password_lte: String
"""All values greater than the given value."""
password_gt: String
"""All values greater than or equal the given value."""
password_gte: String
"""All values containing the given string."""
password_contains: String
"""All values not containing the given string."""
password_not_contains: String
"""All values starting with the given string."""
password_starts_with: String
"""All values not starting with the given string."""
password_not_starts_with: String
"""All values ending with the given string."""
password_ends_with: String
"""All values not ending with the given string."""
password_not_ends_with: String
name: String
"""All values that are not equal to given value."""
name_not: String
"""All values that are contained in given list."""
name_in: [String!]
"""All values that are not contained in given list."""
name_not_in: [String!]
"""All values less than the given value."""
name_lt: String
"""All values less than or equal the given value."""
name_lte: String
"""All values greater than the given value."""
name_gt: String
"""All values greater than or equal the given value."""
name_gte: String
"""All values containing the given string."""
name_contains: String
"""All values not containing the given string."""
name_not_contains: String
"""All values starting with the given string."""
name_starts_with: String
"""All values not starting with the given string."""
name_not_starts_with: String
"""All values ending with the given string."""
name_ends_with: String
"""All values not ending with the given string."""
name_not_ends_with: String
inviteToken: String
"""All values that are not equal to given value."""
inviteToken_not: String
"""All values that are contained in given list."""
inviteToken_in: [String!]
"""All values that are not contained in given list."""
inviteToken_not_in: [String!]
"""All values less than the given value."""
inviteToken_lt: String
"""All values less than or equal the given value."""
inviteToken_lte: String
"""All values greater than the given value."""
inviteToken_gt: String
"""All values greater than or equal the given value."""
inviteToken_gte: String
"""All values containing the given string."""
inviteToken_contains: String
"""All values not containing the given string."""
inviteToken_not_contains: String
"""All values starting with the given string."""
inviteToken_starts_with: String
"""All values not starting with the given string."""
inviteToken_not_starts_with: String
"""All values ending with the given string."""
inviteToken_ends_with: String
"""All values not ending with the given string."""
inviteToken_not_ends_with: String
inviteAccepted: Boolean
"""All values that are not equal to given value."""
inviteAccepted_not: Boolean
emailConfirmed: Boolean
"""All values that are not equal to given value."""
emailConfirmed_not: Boolean
emailConfirmToken: String
"""All values that are not equal to given value."""
emailConfirmToken_not: String
"""All values that are contained in given list."""
emailConfirmToken_in: [String!]
"""All values that are not contained in given list."""
emailConfirmToken_not_in: [String!]
"""All values less than the given value."""
emailConfirmToken_lt: String
"""All values less than or equal the given value."""
emailConfirmToken_lte: String
"""All values greater than the given value."""
emailConfirmToken_gt: String
"""All values greater than or equal the given value."""
emailConfirmToken_gte: String
"""All values containing the given string."""
emailConfirmToken_contains: String
"""All values not containing the given string."""
emailConfirmToken_not_contains: String
"""All values starting with the given string."""
emailConfirmToken_starts_with: String
"""All values not starting with the given string."""
emailConfirmToken_not_starts_with: String
"""All values ending with the given string."""
emailConfirmToken_ends_with: String
"""All values not ending with the given string."""
emailConfirmToken_not_ends_with: String
resetToken: String
"""All values that are not equal to given value."""
resetToken_not: String
"""All values that are contained in given list."""
resetToken_in: [String!]
"""All values that are not contained in given list."""
resetToken_not_in: [String!]
"""All values less than the given value."""
resetToken_lt: String
"""All values less than or equal the given value."""
resetToken_lte: String
"""All values greater than the given value."""
resetToken_gt: String
"""All values greater than or equal the given value."""
resetToken_gte: String
"""All values containing the given string."""
resetToken_contains: String
"""All values not containing the given string."""
resetToken_not_contains: String
"""All values starting with the given string."""
resetToken_starts_with: String
"""All values not starting with the given string."""
resetToken_not_starts_with: String
"""All values ending with the given string."""
resetToken_ends_with: String
"""All values not ending with the given string."""
resetToken_not_ends_with: String
resetExpires: DateTime
"""All values that are not equal to given value."""
resetExpires_not: DateTime
"""All values that are contained in given list."""
resetExpires_in: [DateTime!]
"""All values that are not contained in given list."""
resetExpires_not_in: [DateTime!]
"""All values less than the given value."""
resetExpires_lt: DateTime
"""All values less than or equal the given value."""
resetExpires_lte: DateTime
"""All values greater than the given value."""
resetExpires_gt: DateTime
"""All values greater than or equal the given value."""
resetExpires_gte: DateTime
deletedAt: DateTime
"""All values that are not equal to given value."""
deletedAt_not: DateTime
"""All values that are contained in given list."""
deletedAt_in: [DateTime!]
"""All values that are not contained in given list."""
deletedAt_not_in: [DateTime!]
"""All values less than the given value."""
deletedAt_lt: DateTime
"""All values less than or equal the given value."""
deletedAt_lte: DateTime
"""All values greater than the given value."""
deletedAt_gt: DateTime
"""All values greater than or equal the given value."""
deletedAt_gte: DateTime
lastLogin: DateTime
"""All values that are not equal to given value."""
lastLogin_not: DateTime
"""All values that are contained in given list."""
lastLogin_in: [DateTime!]
"""All values that are not contained in given list."""
lastLogin_not_in: [DateTime!]
"""All values less than the given value."""
lastLogin_lt: DateTime
"""All values less than or equal the given value."""
lastLogin_lte: DateTime
"""All values greater than the given value."""
lastLogin_gt: DateTime
"""All values greater than or equal the given value."""
lastLogin_gte: DateTime
joinedAt: DateTime
"""All values that are not equal to given value."""
joinedAt_not: DateTime
"""All values that are contained in given list."""
joinedAt_in: [DateTime!]
"""All values that are not contained in given list."""
joinedAt_not_in: [DateTime!]
"""All values less than the given value."""
joinedAt_lt: DateTime
"""All values less than or equal the given value."""
joinedAt_lte: DateTime
"""All values greater than the given value."""
joinedAt_gt: DateTime
"""All values greater than or equal the given value."""
joinedAt_gte: DateTime
isSuper: Boolean
"""All values that are not equal to given value."""
isSuper_not: Boolean
}
input UserWhereUniqueInput {
id: ID
email: String
}
`;
export const Prisma = makePrismaBindingClass<BindingConstructor<Prisma>>({
typeDefs
});
/**
* Types
*/
export type UserOrderByInput =
| 'id_ASC'
| 'id_DESC'
| 'email_ASC'
| 'email_DESC'
| 'password_ASC'
| 'password_DESC'
| 'name_ASC'
| 'name_DESC'
| 'inviteToken_ASC'
| 'inviteToken_DESC'
| 'inviteAccepted_ASC'
| 'inviteAccepted_DESC'
| 'emailConfirmed_ASC'
| 'emailConfirmed_DESC'
| 'emailConfirmToken_ASC'
| 'emailConfirmToken_DESC'
| 'resetToken_ASC'
| 'resetToken_DESC'
| 'resetExpires_ASC'
| 'resetExpires_DESC'
| 'deletedAt_ASC'
| 'deletedAt_DESC'
| 'lastLogin_ASC'
| 'lastLogin_DESC'
| 'joinedAt_ASC'
| 'joinedAt_DESC'
| 'isSuper_ASC'
| 'isSuper_DESC'
| 'updatedAt_ASC'
| 'updatedAt_DESC'
| 'createdAt_ASC'
| 'createdAt_DESC';
export type MutationType = 'CREATED' | 'UPDATED' | 'DELETED';
export interface UserWhereUniqueInput {
id?: ID_Input;
email?: String;
}
export interface UserCreateInput {
email: String;
password: String;
name: String;
inviteToken?: String;
inviteAccepted?: Boolean;
emailConfirmed?: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper?: Boolean;
}
export interface UserUpdateInput {
email?: String;
password?: String;
name?: String;
inviteToken?: String;
inviteAccepted?: Boolean;
emailConfirmed?: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt?: DateTime;
isSuper?: Boolean;
}
export interface UserSubscriptionWhereInput {
AND?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
OR?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
NOT?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
mutation_in?: MutationType[] | MutationType;
updatedFields_contains?: String;
updatedFields_contains_every?: String[] | String;
updatedFields_contains_some?: String[] | String;
node?: UserWhereInput;
}
export interface UserWhereInput {
AND?: UserWhereInput[] | UserWhereInput;
OR?: UserWhereInput[] | UserWhereInput;
NOT?: UserWhereInput[] | UserWhereInput;
id?: ID_Input;
id_not?: ID_Input;
id_in?: ID_Input[] | ID_Input;
id_not_in?: ID_Input[] | ID_Input;
id_lt?: ID_Input;
id_lte?: ID_Input;
id_gt?: ID_Input;
id_gte?: ID_Input;
id_contains?: ID_Input;
id_not_contains?: ID_Input;
id_starts_with?: ID_Input;
id_not_starts_with?: ID_Input;
id_ends_with?: ID_Input;
id_not_ends_with?: ID_Input;
email?: String;
email_not?: String;
email_in?: String[] | String;
email_not_in?: String[] | String;
email_lt?: String;
email_lte?: String;
email_gt?: String;
email_gte?: String;
email_contains?: String;
email_not_contains?: String;
email_starts_with?: String;
email_not_starts_with?: String;
email_ends_with?: String;
email_not_ends_with?: String;
password?: String;
password_not?: String;
password_in?: String[] | String;
password_not_in?: String[] | String;
password_lt?: String;
password_lte?: String;
password_gt?: String;
password_gte?: String;
password_contains?: String;
password_not_contains?: String;
password_starts_with?: String;
password_not_starts_with?: String;
password_ends_with?: String;
password_not_ends_with?: String;
name?: String;
name_not?: String;
name_in?: String[] | String;
name_not_in?: String[] | String;
name_lt?: String;
name_lte?: String;
name_gt?: String;
name_gte?: String;
name_contains?: String;
name_not_contains?: String;
name_starts_with?: String;
name_not_starts_with?: String;
name_ends_with?: String;
name_not_ends_with?: String;
inviteToken?: String;
inviteToken_not?: String;
inviteToken_in?: String[] | String;
inviteToken_not_in?: String[] | String;
inviteToken_lt?: String;
inviteToken_lte?: String;
inviteToken_gt?: String;
inviteToken_gte?: String;
inviteToken_contains?: String;
inviteToken_not_contains?: String;
inviteToken_starts_with?: String;
inviteToken_not_starts_with?: String;
inviteToken_ends_with?: String;
inviteToken_not_ends_with?: String;
inviteAccepted?: Boolean;
inviteAccepted_not?: Boolean;
emailConfirmed?: Boolean;
emailConfirmed_not?: Boolean;
emailConfirmToken?: String;
emailConfirmToken_not?: String;
emailConfirmToken_in?: String[] | String;
emailConfirmToken_not_in?: String[] | String;
emailConfirmToken_lt?: String;
emailConfirmToken_lte?: String;
emailConfirmToken_gt?: String;
emailConfirmToken_gte?: String;
emailConfirmToken_contains?: String;
emailConfirmToken_not_contains?: String;
emailConfirmToken_starts_with?: String;
emailConfirmToken_not_starts_with?: String;
emailConfirmToken_ends_with?: String;
emailConfirmToken_not_ends_with?: String;
resetToken?: String;
resetToken_not?: String;
resetToken_in?: String[] | String;
resetToken_not_in?: String[] | String;
resetToken_lt?: String;
resetToken_lte?: String;
resetToken_gt?: String;
resetToken_gte?: String;
resetToken_contains?: String;
resetToken_not_contains?: String;
resetToken_starts_with?: String;
resetToken_not_starts_with?: String;
resetToken_ends_with?: String;
resetToken_not_ends_with?: String;
resetExpires?: DateTime;
resetExpires_not?: DateTime;
resetExpires_in?: DateTime[] | DateTime;
resetExpires_not_in?: DateTime[] | DateTime;
resetExpires_lt?: DateTime;
resetExpires_lte?: DateTime;
resetExpires_gt?: DateTime;
resetExpires_gte?: DateTime;
deletedAt?: DateTime;
deletedAt_not?: DateTime;
deletedAt_in?: DateTime[] | DateTime;
deletedAt_not_in?: DateTime[] | DateTime;
deletedAt_lt?: DateTime;
deletedAt_lte?: DateTime;
deletedAt_gt?: DateTime;
deletedAt_gte?: DateTime;
lastLogin?: DateTime;
lastLogin_not?: DateTime;
lastLogin_in?: DateTime[] | DateTime;
lastLogin_not_in?: DateTime[] | DateTime;
lastLogin_lt?: DateTime;
lastLogin_lte?: DateTime;
lastLogin_gt?: DateTime;
lastLogin_gte?: DateTime;
joinedAt?: DateTime;
joinedAt_not?: DateTime;
joinedAt_in?: DateTime[] | DateTime;
joinedAt_not_in?: DateTime[] | DateTime;
joinedAt_lt?: DateTime;
joinedAt_lte?: DateTime;
joinedAt_gt?: DateTime;
joinedAt_gte?: DateTime;
isSuper?: Boolean;
isSuper_not?: Boolean;
}
/*
* An object with an ID
*/
export interface Node {
id: ID_Output;
}
/*
* Information about pagination in a connection.
*/
export interface PageInfo {
hasNextPage: Boolean;
hasPreviousPage: Boolean;
startCursor?: String;
endCursor?: String;
}
export interface UserPreviousValues {
id: ID_Output;
email: String;
password: String;
name: String;
inviteToken?: String;
inviteAccepted: Boolean;
emailConfirmed: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper: Boolean;
}
export interface User extends Node {
id: ID_Output;
email: String;
password: String;
name: String;
inviteToken?: String;
inviteAccepted: Boolean;
emailConfirmed: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper: Boolean;
}
/*
* An edge in a connection.
*/
export interface UserEdge {
node: User;
cursor: String;
}
/*
* A connection to a list of items.
*/
export interface UserConnection {
pageInfo: PageInfo;
edges: UserEdge[];
aggregate: AggregateUser;
}
export interface UserSubscriptionPayload {
mutation: MutationType;
node?: User;
updatedFields?: String[];
previousValues?: UserPreviousValues;
}
export interface AggregateUser {
count: Int;
}
export interface BatchPayload {
count: Long;
}
export type DateTime = Date | string;
/*
The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
*/
export type ID_Input = string | number;
export type ID_Output = string;
/*
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
*/
export type Int = number;
/*
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
*/
export type String = string;
/*
The `Boolean` scalar type represents `true` or `false`.
*/
export type Boolean = boolean;
/*
The `Long` scalar type represents non-fractional signed whole numeric values.
Long can represent values between -(2^63) and 2^63 - 1.
*/
export type Long = string;
================================================
FILE: examples/with-prisma/package.json
================================================
{
"name": "graphql-authentication-with-prisma-example",
"private": true,
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"email-templates": "^4.0.1",
"graphql-authentication": "^0.5.3",
"graphql-authentication-prisma": "^0.1.3",
"graphql-cli": "^2.16.4",
"graphql-yoga": "^1.14.12",
"prisma": "^1.11.1",
"prisma-binding": "^2.1.0",
"ts-node": "^7.0.0"
},
"scripts": {
"start": "ts-node server.ts",
"prisma": "PRISMA_MANAGEMENT_API_SECRET=mymanagementsecret123 prisma"
}
}
================================================
FILE: examples/with-prisma/prisma.yml
================================================
endpoint: http://localhost:4466
datamodel: datamodel.graphql
hooks:
post-deploy:
- graphql codegen
================================================
FILE: examples/with-prisma/schema.graphql
================================================
# import Query.*, Mutation.* from "node_modules/graphql-authentication/schema.graphql"
type Query {
timeline: [Post!]!
}
type Post {
name: String!
}
================================================
FILE: examples/with-prisma/server.ts
================================================
import { GraphQLServer } from 'graphql-yoga';
import * as path from 'path';
import * as Email from 'email-templates';
import { Prisma } from './generated/prisma';
import {
authQueries,
authMutations,
graphqlAuthenticationConfig
} from 'graphql-authentication';
import { GraphqlAuthenticationPrismaAdapter } from 'graphql-authentication-prisma';
const resolvers = {
Query: {
...authQueries,
timeline() {
return [{ name: 'Testje' }];
}
},
Mutation: {
...authMutations
}
};
const mailer = new Email({
message: {
from: 'info@example.com'
},
views: {
root: path.join(__dirname, 'emails')
}
});
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
context: req => ({
...req,
db: new Prisma({
endpoint: 'http://localhost:4466',
debug: true
}),
graphqlAuthentication: graphqlAuthenticationConfig({
adapter: new GraphqlAuthenticationPrismaAdapter(),
secret: 'wherearemyshoes',
mailer,
mailAppUrl: 'http://example.com'
})
})
});
server.start(() => console.log('Server is running on http://localhost:4000'));
================================================
FILE: examples/with-prisma/utils.ts
================================================
import { Prisma } from './generated/prisma';
export interface Context {
db: Prisma;
request: any;
}
================================================
FILE: examples/with-sequelize/README.md
================================================
# Sequelize example
This is an example of how to use GraphQL Authentication with [Sequelize](http://docs.sequelizejs.com/). There is no adapter package for Sequelize yet, so in this example we write our own adapter (see `SequelizeAdapter.js`).
Sequelize is configured with SQLite, but only because it doesn't require you to manually start a database so this example stays simple. It also works with MySQL, Postgres etc.
## Usage
```
npm i
npm start
```
Go to http://localhost:4000 in your browser and start running some queries and mutations!
================================================
FILE: examples/with-sequelize/SequelizeAdapter.js
================================================
const { User } = require('./database');
// There currently is no package for a sequelize adapter, so we create one ourselves!
class GraphqlAuthenticationSequelizeAdapter {
findUserById(ctx, id, info) {
return User.findById(id);
}
findUserByEmail(ctx, email, info) {
return User.findOne({ where: { email } });
}
async userExistsByEmail(ctx, email) {
const user = await User.count({ where: { email } });
return user > 0;
}
// the _createUser and _updateUser methods are just helper methods, they are not used by graphql-authentication.
_createUser(ctx, data) {
return User.create(data);
}
_updateUser(ctx, userId, data) {
return User.update(data, { where: { id: userId } });
}
createUserBySignup(ctx, data) {
return this._createUser(ctx, data);
}
createUserByInvite(ctx, data) {
return this._createUser(ctx, data);
}
updateUserConfirmToken(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserLastLogin(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserPassword(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserResetToken(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserInfo(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserCompleteInvite(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
}
module.exports = { GraphqlAuthenticationSequelizeAdapter };
================================================
FILE: examples/with-sequelize/database.js
================================================
const Sequelize = require('sequelize');
const sequelize = new Sequelize({ dialect: 'sqlite' });
const User = sequelize.define('user', {
email: Sequelize.STRING,
password: Sequelize.STRING,
name: Sequelize.STRING,
inviteToken: Sequelize.STRING,
inviteAccepted: Sequelize.BOOLEAN,
emailConfirmed: Sequelize.BOOLEAN,
emailConfirmToken: Sequelize.STRING,
resetToken: Sequelize.STRING,
resetExpires: Sequelize.DATE,
deletedAt: Sequelize.DATE,
lastLogin: Sequelize.DATE,
joinedAt: Sequelize.DATE,
isSuper: Sequelize.BOOLEAN
});
sequelize.sync();
module.exports = { User };
================================================
FILE: examples/with-sequelize/emails/inviteUser/html.pug
================================================
p Hi,
p You are invited to join *your project*!
p
a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept invite.
================================================
FILE: examples/with-sequelize/emails/inviteUser/subject.pug
================================================
= `Invited for *your project*!`
================================================
FILE: examples/with-sequelize/emails/passwordReset/html.pug
================================================
p Hi,
p You requested a password reset on *your project*.
p
a(href=mailAppUrl + '/login/reset-password/' + email + '/' + resetToken) Reset my password.
================================================
FILE: examples/with-sequelize/emails/passwordReset/subject.pug
================================================
= `Confirm your email on *your project*`
================================================
FILE: examples/with-sequelize/emails/signupUser/html.pug
================================================
p Hi,
p You have just created an account on *your project*! As a last step, please confirm your email:
p
a(href=mailAppUrl + '/confirm-email/' + email + '/' + emailConfirmToken) Confirm email.
================================================
FILE: examples/with-sequelize/emails/signupUser/subject.pug
================================================
= `Confirm your email on *your project*`
================================================
FILE: examples/with-sequelize/package.json
================================================
{
"name": "graphql-authentication-with-sequelize-example",
"private": true,
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"email-templates": "^4.0.1",
"graphql-authentication": "^0.5.3",
"graphql-yoga": "^1.14.12",
"sequelize": "^4.38.0",
"sqlite3": "^4.0.2"
},
"scripts": {
"start": "node server.js"
}
}
================================================
FILE: examples/with-sequelize/schema.graphql
================================================
# import Query.*, Mutation.* from "node_modules/graphql-authentication/schema.graphql"
type Query {
timeline: [Post!]!
}
type Post {
name: String!
}
================================================
FILE: examples/with-sequelize/server.js
================================================
const { GraphQLServer } = require('graphql-yoga');
const path = require('path');
const Email = require('email-templates');
const {
authQueries,
authMutations,
graphqlAuthenticationConfig
} = require('graphql-authentication');
const { GraphqlAuthenticationSequelizeAdapter } = require('./SequelizeAdapter');
const resolvers = {
Query: {
...authQueries,
timeline() {
return [{ name: 'Testje' }];
}
},
Mutation: {
...authMutations
}
};
const mailer = new Email({
message: {
from: 'info@example.com'
},
views: {
root: path.join(__dirname, 'emails')
}
});
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
context: req => ({
...req,
graphqlAuthentication: graphqlAuthenticationConfig({
adapter: new GraphqlAuthenticationSequelizeAdapter(),
secret: 'wherearemyshoes',
mailer,
mailAppUrl: 'http://example.com'
})
})
});
server.start(() => console.log('Server is running on http://localhost:4000'));
================================================
FILE: examples/with-typeorm/README.md
================================================
# TypeORM example
This is an example of how to use GraphQL Authentication with [TypeORM](http://typeorm.io/). There is no adapter package for TypeORM yet, so in this example we write our own adapter (see `TypeOrmAdapter.js`).
TypeORM is configured with SQLite, but only because it doesn't require you to manually start a database so this example stays simple. It also works with MySQL, Postgres etc.
## Usage
```
npm i
npm start
```
Go to http://localhost:4000 in your browser and start running some queries and mutations!
================================================
FILE: examples/with-typeorm/TypeOrmAdapter.ts
================================================
import { getRepository } from 'typeorm';
import { User } from './database';
import { GraphqlAuthenticationAdapter } from './node_modules/graphql-authentication';
// There currently is no package for a TypeORM adapter, so we create one ourselves!
export class GraphqlAuthenticationTypeOrmAdapter
implements GraphqlAuthenticationAdapter {
private db() {
return getRepository(User);
}
async findUserById(ctx: object, id, info) {
return (await this.db().findOne(id)) || null;
}
async findUserByEmail(ctx: object, email, info) {
return (await this.db().findOne({ where: { email } })) || null;
}
async userExistsByEmail(ctx: object, email) {
const user = await this.db().count({ email });
return user > 0;
}
// the _createUser and _updateUser methods are just helper methods, they are not used by graphql-authentication.
async _createUser(ctx: object, data) {
const user = ((await this.db().create(data)) as any) as User;
await this.db().save(user);
return user;
}
async _updateUser(ctx: object, userId, data) {
return await this.db().update(userId, { name: 'kees' })[0];
}
createUserBySignup(ctx: object, data) {
return this._createUser(ctx, data);
}
createUserByInvite(ctx: object, data) {
return this._createUser(ctx, data);
}
updateUserConfirmToken(ctx: object, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserLastLogin(ctx: object, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserPassword(ctx: object, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserResetToken(ctx: object, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserInfo(ctx: object, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserCompleteInvite(ctx: object, userId, data) {
return this._updateUser(ctx, userId, data);
}
}
================================================
FILE: examples/with-typeorm/database.ts
================================================
import 'reflect-metadata';
import { createConnection } from 'typeorm';
export { User } from './entities/User';
createConnection();
================================================
FILE: examples/with-typeorm/emails/inviteUser/html.pug
================================================
p Hi,
p You are invited to join *your project*!
p
a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept invite.
================================================
FILE: examples/with-typeorm/emails/inviteUser/subject.pug
================================================
= `Invited for *your project*!`
================================================
FILE: examples/with-typeorm/emails/passwordReset/html.pug
================================================
p Hi,
p You requested a password reset on *your project*.
p
a(href=mailAppUrl + '/login/reset-password/' + email + '/' + resetToken) Reset my password.
================================================
FILE: examples/with-typeorm/emails/passwordReset/subject.pug
================================================
= `Confirm your email on *your project*`
================================================
FILE: examples/with-typeorm/emails/signupUser/html.pug
================================================
p Hi,
p You have just created an account on *your project*! As a last step, please confirm your email:
p
a(href=mailAppUrl + '/confirm-email/' + email + '/' + emailConfirmToken) Confirm email.
================================================
FILE: examples/with-typeorm/emails/signupUser/subject.pug
================================================
= `Confirm your email on *your project*`
================================================
FILE: examples/with-typeorm/entities/User.ts
================================================
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn() id!: string;
@Column() email!: string;
@Column() password!: string;
@Column() name!: string;
@Column({ nullable: true })
inviteToken!: string;
@Column({ default: true })
inviteAccepted!: boolean;
@Column({ default: true })
emailConfirmed!: boolean;
@Column({ nullable: true })
emailConfirmToken!: string;
@Column({ nullable: true })
resetToken!: string;
@Column({ nullable: true })
resetExpires!: Date;
@Column({ nullable: true })
deletedAt!: Date;
@Column({ nullable: true })
lastLogin!: Date;
@Column() joinedAt!: Date;
@Column({ default: false })
isSuper!: boolean;
}
================================================
FILE: examples/with-typeorm/ormconfig.json
================================================
{
"type": "sqlite",
"database": ":memory:",
"synchronize": true,
"logging": true,
"entities": ["entities/**/*.ts"]
}
================================================
FILE: examples/with-typeorm/package.json
================================================
{
"name": "graphql-authentication-with-typeorm-example",
"private": true,
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"email-templates": "^4.0.1",
"graphql-authentication": "^0.5.4",
"graphql-yoga": "^1.14.12",
"reflect-metadata": "^0.1.12",
"sqlite3": "^4.0.2",
"typeorm": "^0.2.7"
},
"scripts": {
"start": "ts-node server.ts"
},
"devDependencies": {
"ts-node": "^7.0.0",
"typescript": "^2.9.2"
}
}
================================================
FILE: examples/with-typeorm/schema.graphql
================================================
# import Query.*, Mutation.* from "node_modules/graphql-authentication/schema.graphql"
type Query {
timeline: [Post!]!
}
type Post {
name: String!
}
================================================
FILE: examples/with-typeorm/server.ts
================================================
import { GraphQLServer } from 'graphql-yoga';
import * as Email from 'email-templates';
import {
authQueries,
authMutations,
graphqlAuthenticationConfig
} from 'graphql-authentication';
import { GraphqlAuthenticationTypeOrmAdapter } from './TypeOrmAdapter';
const resolvers = {
Query: {
...authQueries,
timeline() {
return [{ name: 'Testje' }];
}
},
Mutation: {
...authMutations
}
};
const mailer = new Email({
message: {
from: 'info@example.com'
}
});
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
context: req => ({
...req,
graphqlAuthentication: graphqlAuthenticationConfig({
adapter: new GraphqlAuthenticationTypeOrmAdapter(),
secret: 'wherearemyshoes',
mailer,
mailAppUrl: 'http://example.com'
})
})
});
server.start(() => console.log('Server is running on http://localhost:4000'));
================================================
FILE: examples/with-typeorm/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"lib": ["esnext"],
"strict": true,
"strictFunctionTypes": false,
"noImplicitAny": false,
"forceConsistentCasingInFileNames": true
}
}
================================================
FILE: lerna.json
================================================
{
"lerna": "2.11.0",
"packages": [
"packages/*"
],
"version": "independent",
"npmClient": "yarn",
"useWorkspaces": true
}
================================================
FILE: live-demo/InMemoryAdapter.js
================================================
class GraphqlAuthenticationInMemoryAdapter {
constructor() {
this.users = [];
}
// If you'd use a database you wouldn't need this
_generateId() {
const lastUser = this.users[this.users.length - 1];
if (lastUser) {
return String(parseInt(lastUser.id) + 1);
}
return '1';
}
findUserById(ctx, id, info) {
return Promise.resolve(this.users.find(user => user.id === id) || null);
}
findUserByEmail(ctx, email, info) {
return Promise.resolve(
this.users.find(user => user.email === email) || null
);
}
async userExistsByEmail(ctx, email) {
return Promise.resolve(this.users.some(user => user.email === email));
}
_createUser(ctx, data) {
const user = { id: this._generateId(), ...data };
this.users.push(user);
return Promise.resolve(user);
}
async _updateUser(ctx, userId, data) {
const user = await this.findUserById(ctx, userId);
Object.assign(user, data);
return Promise.resolve(user);
}
createUserBySignup(ctx, data) {
return this._createUser(ctx, data);
}
createUserByInvite(ctx, data) {
return this._createUser(ctx, data);
}
updateUserConfirmToken(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserLastLogin(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserPassword(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserResetToken(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserInfo(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
updateUserCompleteInvite(ctx, userId, data) {
return this._updateUser(ctx, userId, data);
}
}
module.exports = { GraphqlAuthenticationInMemoryAdapter };
================================================
FILE: live-demo/README.md
================================================
# Live Demo
The code in this repository is used to host a live demo on x.now.sh (TODO).
The live demo uses an in-memory adapter, so everytime the server restarts the data is gone. For a demo this is perfect :).
## Test locally
Run `yarn && yarn start`.
## Deploy on Now
Copy `.env.example` to `.env` and fill the variables in.
```
npm i -g now
now --dotenv
now alias graphql-authentication-demo.now.sh
```
================================================
FILE: live-demo/email.js
================================================
const { createTransport } = require('nodemailer');
const mailgun = require('nodemailer-mailgun-transport');
const Email = require('email-templates');
const apiKey = process.env.MAILGUN_API_KEY;
const mailgunConfig = {
auth: {
api_key: apiKey,
domain: process.env.MAILGUN_DOMAIN
}
};
// Just send the email locally if apikey is not filled in
const transporter = apiKey
? createTransport(mailgun(mailgunConfig))
: undefined;
email = new Email({
message: {
from: process.env.MAIL_FROM
},
send: true,
transport: transporter
});
module.exports = { email };
================================================
FILE: live-demo/emails/inviteUser/html.pug
================================================
p Hi,
p You are invited to join GraphQL Authentication Demo! Accept the invite by writing this mutation:
pre
| mutation {
| signupByInvite(
| data: {
| name: "Enter your name here",
| password: "myverystrongpassword",
| email: "#{email}",
| inviteToken: "#{inviteToken}"
| }
| ) {
| token
| }
| }
p
em In a real-world application the user wouldn't have to run the mutation itself of course, it would something like this:<br />
a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept invite.
================================================
FILE: live-demo/emails/inviteUser/subject.pug
================================================
= `Invited for GraphQL Authentication Demo!`
================================================
FILE: live-demo/emails/passwordReset/html.pug
================================================
p Hi,
p You requested a password reset on GraphQL Authentication Demo. Reset your password by writing this mutation:
pre
| mutation {
| passwordReset(password: "mynewpassword", email: "#{email}", resetToken: "#{resetToken}") {
| id
| }
|}
p
em In a real-world application the user wouldn't have to run the mutation itself of course, it would something like this:<br />
a(href=mailAppUrl + '/login/reset-password/' + email + '/' + resetToken) Reset my password.
================================================
FILE: live-demo/emails/passwordReset/subject.pug
================================================
= `Confirm your email on GraphQL Authentication Demo`
================================================
FILE: live-demo/emails/signupUser/html.pug
================================================
p Hi,
p You have just created an account on GraphQL Authentication Demo! As a last step, please confirm your email by writing this mutation:
pre
| mutation {
| confirmEmail(email: "#{email}", emailConfirmToken: "#{emailConfirmToken}") {
| token
| }
| }
p
em In a real-world application the user wouldn't have to run the mutation itself of course, it would something like this:<br />
a(href=mailAppUrl + '/confirm-email/' + email + '/' + emailConfirmToken) Confirm your email.
================================================
FILE: live-demo/emails/signupUser/subject.pug
================================================
= `Confirm your email on GraphQL Authentication Demo`
================================================
FILE: live-demo/index.js
================================================
const { GraphQLServer } = require('graphql-yoga');
const {
authQueries,
authMutations,
graphqlAuthenticationConfig
} = require('graphql-authentication');
const { GraphqlAuthenticationInMemoryAdapter } = require('./InMemoryAdapter');
const { email } = require('./email');
const adapter = new GraphqlAuthenticationInMemoryAdapter();
const resolvers = {
Query: {
...authQueries
},
Mutation: {
...authMutations
}
};
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers,
context: req => ({
...req,
graphqlAuthentication: graphqlAuthenticationConfig({
adapter,
secret: 'wherearemyshoes',
mailer: email,
mailAppUrl: 'http://example.com'
})
})
});
server.start(() => console.log('Server is running on http://localhost:4000'));
================================================
FILE: live-demo/package.json
================================================
{
"name": "graphql-authentication-live-demo",
"private": true,
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"email-templates": "^4.0.1",
"graphql": "^0.13.2",
"graphql-authentication": "^0.5.4",
"graphql-yoga": "^1.14.12",
"nodemailer-mailgun-transport": "^1.4.0",
"now": "^11.2.10"
},
"scripts": {
"start": "node index.js"
},
"now": {
"alias": [
"graphql-authentication-demo.now.sh"
]
}
}
================================================
FILE: live-demo/schema.graphql
================================================
# import Query.*, Mutation.* from "node_modules/graphql-authentication/schema.graphql"
type Query
================================================
FILE: package.json
================================================
{
"private": true,
"workspaces": [
"packages/*"
],
"devDependencies": {
"husky": "^0.14.3",
"lerna": "^2.11.0",
"prettier": "^1.13.6",
"pretty-quick": "^1.6.0"
},
"scripts": {
"publish": "lerna publish",
"precommit": "pretty-quick --staged"
}
}
================================================
FILE: packages/graphql-authentication/README.md
================================================
# GraphQL Authentication
A very opinionated user authentication package for [GraphQL](https://graphql.org/). It uses old-school email/password authentication.
This package does not access your data layer (e.g. an ORM); for that you need to write a _adapter_ (which is not hard to do).
If you use Prisma, there is already an adapter for you, **[graphql-authentication-prisma](https://github.com/Volst/graphql-authentication/tree/master/packages/graphql-authentication-prisma)**.
### [Full Documentation](https://github.com/Volst/graphql-authentication/blob/master/README.md)
================================================
FILE: packages/graphql-authentication/package.json
================================================
{
"name": "graphql-authentication",
"version": "0.5.5",
"description": "Makes it super easy to do do boring authentication stuff with GraphQL (login, password reset, ...)",
"author": "kees@volst.nl",
"repository": "Volst/graphql-authentication",
"keywords": [
"graphql",
"user",
"authentication",
"login"
],
"license": "ISC",
"private": false,
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"engines": {
"node": ">=8.0"
},
"files": [
"dist",
"schema.graphql"
],
"scripts": {
"build": "rm -rf dist && tsc -p tsconfig.build.json",
"lint": "tslint -p .",
"prepublishOnly": "npm run -s build",
"test": "jest --watch",
"test-coverage": "jest --coverage",
"ci": "npm run -s lint && npm run -s build && npm run -s test-coverage && codecov",
"graphql-types": "graphql-binding --input src/schema.ts --language typescript --outputBinding src/binding.ts"
},
"devDependencies": {
"@types/email-templates": "^3.5.0",
"@types/jest": "^23.1.0",
"@volst/tslint-config": "^0.2.1",
"codecov": "^3.0.2",
"email-templates": "^4.0.1",
"graphql-binding": "^2.1.1",
"graphql-cli": "^2.16.3",
"graphql-request": "^1.6.0",
"graphql-yoga": "1.14.10",
"jest": "^23.1.0",
"nodemon": "^1.17.3",
"pug": "^2.0.3",
"ts-jest": "^22.4.6",
"ts-node": "^7.0.0",
"tslint": "^5.9.1",
"typescript": "^2.8.3"
},
"dependencies": {
"@types/bcryptjs": "^2.4.1",
"@types/jsonwebtoken": "^7.2.6",
"@types/uuid": "^3.4.3",
"@types/validator": "^9.4.1",
"apollo-errors": "^1.9.0",
"bcryptjs": "^2.4.3",
"jsonwebtoken": "^8.2.1",
"uuid": "^3.2.1",
"validator": "^10.2.0"
},
"peerDependencies": {
"email-templates": "^3.6 || ^4"
},
"jest": {
"roots": [
"./src"
],
"transform": {
"^.+\\.ts$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(js|ts)$",
"setupTestFrameworkScriptFile": "<rootDir>/src/__tests__/setup.ts",
"moduleFileExtensions": [
"ts",
"js",
"json",
"node"
]
}
}
================================================
FILE: packages/graphql-authentication/schema.graphql
================================================
scalar DateTime
type Query {
currentUser: User
}
type Mutation {
signupByInvite(data: SignupByInviteInput!): AuthPayload!
signup(data: SignupInput!): AuthPayload!
confirmEmail(email: String!, emailConfirmToken: String!): AuthPayload!
inviteUser(data: InviteUserInput!): UserIdPayload!
login(email: String!, password: String!): AuthPayload!
changePassword(oldPassword: String!, newPassword: String!): UserIdPayload!
updateCurrentUser(data: UserUpdateInput!): User
triggerPasswordReset(email: String!): TriggerPasswordResetPayload!
passwordReset(
email: String!
resetToken: String!
password: String!
): UserIdPayload!
}
type AuthPayload {
token: String!
user: User!
}
type UserIdPayload {
id: ID!
}
type TriggerPasswordResetPayload {
ok: Boolean!
}
type User {
id: ID!
email: String!
name: String!
inviteAccepted: Boolean!
emailConfirmed: Boolean!
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
input InviteUserInput {
email: String!
}
input UserUpdateInput {
email: String
name: String
}
input SignupByInviteInput {
email: String!
inviteToken: String!
password: String!
name: String!
}
input SignupInput {
email: String!
password: String!
name: String!
}
================================================
FILE: packages/graphql-authentication/src/Adapter.ts
================================================
import { Context } from './utils';
export type DateTime = Date | string;
export type ID = string;
export interface User {
id: ID;
email: string;
password: string;
name: string;
inviteToken?: string;
inviteAccepted: Boolean;
emailConfirmed: Boolean;
emailConfirmToken?: string;
resetToken?: string;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper: Boolean;
}
export interface GraphqlAuthenticationAdapter {
findUserById(ctx: Context, id: ID, info?: any): Promise<User | null>;
findUserByEmail(
ctx: Context,
email: string,
info?: any
): Promise<User | null>;
userExistsByEmail(ctx: Context, email: string): Promise<boolean>;
createUserBySignup(ctx: Context, data: any): Promise<User>;
createUserByInvite(ctx: Context, data: any): Promise<User>;
updateUserConfirmToken(
ctx: Context,
userId: ID,
data: any
): Promise<User | null>;
updateUserLastLogin(
ctx: Context,
userId: ID,
data: any
): Promise<User | null>;
updateUserPassword(ctx: Context, userId: ID, data: any): Promise<User | null>;
updateUserResetToken(
ctx: Context,
userId: ID,
data: any
): Promise<User | null>;
updateUserInfo(ctx: Context, userId: ID, data: any): Promise<User | null>;
updateUserCompleteInvite(
ctx: Context,
userId: ID,
data: any
): Promise<User | null>;
}
================================================
FILE: packages/graphql-authentication/src/Config.ts
================================================
import * as Email from 'email-templates';
import { User } from './Adapter';
import { Context } from './utils';
import { GraphqlAuthenticationAdapter } from './Adapter';
export interface IGraphqlAuthenticationConfig {
mailer?: Email;
mailAppUrl?: string;
secret: string;
requiredConfirmedEmailForLogin?: boolean;
hookInviteUserPostCreate?: (
data: any,
ctx: Context,
user: User
) => Promise<any>;
adapter: GraphqlAuthenticationAdapter;
validatePassword?: (value: string) => boolean;
}
export function graphqlAuthenticationConfig(
options: IGraphqlAuthenticationConfig
) {
const defaults = {
requiredConfirmedEmailForLogin: false,
validatePassword: value => value.length >= 8
};
if (!options.adapter) {
throw new Error(
'You forgot to add the `adapter` option to graphql-authentication!'
);
}
return Object.assign(defaults, options);
}
================================================
FILE: packages/graphql-authentication/src/__tests__/mutations.ts
================================================
import { client, clientWithAuth, startServer, FakeAdapter } from './setup';
test('signup - a new user', async () => {
const req = client(await startServer());
const result = await req.request(`mutation {
signup(data: {name: "Roger", email: "roger@volst.nl", password: "testtest2"}) {
token
user {
id
name
}
}
}`);
expect((result as any).signup).toEqual({
// Poorly check for a JWT token
token: expect.stringContaining('.'),
user: {
id: '3',
name: 'Roger'
}
});
});
test('signup - with existent user', async () => {
expect.assertions(1);
const req = client(await startServer());
try {
await req.request(`mutation {
signup(data: {name: "Kees", email: "kees@volst.nl", password: "testtest2"}) {
token
}
}`);
} catch (e) {
expect(String(e)).toMatch(/User already exists with this email/);
}
});
test('signup - with weak password', async () => {
expect.assertions(1);
const req = client(await startServer());
try {
await req.request(`mutation {
signup(data: {name: "Roger", email: "roger@volst.nl", password: "test"}) {
token
}
}`);
} catch (e) {
expect(String(e)).toMatch(/Password is too short/);
}
});
test('signup - with custom password validation', async () => {
expect.assertions(1);
const req = client(
await startServer({
graphqlAuthentication: {
validatePassword: value => {
return value.length > 400;
}
}
})
);
try {
await req.request(`mutation {
signup(data: {name: "Roger", email: "roger@volst.nl", password: "testtest2"}) {
token
}
}`);
} catch (e) {
expect(String(e)).toMatch(/Password is too short/);
}
});
test('login - correct', async () => {
const req = client(await startServer());
const result = await req.request(`mutation {
login(email: "kees@volst.nl", password: "testtest2") {
token
user {
id
name
}
}
}`);
expect((result as any).login).toEqual({
// Poorly check for a JWT token
token: expect.stringContaining('.'),
user: {
id: '2',
name: 'Kees'
}
});
});
test('login - non-existent user', async () => {
const req = client(await startServer());
expect.assertions(1);
try {
await req.request(`mutation {
login(email: "roger@volst.nl", password: "testtest2") {
token
}
}`);
} catch (e) {
expect(String(e)).toMatch(/No user found/);
}
});
test('login - wrong password', async () => {
expect.assertions(1);
const req = client(await startServer());
try {
await req.request(`mutation {
login(email: "kees@volst.nl", password: "testtest1") {
token
}
}`);
} catch (e) {
expect(String(e)).toMatch(/No user found/);
}
});
test('update current user data - correct', async () => {
const req = clientWithAuth(await startServer());
const result = await req.request(`mutation {
updateCurrentUser(data: {name: "Voldemort"}) {
id
name
}
}`);
expect((result as any).updateCurrentUser).toEqual({
id: '2',
name: 'Voldemort'
});
});
test('update current user data - wrong old passwd', async () => {
expect.assertions(1);
const req = clientWithAuth(await startServer());
try {
await req.request(`mutation {
changePassword(oldPassword: "testtest3", newPassword: "testtest4") {
id
}
}`);
} catch (e) {
expect(String(e)).toMatch(/Invalid old password/);
}
});
test('update user password', async () => {
const req = clientWithAuth(await startServer());
const result = await req.request(`mutation {
changePassword(oldPassword: "testtest2", newPassword: "testtest3") {
id
}
}`);
expect((result as any).changePassword).toEqual({
id: '2'
});
// Now verify the password has actually been changed correctly.
const result2 = await req.request(`mutation {
login(email: "kees@volst.nl", password: "testtest3") {
user {
id
}
}
}`);
expect((result2 as any).login.user).toEqual({
id: '2'
});
});
test('trigger password reset - correct', async () => {
expect.assertions(6);
const req = clientWithAuth(await startServer());
const spy = jest.spyOn(FakeAdapter.prototype, 'updateUserResetToken');
const result = await req.request(`mutation {
triggerPasswordReset(email: "kees@volst.nl") {
ok
}
}`);
expect(spy).toHaveBeenCalled();
expect((result as any).triggerPasswordReset).toEqual({
ok: true
});
const { resetToken } = await spy.mock.results[0].value;
// Verify the resetToken is a UUID
expect(resetToken.length).toBe(36);
const result2 = await req.request(`mutation {
passwordReset(email: "kees@volst.nl", password: "testtest4", resetToken: "${resetToken}") {
id
}
}`);
expect((result2 as any).passwordReset).toEqual({
id: '2'
});
const result3 = await req.request(`mutation {
login(email: "kees@volst.nl", password: "testtest4") {
user {
id
}
}
}`);
expect((result3 as any).login.user).toEqual({
id: '2'
});
// Now verify that the resetToken is now invalid
try {
await req.request(`mutation {
passwordReset(email: "kees@volst.nl", password: "badbadbad", resetToken: "${resetToken}") {
id
}
}`);
} catch (e) {
expect(String(e)).toMatch(/No user found/);
}
spy.mockRestore();
});
test('invite user - correct', async () => {
expect.assertions(6);
const req = clientWithAuth(await startServer());
const spy = jest.spyOn(FakeAdapter.prototype, 'createUserByInvite');
const result = await req.request(`mutation {
inviteUser(data: {email: "roger@volst.nl"}) {
id
}
}`);
expect(spy).toHaveBeenCalled();
expect((result as any).inviteUser).toEqual({
id: '3'
});
const { inviteToken } = await spy.mock.results[0].value;
// Verify the resetToken is a UUID
expect(inviteToken.length).toBe(36);
const SIGNUP_INVITE = `mutation {
signupByInvite(data:{name: "Roger", email: "roger@volst.nl", password: "testtest4", inviteToken: "${inviteToken}"}) {
user {
id
}
}
}`;
const result2 = await req.request(SIGNUP_INVITE);
expect((result2 as any).signupByInvite.user).toEqual({
id: '3'
});
const result3 = await req.request(`mutation {
login(email: "roger@volst.nl", password: "testtest4") {
user {
id
}
}
}`);
expect((result3 as any).login.user).toEqual({
id: '3'
});
// Now verify that the inviteToken is now invalid
try {
await req.request(SIGNUP_INVITE);
} catch (e) {
expect(String(e)).toMatch(/inviteToken is invalid/);
}
spy.mockRestore();
});
test('confirm email - correct', async () => {
expect.assertions(6);
const req = clientWithAuth(await startServer());
const spy = jest.spyOn(FakeAdapter.prototype, 'createUserBySignup');
const result = await req.request(`mutation {
signup(data:{name: "Roger", email: "roger@volst.nl", password: "testtest4"}) {
user {
id
}
}
}`);
expect(spy).toHaveBeenCalled();
expect((result as any).signup.user).toEqual({
id: '3'
});
const { emailConfirmToken } = await spy.mock.results[0].value;
// Verify the emailConfirmToken is a UUID
expect(emailConfirmToken.length).toBe(36);
const CONFIRM_EMAIL = `mutation {
confirmEmail(email: "roger@volst.nl", emailConfirmToken: "${emailConfirmToken}") {
user {
id
}
}
}`;
const result2 = await req.request(CONFIRM_EMAIL);
expect((result2 as any).confirmEmail.user).toEqual({
id: '3'
});
const result3 = await req.request(`mutation {
login(email: "roger@volst.nl", password: "testtest4") {
user {
id
}
}
}`);
expect((result3 as any).login.user).toEqual({
id: '3'
});
// Now verify that the emailConfirmToken is now invalid
try {
await req.request(CONFIRM_EMAIL);
} catch (e) {
expect(String(e)).toMatch(/emailConfirmToken is invalid/);
}
spy.mockRestore();
});
================================================
FILE: packages/graphql-authentication/src/__tests__/queries.ts
================================================
import { client, startServer, clientWithAuth } from './setup';
test('currentUser - throw error when login fails', async () => {
const req = client(await startServer());
expect.assertions(1);
try {
await req.request(`query {
currentUser {
name
}
}`);
} catch (e) {
expect(String(e)).toMatch(/Not authorized/);
}
});
test('currentUser - fetch user data', async () => {
const req = clientWithAuth(await startServer());
const result = await req.request(`query {
currentUser {
name
}
}`);
expect((result as any).currentUser.name).toBe('Kees');
});
================================================
FILE: packages/graphql-authentication/src/__tests__/setup.ts
================================================
import { GraphQLServer } from 'graphql-yoga';
import { GraphQLClient } from 'graphql-request';
import {
graphqlAuthenticationConfig,
authQueries,
authMutations,
GraphqlAuthenticationAdapter,
User,
ID
} from '..';
export class FakeAdapter implements GraphqlAuthenticationAdapter {
users: User[] = [
{
id: '2',
name: 'Kees',
password: '$2a$10$3dcRen7qMwJmzUzgj7cjUukHYlPTTCAjFhfF00.5WAFhhClTp6H4y', // testtest2
email: 'kees@volst.nl',
inviteAccepted: true,
emailConfirmed: true,
joinedAt: '2018-06-29T14:26:57+00:00',
isSuper: false,
lastLogin: ''
}
];
// If you'd use a database you wouldn't need this
_generateId() {
const lastUser = this.users[this.users.length - 1];
return String(parseInt(lastUser.id) + 1);
}
findUserById(ctx: object, id: ID, info?: any) {
return Promise.resolve(this.users.find(user => user.id === id) || null);
}
findUserByEmail(ctx: any, email: string) {
return Promise.resolve(
this.users.find(user => user.email === email) || null
);
}
userExistsByEmail(ctx: any, email: string) {
return Promise.resolve(this.users.some(user => user.email === email));
}
createUserBySignup(ctx: any, data: any) {
const user = { id: this._generateId(), ...data };
this.users.push(user);
return Promise.resolve(user);
}
createUserByInvite(ctx: any, data: any) {
const user = { id: this._generateId(), ...data };
this.users.push(user);
return Promise.resolve(user);
}
async updateUserLastLogin(ctx: any, userId: string, data: any) {
const user = await this.findUserById(ctx, userId);
Object.assign(user, data); // iel
return Promise.resolve(user);
}
async updateUserInfo(ctx: any, userId: string, data: any) {
const user = await this.findUserById(ctx, userId);
Object.assign(user, data); // iel
return Promise.resolve(user);
}
async updateUserPassword(ctx: any, userId: string, data: any) {
const user = await this.findUserById(ctx, userId);
user!.password = data.password;
return Promise.resolve(user);
}
async updateUserResetToken(ctx: any, userId: string, data: any) {
const user = await this.findUserById(ctx, userId);
Object.assign(user, data); // iel
return Promise.resolve(user);
}
async updateUserCompleteInvite(ctx: any, userId: string, data: any) {
const user = await this.findUserById(ctx, userId);
Object.assign(user, data); // iel
return Promise.resolve(user);
}
async updateUserConfirmToken(ctx: any, userId: string, data: any) {
const user = await this.findUserById(ctx, userId);
Object.assign(user, data); // iel
return Promise.resolve(user);
}
}
// In nodejs run `require('jsonwebtoken').sign({ userId: '2' }, 'wherearemyshoes')`
const AUTH_KEY =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIyIiwiaWF0IjoxNTI5MjUxNjQ4fQ.Tw4a0CI3r_8GmyuO1v2aMonrQtKV9QFYnXoxQz0cyRQ';
let http: any;
export async function startServer(options: any = {}) {
if (http) {
await http.close();
}
const adapter = new FakeAdapter() as any;
const server = new GraphQLServer({
typeDefs: './schema.graphql',
resolvers: {
Query: {
...authQueries
},
Mutation: {
...authMutations
}
},
context: req => ({
...req,
graphqlAuthentication: graphqlAuthenticationConfig({
secret: 'wherearemyshoes',
adapter,
...options.graphqlAuthentication
})
})
});
http = await server.start({
port: 0
});
const { port } = http.address();
return `http://localhost:${port}/`;
}
afterAll(async () => {
if (http) {
await http.close();
}
});
export const clientWithAuth = uri =>
new GraphQLClient(uri, {
headers: {
Authorization: `Bearer ${AUTH_KEY}`
}
});
export const client = uri => new GraphQLClient(uri);
// TODO: this workaround sucks
test('asdf', () => undefined);
================================================
FILE: packages/graphql-authentication/src/binding.ts
================================================
import { makeBindingClass, Options } from 'graphql-binding';
import { GraphQLResolveInfo, GraphQLSchema } from 'graphql';
import { IResolvers } from 'graphql-tools/dist/Interfaces';
import schema from './schema';
export interface Query {
currentUser: <T = User | null>(
args?: {},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
}
export interface Mutation {
signupByInvite: <T = AuthPayload>(
args: { data: SignupByInviteInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
signup: <T = AuthPayload>(
args: { data: SignupInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
confirmEmail: <T = AuthPayload>(
args: { email: String; emailConfirmToken: String },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
inviteUser: <T = UserIdPayload>(
args: { data: InviteUserInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
login: <T = AuthPayload>(
args: { email: String; password: String },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
changePassword: <T = UserIdPayload>(
args: { oldPassword: String; newPassword: String },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
updateCurrentUser: <T = User | null>(
args: { data: UserUpdateInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
triggerPasswordReset: <T = TriggerPasswordResetPayload>(
args: { email: String },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
passwordReset: <T = UserIdPayload>(
args: { email: String; resetToken: String; password: String },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
}
export interface Subscription {}
export interface Binding {
query: Query;
mutation: Mutation;
subscription: Subscription;
request: <T = any>(
query: string,
variables?: { [key: string]: any }
) => Promise<T>;
delegate(
operation: 'query' | 'mutation',
fieldName: string,
args: {
[key: string]: any;
},
infoOrQuery?: GraphQLResolveInfo | string,
options?: Options
): Promise<any>;
delegateSubscription(
fieldName: string,
args?: {
[key: string]: any;
},
infoOrQuery?: GraphQLResolveInfo | string,
options?: Options
): Promise<AsyncIterator<any>>;
getAbstractResolvers(filterSchema?: GraphQLSchema | string): IResolvers;
}
export interface BindingConstructor<T> {
new (...args): T;
}
export const Binding = makeBindingClass<BindingConstructor<Binding>>({
schema
});
/**
* Types
*/
export interface SignupByInviteInput {
email: String;
inviteToken: String;
password: String;
name: String;
}
export interface SignupInput {
email: String;
password: String;
name: String;
}
export interface InviteUserInput {
email: String;
}
export interface UserUpdateInput {
email?: String;
name?: String;
}
export interface AuthPayload {
token: String;
user: User;
}
export interface TriggerPasswordResetPayload {
ok: Boolean;
}
export interface User {
id: ID_Output;
email: String;
name: String;
inviteAccepted: Boolean;
emailConfirmed: Boolean;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper: Boolean;
}
export interface UserIdPayload {
id: ID_Output;
}
/*
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
*/
export type String = string;
/*
The `Boolean` scalar type represents `true` or `false`.
*/
export type Boolean = boolean;
export type DateTime = Date | string;
/*
The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
*/
export type ID_Input = string | number;
export type ID_Output = string;
================================================
FILE: packages/graphql-authentication/src/errors.ts
================================================
import { createError } from 'apollo-errors';
export const MissingDataError = createError('MissingDataError', {
message: 'Not all required fields are filled in.'
});
export const InvalidEmailError = createError('InvalidEmailError', {
message: 'Given email is invalid.'
});
export const ResetTokenExpiredError = createError('ResetTokenExpiredError', {
message: 'resetToken expired.'
});
export const PasswordTooShortError = createError('PasswordTooShortError', {
message: 'Password is too short.'
});
export const UserNotFoundError = createError('UserNotFoundError', {
message: 'No user found.'
});
export const InvalidInviteTokenError = createError('InvalidInviteTokenError', {
message: 'inviteToken is invalid.'
});
export const InvalidEmailConfirmToken = createError(
'InvalidEmailConfirmToken',
{
message: 'emailConfirmToken is invalid.'
}
);
export const UserEmailExistsError = createError('UserEmailExistsError', {
message: 'User already exists with this email.'
});
export const UserInviteNotAcceptedError = createError(
'UserInviteNotAcceptedError',
{
message: 'User has not accepted invite yet.'
}
);
export const UserDeletedError = createError('UserDeletedError', {
message: 'User has been deleted.'
});
export const UserEmailUnconfirmedError = createError(
'UserEmailUnconfirmedError',
{
message: 'Users email has not been confirmed yet.'
}
);
export const InvalidOldPasswordError = createError('InvalidOldPasswordError', {
message: 'Invalid old password.'
});
================================================
FILE: packages/graphql-authentication/src/index.ts
================================================
export { mutations as authMutations } from './mutations';
export { queries as authQueries } from './queries';
export { getUser, getUserId, isAuthResolver, Context } from './utils';
export { graphqlAuthenticationConfig } from './Config';
export { GraphqlAuthenticationAdapter, ID, DateTime, User } from './Adapter';
================================================
FILE: packages/graphql-authentication/src/mutations.ts
================================================
import * as bcrypt from 'bcryptjs';
import * as jwt from 'jsonwebtoken';
import * as validator from 'validator';
import { v4 as uuid } from 'uuid';
import { getUser, Context } from './utils';
import { User } from './Adapter';
import {
MissingDataError,
ResetTokenExpiredError,
InvalidEmailError,
PasswordTooShortError,
UserNotFoundError,
InvalidInviteTokenError,
UserEmailExistsError,
UserInviteNotAcceptedError,
UserDeletedError,
InvalidOldPasswordError,
InvalidEmailConfirmToken,
UserEmailUnconfirmedError
} from './errors';
import {
SignupByInviteInput,
SignupInput,
InviteUserInput,
UserUpdateInput
} from './binding';
function generateToken(user: User, ctx: Context) {
return jwt.sign({ userId: user.id }, ctx.graphqlAuthentication.secret);
}
function validatePassword(ctx: Context, value: string) {
if (!ctx.graphqlAuthentication.validatePassword!(value)) {
throw new PasswordTooShortError();
}
}
function getHashedPassword(value: string) {
return bcrypt.hash(value, 10);
}
export const mutations = {
async signupByInvite(
parent: any,
{ data }: { data: SignupByInviteInput },
ctx: Context
) {
// Important first check, because i.e. the `inviteToken` could be an empty string
// and in that case the find query beneath would find any user with any given email,
// allowing you to change the password of everybody.
if (!data.inviteToken || !data.email) {
throw new MissingDataError();
}
const user = await ctx.graphqlAuthentication.adapter.findUserByEmail(
ctx,
data.email
);
if (!user) {
throw new UserNotFoundError();
}
if (user.inviteToken !== data.inviteToken || user.inviteAccepted) {
throw new InvalidInviteTokenError();
}
validatePassword(ctx, data.password);
const hashedPassword = await getHashedPassword(data.password);
const updatedUser = await ctx.graphqlAuthentication.adapter.updateUserCompleteInvite(
ctx,
user.id,
{
name: data.name,
inviteToken: '',
inviteAccepted: true,
password: hashedPassword
}
);
return {
token: generateToken(user, ctx),
user: updatedUser
};
},
async signup(parent: any, { data }: { data: SignupInput }, ctx: Context) {
if (!data.email) {
throw new MissingDataError();
}
const userExists = await ctx.graphqlAuthentication.adapter.userExistsByEmail(
ctx,
data.email
);
if (userExists) {
throw new UserEmailExistsError();
}
validatePassword(ctx, data.password);
const hashedPassword = await getHashedPassword(data.password);
const emailConfirmToken = uuid();
const newUser = await ctx.graphqlAuthentication.adapter.createUserBySignup(
ctx,
{
name: data.name,
email: data.email,
password: hashedPassword,
emailConfirmToken,
emailConfirmed: false,
inviteAccepted: true,
joinedAt: new Date().toISOString()
}
);
if (ctx.graphqlAuthentication.mailer) {
ctx.graphqlAuthentication.mailer.send({
template: 'signupUser',
message: {
to: newUser.email
},
locals: {
mailAppUrl: ctx.graphqlAuthentication.mailAppUrl,
emailConfirmToken,
email: newUser.email
}
});
}
return {
token: generateToken(newUser, ctx),
user: newUser
};
},
async confirmEmail(
parent: any,
{ emailConfirmToken, email }: { emailConfirmToken: string; email: string },
ctx: Context
) {
if (!emailConfirmToken || !email) {
throw new MissingDataError();
}
const user = await ctx.graphqlAuthentication.adapter.findUserByEmail(
ctx,
email
);
if (!user) {
throw new UserNotFoundError();
}
if (user.emailConfirmToken !== emailConfirmToken || user.emailConfirmed) {
throw new InvalidEmailConfirmToken();
}
const updatedUser = await ctx.graphqlAuthentication.adapter.updateUserConfirmToken(
ctx,
user.id,
{
emailConfirmToken: '',
emailConfirmed: true
}
);
return {
token: generateToken(user, ctx),
user: updatedUser
};
},
async login(
parent: any,
{ email, password }: { email: string; password: string },
ctx: Context
) {
const user = await ctx.graphqlAuthentication.adapter.findUserByEmail(
ctx,
email
);
if (!user) {
throw new UserNotFoundError();
}
if (!user.inviteAccepted) {
throw new UserInviteNotAcceptedError();
}
if (user.deletedAt) {
throw new UserDeletedError();
}
if (
ctx.graphqlAuthentication.requiredConfirmedEmailForLogin &&
!user.emailConfirmed
) {
throw new UserEmailUnconfirmedError();
}
const valid = await bcrypt.compare(password, user.password);
if (!valid) {
throw new UserNotFoundError();
}
// Purposefully async, this update doesn't matter that much.
ctx.graphqlAuthentication.adapter.updateUserLastLogin(ctx, user.id, {
lastLogin: new Date().toISOString()
});
return {
token: generateToken(user, ctx),
user
};
},
async changePassword(
parent: any,
{ oldPassword, newPassword }: { oldPassword: string; newPassword: string },
ctx: Context
) {
const user = await getUser(ctx);
const valid = await bcrypt.compare(oldPassword, user.password);
if (!valid) {
throw new InvalidOldPasswordError();
}
validatePassword(ctx, newPassword);
const password = await getHashedPassword(newPassword);
const newUser = await ctx.graphqlAuthentication.adapter.updateUserPassword(
ctx,
user.id,
{ password }
);
return {
id: newUser!.id
};
},
async inviteUser(
parent: any,
{ data }: { data: InviteUserInput },
ctx: Context
) {
await getUser(ctx);
if (!validator.isEmail(data.email)) {
throw new InvalidEmailError();
}
const existingUser = await ctx.graphqlAuthentication.adapter.findUserByEmail(
ctx,
data.email
);
if (existingUser) {
if (ctx.graphqlAuthentication.hookInviteUserPostCreate) {
await ctx.graphqlAuthentication.hookInviteUserPostCreate(
data,
ctx,
existingUser
);
}
return {
id: existingUser.id
};
}
// This token will be used in the email to the user.
// According to https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba
// uuid v4 is safe to be used as random token generator.
const inviteToken = uuid();
const newUser = await ctx.graphqlAuthentication.adapter.createUserByInvite(
ctx,
{
email: data.email,
inviteToken,
inviteAccepted: false,
password: '',
name: '',
joinedAt: new Date().toISOString()
}
);
if (ctx.graphqlAuthentication.hookInviteUserPostCreate) {
await ctx.graphqlAuthentication.hookInviteUserPostCreate(
data,
ctx,
newUser
);
}
if (ctx.graphqlAuthentication.mailer) {
ctx.graphqlAuthentication.mailer.send({
template: 'inviteUser',
message: {
to: newUser.email
},
locals: {
mailAppUrl: ctx.graphqlAuthentication.mailAppUrl,
inviteToken,
email: newUser.email
}
});
}
return {
id: newUser.id
};
},
async triggerPasswordReset(
parent: any,
{ email }: { email: string },
ctx: Context
) {
if (!validator.isEmail(email)) {
throw new InvalidEmailError();
}
const user = await ctx.graphqlAuthentication.adapter.findUserByEmail(
ctx,
email
);
if (!user) {
return { ok: true };
}
// This token will be used in the email to the user.
// According to https://gist.github.com/joepie91/7105003c3b26e65efcea63f3db82dfba
// uuid v4 is safe to be used as random token generator.
const resetToken = uuid();
const now = new Date();
// Expires in two hours
const resetExpires = new Date(now.getTime() + 7200000).toISOString();
await ctx.graphqlAuthentication.adapter.updateUserResetToken(ctx, user.id, {
resetToken,
resetExpires
});
if (ctx.graphqlAuthentication.mailer) {
ctx.graphqlAuthentication.mailer.send({
template: 'passwordReset',
message: {
to: user.email
},
locals: {
mailAppUrl: ctx.graphqlAuthentication.mailAppUrl,
resetToken,
email
}
});
}
return {
ok: true
};
},
async passwordReset(
parent: any,
{
email,
resetToken,
password
}: { email: string; resetToken: string; password: string },
ctx: Context
) {
if (!resetToken || !password) {
throw new MissingDataError();
}
const user = await ctx.graphqlAuthentication.adapter.findUserByEmail(
ctx,
email
);
if (!user || !user.resetExpires || user.resetToken !== resetToken) {
throw new UserNotFoundError();
}
if (new Date() > new Date(user.resetExpires)) {
throw new ResetTokenExpiredError();
}
validatePassword(ctx, password);
const hashedPassword = await getHashedPassword(password);
await ctx.graphqlAuthentication.adapter.updateUserResetToken(ctx, user.id, {
resetToken: '',
resetExpires: undefined
});
await ctx.graphqlAuthentication.adapter.updateUserPassword(ctx, user.id, {
password: hashedPassword
});
return {
id: user.id
};
},
async updateCurrentUser(
parent: any,
{ data }: { data: UserUpdateInput },
ctx: Context
) {
const user = await getUser(ctx);
await ctx.graphqlAuthentication.adapter.updateUserInfo(ctx, user.id, data);
return user;
}
};
================================================
FILE: packages/graphql-authentication/src/queries.ts
================================================
import { getUserId, Context } from './utils';
// Without this manual User interface import, TypeScript will create an incorrect queries.d.ts declaration file, WTF?
import { User } from './Adapter';
export const queries = {
currentUser(parent: any, args: any, ctx: Context, info: any) {
const id = getUserId(ctx);
return ctx.graphqlAuthentication.adapter.findUserById(ctx, id, info);
}
};
================================================
FILE: packages/graphql-authentication/src/schema.ts
================================================
import * as path from 'path';
import { makeExecutableSchema } from 'graphql-tools';
import { importSchema } from 'graphql-import';
// This is only used for generating `src/binding.ts`
export default makeExecutableSchema({
typeDefs: importSchema(path.resolve('schema.graphql'))
});
================================================
FILE: packages/graphql-authentication/src/utils.ts
================================================
import * as jwt from 'jsonwebtoken';
import { IGraphqlAuthenticationConfig } from './Config';
import { ID } from './Adapter';
export interface Context {
graphqlAuthentication: IGraphqlAuthenticationConfig;
request?: any;
req?: any;
}
function _getUserId(ctx: Context): string {
// For Apollo Server 2.0+ it is ctx.req and for GraphQL Yoga ctx.request. Maybe there is a better way...
const Authorization = (ctx.req || ctx.request).get('Authorization');
if (Authorization) {
const token = Authorization.replace('Bearer ', '');
const { userId } = jwt.verify(token, ctx.graphqlAuthentication.secret) as {
userId: ID;
};
return userId;
}
return '';
}
export function getUserId(ctx: Context): string {
const userId = _getUserId(ctx);
if (userId) {
return userId;
}
throw new AuthError();
}
export function getUser(ctx: Context): Promise<any> {
return ctx.graphqlAuthentication.adapter.findUserById(ctx, getUserId(ctx));
}
export class AuthError extends Error {
constructor() {
super('Not authorized');
}
}
export function isAuthResolver(parent: any, args: any, ctx: Context) {
return !!_getUserId(ctx);
}
================================================
FILE: packages/graphql-authentication/tsconfig.build.json
================================================
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src/index.ts"]
}
================================================
FILE: packages/graphql-authentication/tsconfig.json
================================================
{
"extends": "../../tsconfig.json"
}
================================================
FILE: packages/graphql-authentication-prisma/README.md
================================================
# GraphQL Authentication Prisma
A Prisma adapter for [Graphql Authentication](https://github.com/Volst/graphql-authentication/blob/master/README.md).
# Install
Node v8+ should be used. Install with Yarn or npm:
```
yarn add graphql-authentication graphql-authentication-prisma email-templates
npm i graphql-authentication graphql-authentication-prisma email-templates
```
# Usage with Prisma
You can read the guide below or checkout [the example](https://github.com/Volst/graphql-authentication/tree/master/examples/with-prisma) to see the full code.
## Step 1
Read the [Usage](https://github.com/Volst/graphql-authentication/blob/master/README.md#usage) section in the full documentation first.
## Step 2
After configuring the basics, you can now add this package as an adapter. Pseudo-code example:
```js
import { GraphqlAuthenticationPrismaAdapter } from 'graphql-authentication-prisma';
graphqlAuthentication: graphqlAuthenticationConfig({
adapter: new GraphqlAuthenticationPrismaAdapter({
// Optional, defaults to 'db'
prismaContextName: 'db'
})
});
```
## Step 3
In your Prisma `datamodel.graphql` file, add this [User model](https://github.com/Volst/graphql-authentication/blob/master/examples/with-prisma/datamodel.graphql). Run `prisma deploy` to run the migrations.
### [Full Documentation](https://github.com/Volst/graphql-authentication/blob/master/README.md#documentation)
================================================
FILE: packages/graphql-authentication-prisma/package.json
================================================
{
"name": "graphql-authentication-prisma",
"version": "0.1.5",
"description": "Prisma adapter for graphql-authentication",
"author": "kees@volst.nl",
"repository": "Volst/graphql-authentication",
"keywords": [
"graphql",
"user",
"authentication",
"login",
"prisma"
],
"license": "ISC",
"private": false,
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"engines": {
"node": ">=8.0"
},
"files": [
"dist"
],
"scripts": {
"build": "rm -rf dist && tsc -p tsconfig.build.json",
"lint": "tslint -p .",
"prepublishOnly": "npm run -s build",
"test": "jest --watch",
"test-coverage": "jest --coverage",
"ci": "npm run -s lint && npm run -s build && npm run -s test-coverage && codecov"
},
"devDependencies": {
"@types/email-templates": "^3.5.0",
"@types/jest": "^23.1.0",
"@volst/tslint-config": "^0.2.1",
"codecov": "^3.0.2",
"email-templates": "^4.0.1",
"graphql-authentication": "^0.5.5",
"graphql-cli": "^2.15.13",
"graphql-request": "^1.6.0",
"graphql-yoga": "1.14.10",
"jest": "^23.1.0",
"nodemon": "^1.17.3",
"prisma-binding": "^2.0.0",
"pug": "^2.0.3",
"ts-jest": "^22.4.6",
"ts-node": "^7.0.0",
"tslint": "^5.9.1",
"typescript": "^2.8.3"
},
"dependencies": {
"@types/bcryptjs": "^2.4.1",
"@types/jsonwebtoken": "^7.2.6",
"@types/uuid": "^3.4.3",
"@types/validator": "^9.4.1",
"apollo-errors": "^1.9.0",
"bcryptjs": "^2.4.3",
"jsonwebtoken": "^8.2.1",
"uuid": "^3.2.1",
"validator": "^10.2.0"
},
"peerDependencies": {
"graphql-authentication": "^0.5.0",
"prisma-binding": "^2.0.0"
},
"jest": {
"roots": [
"./src"
],
"transform": {
"^.+\\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"js",
"json",
"node"
]
}
}
================================================
FILE: packages/graphql-authentication-prisma/src/Prisma.ts
================================================
import { Prisma, User } from './generated/prisma';
import { GraphqlAuthenticationAdapter, ID } from 'graphql-authentication';
export class GraphqlAuthenticationPrismaAdapter
implements GraphqlAuthenticationAdapter {
prismaContextName = 'db';
constructor(options: { prismaContextName?: string } = {}) {
if (options && options.prismaContextName) {
this.prismaContextName = options.prismaContextName;
}
}
private db(ctx: object) {
const db: Prisma = ctx[this.prismaContextName];
if (!db) {
throw new Error(
`The Prisma binding is not attached to the \`${
this.prismaContextName
}\` property on your context.`
);
}
return db;
}
findUserById(ctx: object, id: ID, info?: any) {
return this.db(ctx).query.user({ where: { id } }, info);
}
findUserByEmail(ctx: object, email: string, info?: any) {
return this.db(ctx).query.user(
{
where: { email: email }
},
info
);
}
userExistsByEmail(ctx: object, email: string) {
return this.db(ctx).exists.User({ email });
}
private createUser(ctx: object, data: any) {
return this.db(ctx).mutation.createUser({
data
});
}
createUserBySignup(ctx: object, data: any) {
return this.createUser(ctx, data);
}
createUserByInvite(ctx: object, data: any) {
return this.createUser(ctx, data);
}
private updateUser(ctx: object, userId: ID, data: any) {
return this.db(ctx).mutation.updateUser({
where: { id: userId },
data
});
}
updateUserConfirmToken(ctx: object, userId: ID, data: any) {
return this.updateUser(ctx, userId, data);
}
updateUserLastLogin(ctx: object, userId: ID, data: any) {
return this.updateUser(ctx, userId, data);
}
updateUserPassword(ctx: object, userId: ID, data: any) {
return this.updateUser(ctx, userId, data);
}
updateUserResetToken(ctx: object, userId: ID, data: any) {
return this.updateUser(ctx, userId, data);
}
updateUserInfo(ctx: object, userId: ID, data: any) {
return this.updateUser(ctx, userId, data);
}
updateUserCompleteInvite(ctx: object, userId: ID, data: any) {
return this.updateUser(ctx, userId, data);
}
}
================================================
FILE: packages/graphql-authentication-prisma/src/generated/prisma.graphql
================================================
# source: http://localhost:4466
# timestamp: Sun Jun 17 2018 19:34:23 GMT+0200 (CEST)
type AggregateUser {
count: Int!
}
type BatchPayload {
"""
The number of nodes that have been affected by the Batch operation.
"""
count: Long!
}
scalar DateTime
"""
The `Long` scalar type represents non-fractional signed whole numeric values.
Long can represent values between -(2^63) and 2^63 - 1.
"""
scalar Long
type Mutation {
createUser(data: UserCreateInput!): User!
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
deleteUser(where: UserWhereUniqueInput!): User
upsertUser(
where: UserWhereUniqueInput!
create: UserCreateInput!
update: UserUpdateInput!
): User!
updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
deleteManyUsers(where: UserWhereInput): BatchPayload!
}
enum MutationType {
CREATED
UPDATED
DELETED
}
"""
An object with an ID
"""
interface Node {
"""
The id of the object.
"""
id: ID!
}
"""
Information about pagination in a connection.
"""
type PageInfo {
"""
When paginating forwards, are there more items?
"""
hasNextPage: Boolean!
"""
When paginating backwards, are there more items?
"""
hasPreviousPage: Boolean!
"""
When paginating backwards, the cursor to continue.
"""
startCursor: String
"""
When paginating forwards, the cursor to continue.
"""
endCursor: String
}
type Query {
users(
where: UserWhereInput
orderBy: UserOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): [User]!
user(where: UserWhereUniqueInput!): User
usersConnection(
where: UserWhereInput
orderBy: UserOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): UserConnection!
"""
Fetches an object given its ID
"""
node(
"""
The ID of an object
"""
id: ID!
): Node
}
type Subscription {
user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}
type User implements Node {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
"""
A connection to a list of items.
"""
type UserConnection {
"""
Information to aid in pagination.
"""
pageInfo: PageInfo!
"""
A list of edges.
"""
edges: [UserEdge]!
aggregate: AggregateUser!
}
input UserCreateInput {
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean
}
"""
An edge in a connection.
"""
type UserEdge {
"""
The item at the end of the edge.
"""
node: User!
"""
A cursor for use in pagination.
"""
cursor: String!
}
enum UserOrderByInput {
id_ASC
id_DESC
email_ASC
email_DESC
password_ASC
password_DESC
name_ASC
name_DESC
inviteToken_ASC
inviteToken_DESC
inviteAccepted_ASC
inviteAccepted_DESC
emailConfirmed_ASC
emailConfirmed_DESC
emailConfirmToken_ASC
emailConfirmToken_DESC
resetToken_ASC
resetToken_DESC
resetExpires_ASC
resetExpires_DESC
deletedAt_ASC
deletedAt_DESC
lastLogin_ASC
lastLogin_DESC
joinedAt_ASC
joinedAt_DESC
isSuper_ASC
isSuper_DESC
updatedAt_ASC
updatedAt_DESC
createdAt_ASC
createdAt_DESC
}
type UserPreviousValues {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
type UserSubscriptionPayload {
mutation: MutationType!
node: User
updatedFields: [String!]
previousValues: UserPreviousValues
}
input UserSubscriptionWhereInput {
"""
Logical AND on all given filters.
"""
AND: [UserSubscriptionWhereInput!]
"""
Logical OR on all given filters.
"""
OR: [UserSubscriptionWhereInput!]
"""
Logical NOT on all given filters combined by AND.
"""
NOT: [UserSubscriptionWhereInput!]
"""
The subscription event gets dispatched when it's listed in mutation_in
"""
mutation_in: [MutationType!]
"""
The subscription event gets only dispatched when one of the updated fields names is included in this list
"""
updatedFields_contains: String
"""
The subscription event gets only dispatched when all of the field names included in this list have been updated
"""
updatedFields_contains_every: [String!]
"""
The subscription event gets only dispatched when some of the field names included in this list have been updated
"""
updatedFields_contains_some: [String!]
node: UserWhereInput
}
input UserUpdateInput {
email: String
password: String
name: String
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime
isSuper: Boolean
}
input UserWhereInput {
"""
Logical AND on all given filters.
"""
AND: [UserWhereInput!]
"""
Logical OR on all given filters.
"""
OR: [UserWhereInput!]
"""
Logical NOT on all given filters combined by AND.
"""
NOT: [UserWhereInput!]
id: ID
"""
All values that are not equal to given value.
"""
id_not: ID
"""
All values that are contained in given list.
"""
id_in: [ID!]
"""
All values that are not contained in given list.
"""
id_not_in: [ID!]
"""
All values less than the given value.
"""
id_lt: ID
"""
All values less than or equal the given value.
"""
id_lte: ID
"""
All values greater than the given value.
"""
id_gt: ID
"""
All values greater than or equal the given value.
"""
id_gte: ID
"""
All values containing the given string.
"""
id_contains: ID
"""
All values not containing the given string.
"""
id_not_contains: ID
"""
All values starting with the given string.
"""
id_starts_with: ID
"""
All values not starting with the given string.
"""
id_not_starts_with: ID
"""
All values ending with the given string.
"""
id_ends_with: ID
"""
All values not ending with the given string.
"""
id_not_ends_with: ID
email: String
"""
All values that are not equal to given value.
"""
email_not: String
"""
All values that are contained in given list.
"""
email_in: [String!]
"""
All values that are not contained in given list.
"""
email_not_in: [String!]
"""
All values less than the given value.
"""
email_lt: String
"""
All values less than or equal the given value.
"""
email_lte: String
"""
All values greater than the given value.
"""
email_gt: String
"""
All values greater than or equal the given value.
"""
email_gte: String
"""
All values containing the given string.
"""
email_contains: String
"""
All values not containing the given string.
"""
email_not_contains: String
"""
All values starting with the given string.
"""
email_starts_with: String
"""
All values not starting with the given string.
"""
email_not_starts_with: String
"""
All values ending with the given string.
"""
email_ends_with: String
"""
All values not ending with the given string.
"""
email_not_ends_with: String
password: String
"""
All values that are not equal to given value.
"""
password_not: String
"""
All values that are contained in given list.
"""
password_in: [String!]
"""
All values that are not contained in given list.
"""
password_not_in: [String!]
"""
All values less than the given value.
"""
password_lt: String
"""
All values less than or equal the given value.
"""
password_lte: String
"""
All values greater than the given value.
"""
password_gt: String
"""
All values greater than or equal the given value.
"""
password_gte: String
"""
All values containing the given string.
"""
password_contains: String
"""
All values not containing the given string.
"""
password_not_contains: String
"""
All values starting with the given string.
"""
password_starts_with: String
"""
All values not starting with the given string.
"""
password_not_starts_with: String
"""
All values ending with the given string.
"""
password_ends_with: String
"""
All values not ending with the given string.
"""
password_not_ends_with: String
name: String
"""
All values that are not equal to given value.
"""
name_not: String
"""
All values that are contained in given list.
"""
name_in: [String!]
"""
All values that are not contained in given list.
"""
name_not_in: [String!]
"""
All values less than the given value.
"""
name_lt: String
"""
All values less than or equal the given value.
"""
name_lte: String
"""
All values greater than the given value.
"""
name_gt: String
"""
All values greater than or equal the given value.
"""
name_gte: String
"""
All values containing the given string.
"""
name_contains: String
"""
All values not containing the given string.
"""
name_not_contains: String
"""
All values starting with the given string.
"""
name_starts_with: String
"""
All values not starting with the given string.
"""
name_not_starts_with: String
"""
All values ending with the given string.
"""
name_ends_with: String
"""
All values not ending with the given string.
"""
name_not_ends_with: String
inviteToken: String
"""
All values that are not equal to given value.
"""
inviteToken_not: String
"""
All values that are contained in given list.
"""
inviteToken_in: [String!]
"""
All values that are not contained in given list.
"""
inviteToken_not_in: [String!]
"""
All values less than the given value.
"""
inviteToken_lt: String
"""
All values less than or equal the given value.
"""
inviteToken_lte: String
"""
All values greater than the given value.
"""
inviteToken_gt: String
"""
All values greater than or equal the given value.
"""
inviteToken_gte: String
"""
All values containing the given string.
"""
inviteToken_contains: String
"""
All values not containing the given string.
"""
inviteToken_not_contains: String
"""
All values starting with the given string.
"""
inviteToken_starts_with: String
"""
All values not starting with the given string.
"""
inviteToken_not_starts_with: String
"""
All values ending with the given string.
"""
inviteToken_ends_with: String
"""
All values not ending with the given string.
"""
inviteToken_not_ends_with: String
inviteAccepted: Boolean
"""
All values that are not equal to given value.
"""
inviteAccepted_not: Boolean
emailConfirmed: Boolean
"""
All values that are not equal to given value.
"""
emailConfirmed_not: Boolean
emailConfirmToken: String
"""
All values that are not equal to given value.
"""
emailConfirmToken_not: String
"""
All values that are contained in given list.
"""
emailConfirmToken_in: [String!]
"""
All values that are not contained in given list.
"""
emailConfirmToken_not_in: [String!]
"""
All values less than the given value.
"""
emailConfirmToken_lt: String
"""
All values less than or equal the given value.
"""
emailConfirmToken_lte: String
"""
All values greater than the given value.
"""
emailConfirmToken_gt: String
"""
All values greater than or equal the given value.
"""
emailConfirmToken_gte: String
"""
All values containing the given string.
"""
emailConfirmToken_contains: String
"""
All values not containing the given string.
"""
emailConfirmToken_not_contains: String
"""
All values starting with the given string.
"""
emailConfirmToken_starts_with: String
"""
All values not starting with the given string.
"""
emailConfirmToken_not_starts_with: String
"""
All values ending with the given string.
"""
emailConfirmToken_ends_with: String
"""
All values not ending with the given string.
"""
emailConfirmToken_not_ends_with: String
resetToken: String
"""
All values that are not equal to given value.
"""
resetToken_not: String
"""
All values that are contained in given list.
"""
resetToken_in: [String!]
"""
All values that are not contained in given list.
"""
resetToken_not_in: [String!]
"""
All values less than the given value.
"""
resetToken_lt: String
"""
All values less than or equal the given value.
"""
resetToken_lte: String
"""
All values greater than the given value.
"""
resetToken_gt: String
"""
All values greater than or equal the given value.
"""
resetToken_gte: String
"""
All values containing the given string.
"""
resetToken_contains: String
"""
All values not containing the given string.
"""
resetToken_not_contains: String
"""
All values starting with the given string.
"""
resetToken_starts_with: String
"""
All values not starting with the given string.
"""
resetToken_not_starts_with: String
"""
All values ending with the given string.
"""
resetToken_ends_with: String
"""
All values not ending with the given string.
"""
resetToken_not_ends_with: String
resetExpires: DateTime
"""
All values that are not equal to given value.
"""
resetExpires_not: DateTime
"""
All values that are contained in given list.
"""
resetExpires_in: [DateTime!]
"""
All values that are not contained in given list.
"""
resetExpires_not_in: [DateTime!]
"""
All values less than the given value.
"""
resetExpires_lt: DateTime
"""
All values less than or equal the given value.
"""
resetExpires_lte: DateTime
"""
All values greater than the given value.
"""
resetExpires_gt: DateTime
"""
All values greater than or equal the given value.
"""
resetExpires_gte: DateTime
deletedAt: DateTime
"""
All values that are not equal to given value.
"""
deletedAt_not: DateTime
"""
All values that are contained in given list.
"""
deletedAt_in: [DateTime!]
"""
All values that are not contained in given list.
"""
deletedAt_not_in: [DateTime!]
"""
All values less than the given value.
"""
deletedAt_lt: DateTime
"""
All values less than or equal the given value.
"""
deletedAt_lte: DateTime
"""
All values greater than the given value.
"""
deletedAt_gt: DateTime
"""
All values greater than or equal the given value.
"""
deletedAt_gte: DateTime
lastLogin: DateTime
"""
All values that are not equal to given value.
"""
lastLogin_not: DateTime
"""
All values that are contained in given list.
"""
lastLogin_in: [DateTime!]
"""
All values that are not contained in given list.
"""
lastLogin_not_in: [DateTime!]
"""
All values less than the given value.
"""
lastLogin_lt: DateTime
"""
All values less than or equal the given value.
"""
lastLogin_lte: DateTime
"""
All values greater than the given value.
"""
lastLogin_gt: DateTime
"""
All values greater than or equal the given value.
"""
lastLogin_gte: DateTime
joinedAt: DateTime
"""
All values that are not equal to given value.
"""
joinedAt_not: DateTime
"""
All values that are contained in given list.
"""
joinedAt_in: [DateTime!]
"""
All values that are not contained in given list.
"""
joinedAt_not_in: [DateTime!]
"""
All values less than the given value.
"""
joinedAt_lt: DateTime
"""
All values less than or equal the given value.
"""
joinedAt_lte: DateTime
"""
All values greater than the given value.
"""
joinedAt_gt: DateTime
"""
All values greater than or equal the given value.
"""
joinedAt_gte: DateTime
isSuper: Boolean
"""
All values that are not equal to given value.
"""
isSuper_not: Boolean
}
input UserWhereUniqueInput {
id: ID
email: String
}
================================================
FILE: packages/graphql-authentication-prisma/src/generated/prisma.ts
================================================
import { GraphQLResolveInfo, GraphQLSchema } from 'graphql';
import { IResolvers } from 'graphql-tools/dist/Interfaces';
import { Options } from 'graphql-binding';
import { makePrismaBindingClass, BasePrismaOptions } from 'prisma-binding';
export interface Query {
users: <T = User[]>(
args: {
where?: UserWhereInput;
orderBy?: UserOrderByInput;
skip?: Int;
after?: String;
before?: String;
first?: Int;
last?: Int;
},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
user: <T = User | null>(
args: { where: UserWhereUniqueInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
usersConnection: <T = UserConnection>(
args: {
where?: UserWhereInput;
orderBy?: UserOrderByInput;
skip?: Int;
after?: String;
before?: String;
first?: Int;
last?: Int;
},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
node: <T = Node | null>(
args: { id: ID_Output },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
}
export interface Mutation {
createUser: <T = User>(
args: { data: UserCreateInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
updateUser: <T = User | null>(
args: { data: UserUpdateInput; where: UserWhereUniqueInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
deleteUser: <T = User | null>(
args: { where: UserWhereUniqueInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
upsertUser: <T = User>(
args: {
where: UserWhereUniqueInput;
create: UserCreateInput;
update: UserUpdateInput;
},
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
updateManyUsers: <T = BatchPayload>(
args: { data: UserUpdateInput; where?: UserWhereInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
deleteManyUsers: <T = BatchPayload>(
args: { where?: UserWhereInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<T>;
}
export interface Subscription {
user: <T = UserSubscriptionPayload | null>(
args: { where?: UserSubscriptionWhereInput },
info?: GraphQLResolveInfo | string,
options?: Options
) => Promise<AsyncIterator<T>>;
}
export interface Exists {
User: (where?: UserWhereInput) => Promise<boolean>;
}
export interface Prisma {
query: Query;
mutation: Mutation;
subscription: Subscription;
exists: Exists;
request: <T = any>(
query: string,
variables?: { [key: string]: any }
) => Promise<T>;
delegate(
operation: 'query' | 'mutation',
fieldName: string,
args: {
[key: string]: any;
},
infoOrQuery?: GraphQLResolveInfo | string,
options?: Options
): Promise<any>;
delegateSubscription(
fieldName: string,
args?: {
[key: string]: any;
},
infoOrQuery?: GraphQLResolveInfo | string,
options?: Options
): Promise<AsyncIterator<any>>;
getAbstractResolvers(filterSchema?: GraphQLSchema | string): IResolvers;
}
export interface BindingConstructor<T> {
new (options: BasePrismaOptions): T;
}
/**
* Type Defs
*/
const typeDefs = `type AggregateUser {
count: Int!
}
type BatchPayload {
"""The number of nodes that have been affected by the Batch operation."""
count: Long!
}
scalar DateTime
"""
The \`Long\` scalar type represents non-fractional signed whole numeric values.
Long can represent values between -(2^63) and 2^63 - 1.
"""
scalar Long
type Mutation {
createUser(data: UserCreateInput!): User!
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
deleteUser(where: UserWhereUniqueInput!): User
upsertUser(where: UserWhereUniqueInput!, create: UserCreateInput!, update: UserUpdateInput!): User!
updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
deleteManyUsers(where: UserWhereInput): BatchPayload!
}
enum MutationType {
CREATED
UPDATED
DELETED
}
"""An object with an ID"""
interface Node {
"""The id of the object."""
id: ID!
}
"""Information about pagination in a connection."""
type PageInfo {
"""When paginating forwards, are there more items?"""
hasNextPage: Boolean!
"""When paginating backwards, are there more items?"""
hasPreviousPage: Boolean!
"""When paginating backwards, the cursor to continue."""
startCursor: String
"""When paginating forwards, the cursor to continue."""
endCursor: String
}
type Query {
users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
user(where: UserWhereUniqueInput!): User
usersConnection(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): UserConnection!
"""Fetches an object given its ID"""
node(
"""The ID of an object"""
id: ID!
): Node
}
type Subscription {
user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}
type User implements Node {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
"""A connection to a list of items."""
type UserConnection {
"""Information to aid in pagination."""
pageInfo: PageInfo!
"""A list of edges."""
edges: [UserEdge]!
aggregate: AggregateUser!
}
input UserCreateInput {
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean
}
"""An edge in a connection."""
type UserEdge {
"""The item at the end of the edge."""
node: User!
"""A cursor for use in pagination."""
cursor: String!
}
enum UserOrderByInput {
id_ASC
id_DESC
email_ASC
email_DESC
password_ASC
password_DESC
name_ASC
name_DESC
inviteToken_ASC
inviteToken_DESC
inviteAccepted_ASC
inviteAccepted_DESC
emailConfirmed_ASC
emailConfirmed_DESC
emailConfirmToken_ASC
emailConfirmToken_DESC
resetToken_ASC
resetToken_DESC
resetExpires_ASC
resetExpires_DESC
deletedAt_ASC
deletedAt_DESC
lastLogin_ASC
lastLogin_DESC
joinedAt_ASC
joinedAt_DESC
isSuper_ASC
isSuper_DESC
updatedAt_ASC
updatedAt_DESC
createdAt_ASC
createdAt_DESC
}
type UserPreviousValues {
id: ID!
email: String!
password: String!
name: String!
inviteToken: String
inviteAccepted: Boolean!
emailConfirmed: Boolean!
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime!
isSuper: Boolean!
}
type UserSubscriptionPayload {
mutation: MutationType!
node: User
updatedFields: [String!]
previousValues: UserPreviousValues
}
input UserSubscriptionWhereInput {
"""Logical AND on all given filters."""
AND: [UserSubscriptionWhereInput!]
"""Logical OR on all given filters."""
OR: [UserSubscriptionWhereInput!]
"""Logical NOT on all given filters combined by AND."""
NOT: [UserSubscriptionWhereInput!]
"""
The subscription event gets dispatched when it's listed in mutation_in
"""
mutation_in: [MutationType!]
"""
The subscription event gets only dispatched when one of the updated fields names is included in this list
"""
updatedFields_contains: String
"""
The subscription event gets only dispatched when all of the field names included in this list have been updated
"""
updatedFields_contains_every: [String!]
"""
The subscription event gets only dispatched when some of the field names included in this list have been updated
"""
updatedFields_contains_some: [String!]
node: UserWhereInput
}
input UserUpdateInput {
email: String
password: String
name: String
inviteToken: String
inviteAccepted: Boolean
emailConfirmed: Boolean
emailConfirmToken: String
resetToken: String
resetExpires: DateTime
deletedAt: DateTime
lastLogin: DateTime
joinedAt: DateTime
isSuper: Boolean
}
input UserWhereInput {
"""Logical AND on all given filters."""
AND: [UserWhereInput!]
"""Logical OR on all given filters."""
OR: [UserWhereInput!]
"""Logical NOT on all given filters combined by AND."""
NOT: [UserWhereInput!]
id: ID
"""All values that are not equal to given value."""
id_not: ID
"""All values that are contained in given list."""
id_in: [ID!]
"""All values that are not contained in given list."""
id_not_in: [ID!]
"""All values less than the given value."""
id_lt: ID
"""All values less than or equal the given value."""
id_lte: ID
"""All values greater than the given value."""
id_gt: ID
"""All values greater than or equal the given value."""
id_gte: ID
"""All values containing the given string."""
id_contains: ID
"""All values not containing the given string."""
id_not_contains: ID
"""All values starting with the given string."""
id_starts_with: ID
"""All values not starting with the given string."""
id_not_starts_with: ID
"""All values ending with the given string."""
id_ends_with: ID
"""All values not ending with the given string."""
id_not_ends_with: ID
email: String
"""All values that are not equal to given value."""
email_not: String
"""All values that are contained in given list."""
email_in: [String!]
"""All values that are not contained in given list."""
email_not_in: [String!]
"""All values less than the given value."""
email_lt: String
"""All values less than or equal the given value."""
email_lte: String
"""All values greater than the given value."""
email_gt: String
"""All values greater than or equal the given value."""
email_gte: String
"""All values containing the given string."""
email_contains: String
"""All values not containing the given string."""
email_not_contains: String
"""All values starting with the given string."""
email_starts_with: String
"""All values not starting with the given string."""
email_not_starts_with: String
"""All values ending with the given string."""
email_ends_with: String
"""All values not ending with the given string."""
email_not_ends_with: String
password: String
"""All values that are not equal to given value."""
password_not: String
"""All values that are contained in given list."""
password_in: [String!]
"""All values that are not contained in given list."""
password_not_in: [String!]
"""All values less than the given value."""
password_lt: String
"""All values less than or equal the given value."""
password_lte: String
"""All values greater than the given value."""
password_gt: String
"""All values greater than or equal the given value."""
password_gte: String
"""All values containing the given string."""
password_contains: String
"""All values not containing the given string."""
password_not_contains: String
"""All values starting with the given string."""
password_starts_with: String
"""All values not starting with the given string."""
password_not_starts_with: String
"""All values ending with the given string."""
password_ends_with: String
"""All values not ending with the given string."""
password_not_ends_with: String
name: String
"""All values that are not equal to given value."""
name_not: String
"""All values that are contained in given list."""
name_in: [String!]
"""All values that are not contained in given list."""
name_not_in: [String!]
"""All values less than the given value."""
name_lt: String
"""All values less than or equal the given value."""
name_lte: String
"""All values greater than the given value."""
name_gt: String
"""All values greater than or equal the given value."""
name_gte: String
"""All values containing the given string."""
name_contains: String
"""All values not containing the given string."""
name_not_contains: String
"""All values starting with the given string."""
name_starts_with: String
"""All values not starting with the given string."""
name_not_starts_with: String
"""All values ending with the given string."""
name_ends_with: String
"""All values not ending with the given string."""
name_not_ends_with: String
inviteToken: String
"""All values that are not equal to given value."""
inviteToken_not: String
"""All values that are contained in given list."""
inviteToken_in: [String!]
"""All values that are not contained in given list."""
inviteToken_not_in: [String!]
"""All values less than the given value."""
inviteToken_lt: String
"""All values less than or equal the given value."""
inviteToken_lte: String
"""All values greater than the given value."""
inviteToken_gt: String
"""All values greater than or equal the given value."""
inviteToken_gte: String
"""All values containing the given string."""
inviteToken_contains: String
"""All values not containing the given string."""
inviteToken_not_contains: String
"""All values starting with the given string."""
inviteToken_starts_with: String
"""All values not starting with the given string."""
inviteToken_not_starts_with: String
"""All values ending with the given string."""
inviteToken_ends_with: String
"""All values not ending with the given string."""
inviteToken_not_ends_with: String
inviteAccepted: Boolean
"""All values that are not equal to given value."""
inviteAccepted_not: Boolean
emailConfirmed: Boolean
"""All values that are not equal to given value."""
emailConfirmed_not: Boolean
emailConfirmToken: String
"""All values that are not equal to given value."""
emailConfirmToken_not: String
"""All values that are contained in given list."""
emailConfirmToken_in: [String!]
"""All values that are not contained in given list."""
emailConfirmToken_not_in: [String!]
"""All values less than the given value."""
emailConfirmToken_lt: String
"""All values less than or equal the given value."""
emailConfirmToken_lte: String
"""All values greater than the given value."""
emailConfirmToken_gt: String
"""All values greater than or equal the given value."""
emailConfirmToken_gte: String
"""All values containing the given string."""
emailConfirmToken_contains: String
"""All values not containing the given string."""
emailConfirmToken_not_contains: String
"""All values starting with the given string."""
emailConfirmToken_starts_with: String
"""All values not starting with the given string."""
emailConfirmToken_not_starts_with: String
"""All values ending with the given string."""
emailConfirmToken_ends_with: String
"""All values not ending with the given string."""
emailConfirmToken_not_ends_with: String
resetToken: String
"""All values that are not equal to given value."""
resetToken_not: String
"""All values that are contained in given list."""
resetToken_in: [String!]
"""All values that are not contained in given list."""
resetToken_not_in: [String!]
"""All values less than the given value."""
resetToken_lt: String
"""All values less than or equal the given value."""
resetToken_lte: String
"""All values greater than the given value."""
resetToken_gt: String
"""All values greater than or equal the given value."""
resetToken_gte: String
"""All values containing the given string."""
resetToken_contains: String
"""All values not containing the given string."""
resetToken_not_contains: String
"""All values starting with the given string."""
resetToken_starts_with: String
"""All values not starting with the given string."""
resetToken_not_starts_with: String
"""All values ending with the given string."""
resetToken_ends_with: String
"""All values not ending with the given string."""
resetToken_not_ends_with: String
resetExpires: DateTime
"""All values that are not equal to given value."""
resetExpires_not: DateTime
"""All values that are contained in given list."""
resetExpires_in: [DateTime!]
"""All values that are not contained in given list."""
resetExpires_not_in: [DateTime!]
"""All values less than the given value."""
resetExpires_lt: DateTime
"""All values less than or equal the given value."""
resetExpires_lte: DateTime
"""All values greater than the given value."""
resetExpires_gt: DateTime
"""All values greater than or equal the given value."""
resetExpires_gte: DateTime
deletedAt: DateTime
"""All values that are not equal to given value."""
deletedAt_not: DateTime
"""All values that are contained in given list."""
deletedAt_in: [DateTime!]
"""All values that are not contained in given list."""
deletedAt_not_in: [DateTime!]
"""All values less than the given value."""
deletedAt_lt: DateTime
"""All values less than or equal the given value."""
deletedAt_lte: DateTime
"""All values greater than the given value."""
deletedAt_gt: DateTime
"""All values greater than or equal the given value."""
deletedAt_gte: DateTime
lastLogin: DateTime
"""All values that are not equal to given value."""
lastLogin_not: DateTime
"""All values that are contained in given list."""
lastLogin_in: [DateTime!]
"""All values that are not contained in given list."""
lastLogin_not_in: [DateTime!]
"""All values less than the given value."""
lastLogin_lt: DateTime
"""All values less than or equal the given value."""
lastLogin_lte: DateTime
"""All values greater than the given value."""
lastLogin_gt: DateTime
"""All values greater than or equal the given value."""
lastLogin_gte: DateTime
joinedAt: DateTime
"""All values that are not equal to given value."""
joinedAt_not: DateTime
"""All values that are contained in given list."""
joinedAt_in: [DateTime!]
"""All values that are not contained in given list."""
joinedAt_not_in: [DateTime!]
"""All values less than the given value."""
joinedAt_lt: DateTime
"""All values less than or equal the given value."""
joinedAt_lte: DateTime
"""All values greater than the given value."""
joinedAt_gt: DateTime
"""All values greater than or equal the given value."""
joinedAt_gte: DateTime
isSuper: Boolean
"""All values that are not equal to given value."""
isSuper_not: Boolean
}
input UserWhereUniqueInput {
id: ID
email: String
}
`;
export const Prisma = makePrismaBindingClass<BindingConstructor<Prisma>>({
typeDefs
});
/**
* Types
*/
export type UserOrderByInput =
| 'id_ASC'
| 'id_DESC'
| 'email_ASC'
| 'email_DESC'
| 'password_ASC'
| 'password_DESC'
| 'name_ASC'
| 'name_DESC'
| 'inviteToken_ASC'
| 'inviteToken_DESC'
| 'inviteAccepted_ASC'
| 'inviteAccepted_DESC'
| 'emailConfirmed_ASC'
| 'emailConfirmed_DESC'
| 'emailConfirmToken_ASC'
| 'emailConfirmToken_DESC'
| 'resetToken_ASC'
| 'resetToken_DESC'
| 'resetExpires_ASC'
| 'resetExpires_DESC'
| 'deletedAt_ASC'
| 'deletedAt_DESC'
| 'lastLogin_ASC'
| 'lastLogin_DESC'
| 'joinedAt_ASC'
| 'joinedAt_DESC'
| 'isSuper_ASC'
| 'isSuper_DESC'
| 'updatedAt_ASC'
| 'updatedAt_DESC'
| 'createdAt_ASC'
| 'createdAt_DESC';
export type MutationType = 'CREATED' | 'UPDATED' | 'DELETED';
export interface UserWhereUniqueInput {
id?: ID_Input;
email?: String;
}
export interface UserCreateInput {
email: String;
password: String;
name: String;
inviteToken?: String;
inviteAccepted?: Boolean;
emailConfirmed?: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper?: Boolean;
}
export interface UserUpdateInput {
email?: String;
password?: String;
name?: String;
inviteToken?: String;
inviteAccepted?: Boolean;
emailConfirmed?: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt?: DateTime;
isSuper?: Boolean;
}
export interface UserSubscriptionWhereInput {
AND?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
OR?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
NOT?: UserSubscriptionWhereInput[] | UserSubscriptionWhereInput;
mutation_in?: MutationType[] | MutationType;
updatedFields_contains?: String;
updatedFields_contains_every?: String[] | String;
updatedFields_contains_some?: String[] | String;
node?: UserWhereInput;
}
export interface UserWhereInput {
AND?: UserWhereInput[] | UserWhereInput;
OR?: UserWhereInput[] | UserWhereInput;
NOT?: UserWhereInput[] | UserWhereInput;
id?: ID_Input;
id_not?: ID_Input;
id_in?: ID_Input[] | ID_Input;
id_not_in?: ID_Input[] | ID_Input;
id_lt?: ID_Input;
id_lte?: ID_Input;
id_gt?: ID_Input;
id_gte?: ID_Input;
id_contains?: ID_Input;
id_not_contains?: ID_Input;
id_starts_with?: ID_Input;
id_not_starts_with?: ID_Input;
id_ends_with?: ID_Input;
id_not_ends_with?: ID_Input;
email?: String;
email_not?: String;
email_in?: String[] | String;
email_not_in?: String[] | String;
email_lt?: String;
email_lte?: String;
email_gt?: String;
email_gte?: String;
email_contains?: String;
email_not_contains?: String;
email_starts_with?: String;
email_not_starts_with?: String;
email_ends_with?: String;
email_not_ends_with?: String;
password?: String;
password_not?: String;
password_in?: String[] | String;
password_not_in?: String[] | String;
password_lt?: String;
password_lte?: String;
password_gt?: String;
password_gte?: String;
password_contains?: String;
password_not_contains?: String;
password_starts_with?: String;
password_not_starts_with?: String;
password_ends_with?: String;
password_not_ends_with?: String;
name?: String;
name_not?: String;
name_in?: String[] | String;
name_not_in?: String[] | String;
name_lt?: String;
name_lte?: String;
name_gt?: String;
name_gte?: String;
name_contains?: String;
name_not_contains?: String;
name_starts_with?: String;
name_not_starts_with?: String;
name_ends_with?: String;
name_not_ends_with?: String;
inviteToken?: String;
inviteToken_not?: String;
inviteToken_in?: String[] | String;
inviteToken_not_in?: String[] | String;
inviteToken_lt?: String;
inviteToken_lte?: String;
inviteToken_gt?: String;
inviteToken_gte?: String;
inviteToken_contains?: String;
inviteToken_not_contains?: String;
inviteToken_starts_with?: String;
inviteToken_not_starts_with?: String;
inviteToken_ends_with?: String;
inviteToken_not_ends_with?: String;
inviteAccepted?: Boolean;
inviteAccepted_not?: Boolean;
emailConfirmed?: Boolean;
emailConfirmed_not?: Boolean;
emailConfirmToken?: String;
emailConfirmToken_not?: String;
emailConfirmToken_in?: String[] | String;
emailConfirmToken_not_in?: String[] | String;
emailConfirmToken_lt?: String;
emailConfirmToken_lte?: String;
emailConfirmToken_gt?: String;
emailConfirmToken_gte?: String;
emailConfirmToken_contains?: String;
emailConfirmToken_not_contains?: String;
emailConfirmToken_starts_with?: String;
emailConfirmToken_not_starts_with?: String;
emailConfirmToken_ends_with?: String;
emailConfirmToken_not_ends_with?: String;
resetToken?: String;
resetToken_not?: String;
resetToken_in?: String[] | String;
resetToken_not_in?: String[] | String;
resetToken_lt?: String;
resetToken_lte?: String;
resetToken_gt?: String;
resetToken_gte?: String;
resetToken_contains?: String;
resetToken_not_contains?: String;
resetToken_starts_with?: String;
resetToken_not_starts_with?: String;
resetToken_ends_with?: String;
resetToken_not_ends_with?: String;
resetExpires?: DateTime;
resetExpires_not?: DateTime;
resetExpires_in?: DateTime[] | DateTime;
resetExpires_not_in?: DateTime[] | DateTime;
resetExpires_lt?: DateTime;
resetExpires_lte?: DateTime;
resetExpires_gt?: DateTime;
resetExpires_gte?: DateTime;
deletedAt?: DateTime;
deletedAt_not?: DateTime;
deletedAt_in?: DateTime[] | DateTime;
deletedAt_not_in?: DateTime[] | DateTime;
deletedAt_lt?: DateTime;
deletedAt_lte?: DateTime;
deletedAt_gt?: DateTime;
deletedAt_gte?: DateTime;
lastLogin?: DateTime;
lastLogin_not?: DateTime;
lastLogin_in?: DateTime[] | DateTime;
lastLogin_not_in?: DateTime[] | DateTime;
lastLogin_lt?: DateTime;
lastLogin_lte?: DateTime;
lastLogin_gt?: DateTime;
lastLogin_gte?: DateTime;
joinedAt?: DateTime;
joinedAt_not?: DateTime;
joinedAt_in?: DateTime[] | DateTime;
joinedAt_not_in?: DateTime[] | DateTime;
joinedAt_lt?: DateTime;
joinedAt_lte?: DateTime;
joinedAt_gt?: DateTime;
joinedAt_gte?: DateTime;
isSuper?: Boolean;
isSuper_not?: Boolean;
}
/*
* An object with an ID
*/
export interface Node {
id: ID_Output;
}
/*
* Information about pagination in a connection.
*/
export interface PageInfo {
hasNextPage: Boolean;
hasPreviousPage: Boolean;
startCursor?: String;
endCursor?: String;
}
export interface UserPreviousValues {
id: ID_Output;
email: String;
password: String;
name: String;
inviteToken?: String;
inviteAccepted: Boolean;
emailConfirmed: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper: Boolean;
}
export interface User extends Node {
id: ID_Output;
email: String;
password: String;
name: String;
inviteToken?: String;
inviteAccepted: Boolean;
emailConfirmed: Boolean;
emailConfirmToken?: String;
resetToken?: String;
resetExpires?: DateTime;
deletedAt?: DateTime;
lastLogin?: DateTime;
joinedAt: DateTime;
isSuper: Boolean;
}
/*
* An edge in a connection.
*/
export interface UserEdge {
node: User;
cursor: String;
}
/*
* A connection to a list of items.
*/
export interface UserConnection {
pageInfo: PageInfo;
edges: UserEdge[];
aggregate: AggregateUser;
}
export interface UserSubscriptionPayload {
mutation: MutationType;
node?: User;
updatedFields?: String[];
previousValues?: UserPreviousValues;
}
export interface AggregateUser {
count: Int;
}
export interface BatchPayload {
count: Long;
}
export type DateTime = Date | string;
/*
The `ID` scalar type represents a unique identifier, often used to refetch an object or as key for a cache. The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. When expected as an input type, any string (such as `"4"`) or integer (such as `4`) input value will be accepted as an ID.
*/
export type ID_Input = string | number;
export type ID_Output = string;
/*
The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
*/
export type Int = number;
/*
The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.
*/
export type String = string;
/*
The `Boolean` scalar type represents `true` or `false`.
*/
export type Boolean = boolean;
/*
The `Long` scalar type represents non-fractional signed whole numeric values.
Long can represent values between -(2^63) and 2^63 - 1.
*/
export type Long = string;
================================================
FILE: packages/graphql-authentication-prisma/src/index.ts
================================================
export { forwardTo } from './utils';
export { GraphqlAuthenticationPrismaAdapter } from './Prisma';
================================================
FILE: packages/graphql-authentication-prisma/src/utils.ts
================================================
import { forwardTo as pForwardTo } from 'prisma-binding';
import { getUserId, Context } from 'graphql-authentication';
/**
* @deprecated Use prisma-binding's forwardTo('db') method instead in combination with graphql-shield to handle permissions.
*/
export function forwardTo({
unauthorized,
bindingName
}: {
unauthorized?: boolean;
bindingName?: string;
}) {
return (parent: any, args: any, ctx: Context, info: any) => {
if (!unauthorized) {
getUserId(ctx);
}
return pForwardTo(bindingName || 'db')(parent, args, ctx, info);
};
}
================================================
FILE: packages/graphql-authentication-prisma/tsconfig.build.json
================================================
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "dist"
},
"include": ["src/index.ts"]
}
================================================
FILE: packages/graphql-authentication-prisma/tsconfig.json
================================================
{
"extends": "../../tsconfig.json"
}
================================================
FILE: tsconfig.base.json
================================================
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"declaration": true,
"lib": ["esnext"],
"strict": true,
// Disabled because this doesn't work correctly with "declaration": true
"noUnusedLocals": false,
"strictFunctionTypes": false,
"noImplicitAny": false,
"forceConsistentCasingInFileNames": true
}
}
================================================
FILE: tsconfig.json
================================================
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./packages",
"paths": {
"graphql-authentication": ["./graphql-authentication/src"]
}
}
}
================================================
FILE: tslint.json
================================================
{
"extends": "@volst/tslint-config"
}
gitextract_m2pa_iuq/ ├── .editorconfig ├── .gitignore ├── .prettierrc ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── examples/ │ ├── with-prisma/ │ │ ├── .graphqlconfig.yml │ │ ├── README.md │ │ ├── datamodel.graphql │ │ ├── docker-compose.yml │ │ ├── emails/ │ │ │ ├── inviteUser/ │ │ │ │ ├── html.pug │ │ │ │ └── subject.pug │ │ │ ├── passwordReset/ │ │ │ │ ├── html.pug │ │ │ │ └── subject.pug │ │ │ └── signupUser/ │ │ │ ├── html.pug │ │ │ └── subject.pug │ │ ├── generated/ │ │ │ ├── prisma.graphql │ │ │ └── prisma.ts │ │ ├── package.json │ │ ├── prisma.yml │ │ ├── schema.graphql │ │ ├── server.ts │ │ └── utils.ts │ ├── with-sequelize/ │ │ ├── README.md │ │ ├── SequelizeAdapter.js │ │ ├── database.js │ │ ├── emails/ │ │ │ ├── inviteUser/ │ │ │ │ ├── html.pug │ │ │ │ └── subject.pug │ │ │ ├── passwordReset/ │ │ │ │ ├── html.pug │ │ │ │ └── subject.pug │ │ │ └── signupUser/ │ │ │ ├── html.pug │ │ │ └── subject.pug │ │ ├── package.json │ │ ├── schema.graphql │ │ └── server.js │ └── with-typeorm/ │ ├── README.md │ ├── TypeOrmAdapter.ts │ ├── database.ts │ ├── emails/ │ │ ├── inviteUser/ │ │ │ ├── html.pug │ │ │ └── subject.pug │ │ ├── passwordReset/ │ │ │ ├── html.pug │ │ │ └── subject.pug │ │ └── signupUser/ │ │ ├── html.pug │ │ └── subject.pug │ ├── entities/ │ │ └── User.ts │ ├── ormconfig.json │ ├── package.json │ ├── schema.graphql │ ├── server.ts │ └── tsconfig.json ├── lerna.json ├── live-demo/ │ ├── InMemoryAdapter.js │ ├── README.md │ ├── email.js │ ├── emails/ │ │ ├── inviteUser/ │ │ │ ├── html.pug │ │ │ └── subject.pug │ │ ├── passwordReset/ │ │ │ ├── html.pug │ │ │ └── subject.pug │ │ └── signupUser/ │ │ ├── html.pug │ │ └── subject.pug │ ├── index.js │ ├── package.json │ └── schema.graphql ├── package.json ├── packages/ │ ├── graphql-authentication/ │ │ ├── README.md │ │ ├── package.json │ │ ├── schema.graphql │ │ ├── src/ │ │ │ ├── Adapter.ts │ │ │ ├── Config.ts │ │ │ ├── __tests__/ │ │ │ │ ├── mutations.ts │ │ │ │ ├── queries.ts │ │ │ │ └── setup.ts │ │ │ ├── binding.ts │ │ │ ├── errors.ts │ │ │ ├── index.ts │ │ │ ├── mutations.ts │ │ │ ├── queries.ts │ │ │ ├── schema.ts │ │ │ └── utils.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ └── graphql-authentication-prisma/ │ ├── README.md │ ├── package.json │ ├── src/ │ │ ├── Prisma.ts │ │ ├── generated/ │ │ │ ├── prisma.graphql │ │ │ └── prisma.ts │ │ ├── index.ts │ │ └── utils.ts │ ├── tsconfig.build.json │ └── tsconfig.json ├── tsconfig.base.json ├── tsconfig.json └── tslint.json
SYMBOL INDEX (184 symbols across 19 files)
FILE: examples/with-prisma/generated/prisma.ts
type Query (line 6) | interface Query {
type Mutation (line 45) | interface Mutation {
type Subscription (line 82) | interface Subscription {
type Exists (line 90) | interface Exists {
type Prisma (line 94) | interface Prisma {
type BindingConstructor (line 123) | interface BindingConstructor<T> {
type UserOrderByInput (line 763) | type UserOrderByInput =
type MutationType (line 797) | type MutationType = 'CREATED' | 'UPDATED' | 'DELETED';
type UserWhereUniqueInput (line 799) | interface UserWhereUniqueInput {
type UserCreateInput (line 804) | interface UserCreateInput {
type UserUpdateInput (line 820) | interface UserUpdateInput {
type UserSubscriptionWhereInput (line 836) | interface UserSubscriptionWhereInput {
type UserWhereInput (line 847) | interface UserWhereInput {
type Node (line 993) | interface Node {
type PageInfo (line 1001) | interface PageInfo {
type UserPreviousValues (line 1008) | interface UserPreviousValues {
type User (line 1025) | interface User extends Node {
type UserEdge (line 1046) | interface UserEdge {
type UserConnection (line 1055) | interface UserConnection {
type UserSubscriptionPayload (line 1061) | interface UserSubscriptionPayload {
type AggregateUser (line 1068) | interface AggregateUser {
type BatchPayload (line 1072) | interface BatchPayload {
type DateTime (line 1076) | type DateTime = Date | string;
type ID_Input (line 1081) | type ID_Input = string | number;
type ID_Output (line 1082) | type ID_Output = string;
type Int (line 1087) | type Int = number;
type String (line 1092) | type String = string;
type Boolean (line 1097) | type Boolean = boolean;
type Long (line 1103) | type Long = string;
FILE: examples/with-prisma/server.ts
method timeline (line 15) | timeline() {
FILE: examples/with-prisma/utils.ts
type Context (line 3) | interface Context {
FILE: examples/with-sequelize/SequelizeAdapter.js
class GraphqlAuthenticationSequelizeAdapter (line 5) | class GraphqlAuthenticationSequelizeAdapter {
method findUserById (line 6) | findUserById(ctx, id, info) {
method findUserByEmail (line 9) | findUserByEmail(ctx, email, info) {
method userExistsByEmail (line 12) | async userExistsByEmail(ctx, email) {
method _createUser (line 18) | _createUser(ctx, data) {
method _updateUser (line 21) | _updateUser(ctx, userId, data) {
method createUserBySignup (line 25) | createUserBySignup(ctx, data) {
method createUserByInvite (line 28) | createUserByInvite(ctx, data) {
method updateUserConfirmToken (line 31) | updateUserConfirmToken(ctx, userId, data) {
method updateUserLastLogin (line 34) | updateUserLastLogin(ctx, userId, data) {
method updateUserPassword (line 37) | updateUserPassword(ctx, userId, data) {
method updateUserResetToken (line 40) | updateUserResetToken(ctx, userId, data) {
method updateUserInfo (line 43) | updateUserInfo(ctx, userId, data) {
method updateUserCompleteInvite (line 46) | updateUserCompleteInvite(ctx, userId, data) {
FILE: examples/with-sequelize/server.js
method timeline (line 14) | timeline() {
FILE: examples/with-typeorm/TypeOrmAdapter.ts
class GraphqlAuthenticationTypeOrmAdapter (line 7) | class GraphqlAuthenticationTypeOrmAdapter
method db (line 9) | private db() {
method findUserById (line 12) | async findUserById(ctx: object, id, info) {
method findUserByEmail (line 15) | async findUserByEmail(ctx: object, email, info) {
method userExistsByEmail (line 18) | async userExistsByEmail(ctx: object, email) {
method _createUser (line 24) | async _createUser(ctx: object, data) {
method _updateUser (line 29) | async _updateUser(ctx: object, userId, data) {
method createUserBySignup (line 33) | createUserBySignup(ctx: object, data) {
method createUserByInvite (line 36) | createUserByInvite(ctx: object, data) {
method updateUserConfirmToken (line 39) | updateUserConfirmToken(ctx: object, userId, data) {
method updateUserLastLogin (line 42) | updateUserLastLogin(ctx: object, userId, data) {
method updateUserPassword (line 45) | updateUserPassword(ctx: object, userId, data) {
method updateUserResetToken (line 48) | updateUserResetToken(ctx: object, userId, data) {
method updateUserInfo (line 51) | updateUserInfo(ctx: object, userId, data) {
method updateUserCompleteInvite (line 54) | updateUserCompleteInvite(ctx: object, userId, data) {
FILE: examples/with-typeorm/entities/User.ts
class User (line 4) | class User {
FILE: examples/with-typeorm/server.ts
method timeline (line 13) | timeline() {
FILE: live-demo/InMemoryAdapter.js
class GraphqlAuthenticationInMemoryAdapter (line 1) | class GraphqlAuthenticationInMemoryAdapter {
method constructor (line 2) | constructor() {
method _generateId (line 6) | _generateId() {
method findUserById (line 14) | findUserById(ctx, id, info) {
method findUserByEmail (line 17) | findUserByEmail(ctx, email, info) {
method userExistsByEmail (line 22) | async userExistsByEmail(ctx, email) {
method _createUser (line 26) | _createUser(ctx, data) {
method _updateUser (line 31) | async _updateUser(ctx, userId, data) {
method createUserBySignup (line 37) | createUserBySignup(ctx, data) {
method createUserByInvite (line 40) | createUserByInvite(ctx, data) {
method updateUserConfirmToken (line 43) | updateUserConfirmToken(ctx, userId, data) {
method updateUserLastLogin (line 46) | updateUserLastLogin(ctx, userId, data) {
method updateUserPassword (line 49) | updateUserPassword(ctx, userId, data) {
method updateUserResetToken (line 52) | updateUserResetToken(ctx, userId, data) {
method updateUserInfo (line 55) | updateUserInfo(ctx, userId, data) {
method updateUserCompleteInvite (line 58) | updateUserCompleteInvite(ctx, userId, data) {
FILE: packages/graphql-authentication-prisma/src/Prisma.ts
class GraphqlAuthenticationPrismaAdapter (line 4) | class GraphqlAuthenticationPrismaAdapter
method constructor (line 8) | constructor(options: { prismaContextName?: string } = {}) {
method db (line 14) | private db(ctx: object) {
method findUserById (line 26) | findUserById(ctx: object, id: ID, info?: any) {
method findUserByEmail (line 29) | findUserByEmail(ctx: object, email: string, info?: any) {
method userExistsByEmail (line 37) | userExistsByEmail(ctx: object, email: string) {
method createUser (line 40) | private createUser(ctx: object, data: any) {
method createUserBySignup (line 45) | createUserBySignup(ctx: object, data: any) {
method createUserByInvite (line 48) | createUserByInvite(ctx: object, data: any) {
method updateUser (line 51) | private updateUser(ctx: object, userId: ID, data: any) {
method updateUserConfirmToken (line 57) | updateUserConfirmToken(ctx: object, userId: ID, data: any) {
method updateUserLastLogin (line 60) | updateUserLastLogin(ctx: object, userId: ID, data: any) {
method updateUserPassword (line 63) | updateUserPassword(ctx: object, userId: ID, data: any) {
method updateUserResetToken (line 66) | updateUserResetToken(ctx: object, userId: ID, data: any) {
method updateUserInfo (line 69) | updateUserInfo(ctx: object, userId: ID, data: any) {
method updateUserCompleteInvite (line 72) | updateUserCompleteInvite(ctx: object, userId: ID, data: any) {
FILE: packages/graphql-authentication-prisma/src/generated/prisma.ts
type Query (line 6) | interface Query {
type Mutation (line 45) | interface Mutation {
type Subscription (line 82) | interface Subscription {
type Exists (line 90) | interface Exists {
type Prisma (line 94) | interface Prisma {
type BindingConstructor (line 123) | interface BindingConstructor<T> {
type UserOrderByInput (line 763) | type UserOrderByInput =
type MutationType (line 797) | type MutationType = 'CREATED' | 'UPDATED' | 'DELETED';
type UserWhereUniqueInput (line 799) | interface UserWhereUniqueInput {
type UserCreateInput (line 804) | interface UserCreateInput {
type UserUpdateInput (line 820) | interface UserUpdateInput {
type UserSubscriptionWhereInput (line 836) | interface UserSubscriptionWhereInput {
type UserWhereInput (line 847) | interface UserWhereInput {
type Node (line 993) | interface Node {
type PageInfo (line 1001) | interface PageInfo {
type UserPreviousValues (line 1008) | interface UserPreviousValues {
type User (line 1025) | interface User extends Node {
type UserEdge (line 1046) | interface UserEdge {
type UserConnection (line 1055) | interface UserConnection {
type UserSubscriptionPayload (line 1061) | interface UserSubscriptionPayload {
type AggregateUser (line 1068) | interface AggregateUser {
type BatchPayload (line 1072) | interface BatchPayload {
type DateTime (line 1076) | type DateTime = Date | string;
type ID_Input (line 1081) | type ID_Input = string | number;
type ID_Output (line 1082) | type ID_Output = string;
type Int (line 1087) | type Int = number;
type String (line 1092) | type String = string;
type Boolean (line 1097) | type Boolean = boolean;
type Long (line 1103) | type Long = string;
FILE: packages/graphql-authentication-prisma/src/utils.ts
function forwardTo (line 7) | function forwardTo({
FILE: packages/graphql-authentication/src/Adapter.ts
type DateTime (line 3) | type DateTime = Date | string;
type ID (line 4) | type ID = string;
type User (line 6) | interface User {
type GraphqlAuthenticationAdapter (line 23) | interface GraphqlAuthenticationAdapter {
FILE: packages/graphql-authentication/src/Config.ts
type IGraphqlAuthenticationConfig (line 6) | interface IGraphqlAuthenticationConfig {
function graphqlAuthenticationConfig (line 20) | function graphqlAuthenticationConfig(
FILE: packages/graphql-authentication/src/__tests__/setup.ts
class FakeAdapter (line 12) | class FakeAdapter implements GraphqlAuthenticationAdapter {
method _generateId (line 28) | _generateId() {
method findUserById (line 32) | findUserById(ctx: object, id: ID, info?: any) {
method findUserByEmail (line 35) | findUserByEmail(ctx: any, email: string) {
method userExistsByEmail (line 40) | userExistsByEmail(ctx: any, email: string) {
method createUserBySignup (line 43) | createUserBySignup(ctx: any, data: any) {
method createUserByInvite (line 48) | createUserByInvite(ctx: any, data: any) {
method updateUserLastLogin (line 53) | async updateUserLastLogin(ctx: any, userId: string, data: any) {
method updateUserInfo (line 58) | async updateUserInfo(ctx: any, userId: string, data: any) {
method updateUserPassword (line 63) | async updateUserPassword(ctx: any, userId: string, data: any) {
method updateUserResetToken (line 68) | async updateUserResetToken(ctx: any, userId: string, data: any) {
method updateUserCompleteInvite (line 73) | async updateUserCompleteInvite(ctx: any, userId: string, data: any) {
method updateUserConfirmToken (line 78) | async updateUserConfirmToken(ctx: any, userId: string, data: any) {
constant AUTH_KEY (line 86) | const AUTH_KEY =
function startServer (line 90) | async function startServer(options: any = {}) {
FILE: packages/graphql-authentication/src/binding.ts
type Query (line 6) | interface Query {
type Mutation (line 14) | interface Mutation {
type Subscription (line 62) | interface Subscription {}
type Binding (line 64) | interface Binding {
type BindingConstructor (line 92) | interface BindingConstructor<T> {
type SignupByInviteInput (line 104) | interface SignupByInviteInput {
type SignupInput (line 111) | interface SignupInput {
type InviteUserInput (line 117) | interface InviteUserInput {
type UserUpdateInput (line 121) | interface UserUpdateInput {
type AuthPayload (line 126) | interface AuthPayload {
type TriggerPasswordResetPayload (line 131) | interface TriggerPasswordResetPayload {
type User (line 135) | interface User {
type UserIdPayload (line 147) | interface UserIdPayload {
type String (line 154) | type String = string;
type Boolean (line 159) | type Boolean = boolean;
type DateTime (line 161) | type DateTime = Date | string;
type ID_Input (line 166) | type ID_Input = string | number;
type ID_Output (line 167) | type ID_Output = string;
FILE: packages/graphql-authentication/src/mutations.ts
function generateToken (line 28) | function generateToken(user: User, ctx: Context) {
function validatePassword (line 32) | function validatePassword(ctx: Context, value: string) {
function getHashedPassword (line 38) | function getHashedPassword(value: string) {
method signupByInvite (line 43) | async signupByInvite(
method signup (line 85) | async signup(parent: any, { data }: { data: SignupInput }, ctx: Context) {
method confirmEmail (line 134) | async confirmEmail(
method login (line 168) | async login(
method changePassword (line 212) | async changePassword(
method inviteUser (line 238) | async inviteUser(
method triggerPasswordReset (line 310) | async triggerPasswordReset(
method passwordReset (line 359) | async passwordReset(
method updateCurrentUser (line 398) | async updateCurrentUser(
FILE: packages/graphql-authentication/src/queries.ts
method currentUser (line 6) | currentUser(parent: any, args: any, ctx: Context, info: any) {
FILE: packages/graphql-authentication/src/utils.ts
type Context (line 5) | interface Context {
function _getUserId (line 11) | function _getUserId(ctx: Context): string {
function getUserId (line 24) | function getUserId(ctx: Context): string {
function getUser (line 32) | function getUser(ctx: Context): Promise<any> {
class AuthError (line 36) | class AuthError extends Error {
method constructor (line 37) | constructor() {
function isAuthResolver (line 42) | function isAuthResolver(parent: any, args: any, ctx: Context) {
Condensed preview — 94 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (185K chars).
[
{
"path": ".editorconfig",
"chars": 207,
"preview": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_"
},
{
"path": ".gitignore",
"chars": 38,
"preview": "node_modules\ndist\n*.log\ncoverage\n.env\n"
},
{
"path": ".prettierrc",
"chars": 26,
"preview": "{\n \"singleQuote\": true\n}\n"
},
{
"path": ".travis.yml",
"chars": 166,
"preview": "sudo: false\n\nlanguage:\n node_js\n\nnode_js:\n - '8'\n\ncache:\n yarn: true\n directories:\n - node_modules\n\nscript:\n cd "
},
{
"path": "CONTRIBUTING.md",
"chars": 1098,
"preview": "Pull requests and issues are very welcome!\n\n# Prerequisites\n\n- Node v8+\n\n# Getting started\n\nTo get started, clone this r"
},
{
"path": "LICENSE",
"chars": 737,
"preview": "ISC License\n\nCopyright (c) 2018, Volst\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose"
},
{
"path": "README.md",
"chars": 10401,
"preview": "# GraphQL Authentication\n\n**Disclaimer: This repository is not actively maintained!**\n\n_Previously called Prisma Auth_\n\n"
},
{
"path": "examples/with-prisma/.graphqlconfig.yml",
"chars": 241,
"preview": "projects:\n prisma:\n schemaPath: \"./generated/prisma.graphql\"\n extensions:\n prisma: prisma.yml\n codegen:"
},
{
"path": "examples/with-prisma/README.md",
"chars": 635,
"preview": "# Prisma example\n\nThis is an example of how to use GraphQL Authentication with [Prisma](https://www.prisma.io/). It uses"
},
{
"path": "examples/with-prisma/datamodel.graphql",
"chars": 402,
"preview": "type User {\n id: ID! @unique\n email: String! @unique\n password: String!\n name: String!\n inviteToken: String\n invit"
},
{
"path": "examples/with-prisma/docker-compose.yml",
"chars": 512,
"preview": "version: '3'\nservices:\n prisma:\n image: prismagraphql/prisma:1.9\n restart: \"no\"\n ports:\n - \"4466:4466\"\n "
},
{
"path": "examples/with-prisma/emails/inviteUser/html.pug",
"chars": 129,
"preview": "p Hi,\np You are invited to join *your project*!\np\n a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept"
},
{
"path": "examples/with-prisma/emails/inviteUser/subject.pug",
"chars": 32,
"preview": "= `Invited for *your project*!`\n"
},
{
"path": "examples/with-prisma/emails/passwordReset/html.pug",
"chars": 154,
"preview": "p Hi,\np You requested a password reset on *your project*.\np\n a(href=mailAppUrl + '/login/reset-password/' + email + '/'"
},
{
"path": "examples/with-prisma/emails/passwordReset/subject.pug",
"chars": 41,
"preview": "= `Confirm your email on *your project*`\n"
},
{
"path": "examples/with-prisma/emails/signupUser/html.pug",
"chars": 195,
"preview": "p Hi,\np You have just created an account on *your project*! As a last step, please confirm your email:\np\n a(href=mailAp"
},
{
"path": "examples/with-prisma/emails/signupUser/subject.pug",
"chars": 41,
"preview": "= `Confirm your email on *your project*`\n"
},
{
"path": "examples/with-prisma/generated/prisma.graphql",
"chars": 16508,
"preview": "# source: http://localhost:4466\n# timestamp: Mon Jul 16 2018 12:37:56 GMT+0200 (CEST)\n\ntype AggregateUser {\n count: Int"
},
{
"path": "examples/with-prisma/generated/prisma.ts",
"chars": 27831,
"preview": "import { GraphQLResolveInfo, GraphQLSchema } from 'graphql';\nimport { IResolvers } from 'graphql-tools/dist/Interfaces';"
},
{
"path": "examples/with-prisma/package.json",
"chars": 536,
"preview": "{\n \"name\": \"graphql-authentication-with-prisma-example\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"license\": \"ISC\",\n "
},
{
"path": "examples/with-prisma/prisma.yml",
"chars": 106,
"preview": "endpoint: http://localhost:4466\ndatamodel: datamodel.graphql\n\nhooks:\n post-deploy:\n - graphql codegen\n"
},
{
"path": "examples/with-prisma/schema.graphql",
"chars": 155,
"preview": "# import Query.*, Mutation.* from \"node_modules/graphql-authentication/schema.graphql\"\n\ntype Query {\n timeline: [Post!]"
},
{
"path": "examples/with-prisma/server.ts",
"chars": 1140,
"preview": "import { GraphQLServer } from 'graphql-yoga';\nimport * as path from 'path';\nimport * as Email from 'email-templates';\nim"
},
{
"path": "examples/with-prisma/utils.ts",
"chars": 105,
"preview": "import { Prisma } from './generated/prisma';\n\nexport interface Context {\n db: Prisma;\n request: any;\n}\n"
},
{
"path": "examples/with-sequelize/README.md",
"chars": 548,
"preview": "# Sequelize example\n\nThis is an example of how to use GraphQL Authentication with [Sequelize](http://docs.sequelizejs.co"
},
{
"path": "examples/with-sequelize/SequelizeAdapter.js",
"chars": 1517,
"preview": "const { User } = require('./database');\n\n// There currently is no package for a sequelize adapter, so we create one ours"
},
{
"path": "examples/with-sequelize/database.js",
"chars": 596,
"preview": "const Sequelize = require('sequelize');\nconst sequelize = new Sequelize({ dialect: 'sqlite' });\n\nconst User = sequelize."
},
{
"path": "examples/with-sequelize/emails/inviteUser/html.pug",
"chars": 129,
"preview": "p Hi,\np You are invited to join *your project*!\np\n a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept"
},
{
"path": "examples/with-sequelize/emails/inviteUser/subject.pug",
"chars": 32,
"preview": "= `Invited for *your project*!`\n"
},
{
"path": "examples/with-sequelize/emails/passwordReset/html.pug",
"chars": 154,
"preview": "p Hi,\np You requested a password reset on *your project*.\np\n a(href=mailAppUrl + '/login/reset-password/' + email + '/'"
},
{
"path": "examples/with-sequelize/emails/passwordReset/subject.pug",
"chars": 41,
"preview": "= `Confirm your email on *your project*`\n"
},
{
"path": "examples/with-sequelize/emails/signupUser/html.pug",
"chars": 195,
"preview": "p Hi,\np You have just created an account on *your project*! As a last step, please confirm your email:\np\n a(href=mailAp"
},
{
"path": "examples/with-sequelize/emails/signupUser/subject.pug",
"chars": 41,
"preview": "= `Confirm your email on *your project*`\n"
},
{
"path": "examples/with-sequelize/package.json",
"chars": 355,
"preview": "{\n \"name\": \"graphql-authentication-with-sequelize-example\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"license\": \"ISC\""
},
{
"path": "examples/with-sequelize/schema.graphql",
"chars": 155,
"preview": "# import Query.*, Mutation.* from \"node_modules/graphql-authentication/schema.graphql\"\n\ntype Query {\n timeline: [Post!]"
},
{
"path": "examples/with-sequelize/server.js",
"chars": 1017,
"preview": "const { GraphQLServer } = require('graphql-yoga');\nconst path = require('path');\nconst Email = require('email-templates'"
},
{
"path": "examples/with-typeorm/README.md",
"chars": 528,
"preview": "# TypeORM example\n\nThis is an example of how to use GraphQL Authentication with [TypeORM](http://typeorm.io/). There is "
},
{
"path": "examples/with-typeorm/TypeOrmAdapter.ts",
"chars": 1931,
"preview": "import { getRepository } from 'typeorm';\nimport { User } from './database';\nimport { GraphqlAuthenticationAdapter } from"
},
{
"path": "examples/with-typeorm/database.ts",
"chars": 133,
"preview": "import 'reflect-metadata';\nimport { createConnection } from 'typeorm';\n\nexport { User } from './entities/User';\n\ncreateC"
},
{
"path": "examples/with-typeorm/emails/inviteUser/html.pug",
"chars": 129,
"preview": "p Hi,\np You are invited to join *your project*!\np\n a(href=mailAppUrl + '/register/' + email + '/' + inviteToken) Accept"
},
{
"path": "examples/with-typeorm/emails/inviteUser/subject.pug",
"chars": 32,
"preview": "= `Invited for *your project*!`\n"
},
{
"path": "examples/with-typeorm/emails/passwordReset/html.pug",
"chars": 154,
"preview": "p Hi,\np You requested a password reset on *your project*.\np\n a(href=mailAppUrl + '/login/reset-password/' + email + '/'"
},
{
"path": "examples/with-typeorm/emails/passwordReset/subject.pug",
"chars": 41,
"preview": "= `Confirm your email on *your project*`\n"
},
{
"path": "examples/with-typeorm/emails/signupUser/html.pug",
"chars": 195,
"preview": "p Hi,\np You have just created an account on *your project*! As a last step, please confirm your email:\np\n a(href=mailAp"
},
{
"path": "examples/with-typeorm/emails/signupUser/subject.pug",
"chars": 41,
"preview": "= `Confirm your email on *your project*`\n"
},
{
"path": "examples/with-typeorm/entities/User.ts",
"chars": 753,
"preview": "import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';\n\n@Entity()\nexport class User {\n @PrimaryGeneratedColu"
},
{
"path": "examples/with-typeorm/ormconfig.json",
"chars": 127,
"preview": "{\n \"type\": \"sqlite\",\n \"database\": \":memory:\",\n \"synchronize\": true,\n \"logging\": true,\n \"entities\": [\"entities/**/*."
},
{
"path": "examples/with-typeorm/package.json",
"chars": 468,
"preview": "{\n \"name\": \"graphql-authentication-with-typeorm-example\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"license\": \"ISC\",\n"
},
{
"path": "examples/with-typeorm/schema.graphql",
"chars": 155,
"preview": "# import Query.*, Mutation.* from \"node_modules/graphql-authentication/schema.graphql\"\n\ntype Query {\n timeline: [Post!]"
},
{
"path": "examples/with-typeorm/server.ts",
"chars": 909,
"preview": "import { GraphQLServer } from 'graphql-yoga';\nimport * as Email from 'email-templates';\nimport {\n authQueries,\n authMu"
},
{
"path": "examples/with-typeorm/tsconfig.json",
"chars": 302,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2017\",\n \"module\": \"commonjs\",\n \"experimentalDecorators\": true,\n \"emit"
},
{
"path": "lerna.json",
"chars": 138,
"preview": "{\n \"lerna\": \"2.11.0\",\n \"packages\": [\n \"packages/*\"\n ],\n \"version\": \"independent\",\n \"npmClient\": \"yarn\",\n \"useWo"
},
{
"path": "live-demo/InMemoryAdapter.js",
"chars": 1782,
"preview": "class GraphqlAuthenticationInMemoryAdapter {\n constructor() {\n this.users = [];\n }\n // If you'd use a database you"
},
{
"path": "live-demo/README.md",
"chars": 413,
"preview": "# Live Demo\n\nThe code in this repository is used to host a live demo on x.now.sh (TODO).\n\nThe live demo uses an in-memor"
},
{
"path": "live-demo/email.js",
"chars": 585,
"preview": "const { createTransport } = require('nodemailer');\nconst mailgun = require('nodemailer-mailgun-transport');\nconst Email "
},
{
"path": "live-demo/emails/inviteUser/html.pug",
"chars": 574,
"preview": "p Hi,\np You are invited to join GraphQL Authentication Demo! Accept the invite by writing this mutation:\npre\n | mutatio"
},
{
"path": "live-demo/emails/inviteUser/subject.pug",
"chars": 45,
"preview": "= `Invited for GraphQL Authentication Demo!`\n"
},
{
"path": "live-demo/emails/passwordReset/html.pug",
"chars": 484,
"preview": "p Hi,\np You requested a password reset on GraphQL Authentication Demo. Reset your password by writing this mutation:\npre"
},
{
"path": "live-demo/emails/passwordReset/subject.pug",
"chars": 54,
"preview": "= `Confirm your email on GraphQL Authentication Demo`\n"
},
{
"path": "live-demo/emails/signupUser/html.pug",
"chars": 499,
"preview": "p Hi,\np You have just created an account on GraphQL Authentication Demo! As a last step, please confirm your email by wr"
},
{
"path": "live-demo/emails/signupUser/subject.pug",
"chars": 54,
"preview": "= `Confirm your email on GraphQL Authentication Demo`\n"
},
{
"path": "live-demo/index.js",
"chars": 811,
"preview": "const { GraphQLServer } = require('graphql-yoga');\nconst {\n authQueries,\n authMutations,\n graphqlAuthenticationConfig"
},
{
"path": "live-demo/package.json",
"chars": 463,
"preview": "{\n \"name\": \"graphql-authentication-live-demo\",\n \"private\": true,\n \"version\": \"1.0.0\",\n \"license\": \"ISC\",\n \"dependen"
},
{
"path": "live-demo/schema.graphql",
"chars": 99,
"preview": "# import Query.*, Mutation.* from \"node_modules/graphql-authentication/schema.graphql\"\n\ntype Query\n"
},
{
"path": "package.json",
"chars": 287,
"preview": "{\n \"private\": true,\n \"workspaces\": [\n \"packages/*\"\n ],\n \"devDependencies\": {\n \"husky\": \"^0.14.3\",\n \"lerna\":"
},
{
"path": "packages/graphql-authentication/README.md",
"chars": 577,
"preview": "# GraphQL Authentication\n\nA very opinionated user authentication package for [GraphQL](https://graphql.org/). It uses ol"
},
{
"path": "packages/graphql-authentication/package.json",
"chars": 2131,
"preview": "{\n \"name\": \"graphql-authentication\",\n \"version\": \"0.5.5\",\n \"description\": \"Makes it super easy to do do boring authen"
},
{
"path": "packages/graphql-authentication/schema.graphql",
"chars": 1277,
"preview": "scalar DateTime\n\ntype Query {\n currentUser: User\n}\n\ntype Mutation {\n signupByInvite(data: SignupByInviteInput!): AuthP"
},
{
"path": "packages/graphql-authentication/src/Adapter.ts",
"chars": 1409,
"preview": "import { Context } from './utils';\n\nexport type DateTime = Date | string;\nexport type ID = string;\n\nexport interface Use"
},
{
"path": "packages/graphql-authentication/src/Config.ts",
"chars": 898,
"preview": "import * as Email from 'email-templates';\nimport { User } from './Adapter';\nimport { Context } from './utils';\nimport { "
},
{
"path": "packages/graphql-authentication/src/__tests__/mutations.ts",
"chars": 8167,
"preview": "import { client, clientWithAuth, startServer, FakeAdapter } from './setup';\n\ntest('signup - a new user', async () => {\n "
},
{
"path": "packages/graphql-authentication/src/__tests__/queries.ts",
"chars": 612,
"preview": "import { client, startServer, clientWithAuth } from './setup';\n\ntest('currentUser - throw error when login fails', async"
},
{
"path": "packages/graphql-authentication/src/__tests__/setup.ts",
"chars": 3963,
"preview": "import { GraphQLServer } from 'graphql-yoga';\nimport { GraphQLClient } from 'graphql-request';\nimport {\n graphqlAuthent"
},
{
"path": "packages/graphql-authentication/src/binding.ts",
"chars": 4248,
"preview": "import { makeBindingClass, Options } from 'graphql-binding';\nimport { GraphQLResolveInfo, GraphQLSchema } from 'graphql'"
},
{
"path": "packages/graphql-authentication/src/errors.ts",
"chars": 1530,
"preview": "import { createError } from 'apollo-errors';\n\nexport const MissingDataError = createError('MissingDataError', {\n messag"
},
{
"path": "packages/graphql-authentication/src/index.ts",
"chars": 315,
"preview": "export { mutations as authMutations } from './mutations';\nexport { queries as authQueries } from './queries';\nexport { g"
},
{
"path": "packages/graphql-authentication/src/mutations.ts",
"chars": 9991,
"preview": "import * as bcrypt from 'bcryptjs';\nimport * as jwt from 'jsonwebtoken';\nimport * as validator from 'validator';\nimport "
},
{
"path": "packages/graphql-authentication/src/queries.ts",
"chars": 401,
"preview": "import { getUserId, Context } from './utils';\n// Without this manual User interface import, TypeScript will create an in"
},
{
"path": "packages/graphql-authentication/src/schema.ts",
"chars": 284,
"preview": "import * as path from 'path';\nimport { makeExecutableSchema } from 'graphql-tools';\nimport { importSchema } from 'graphq"
},
{
"path": "packages/graphql-authentication/src/utils.ts",
"chars": 1167,
"preview": "import * as jwt from 'jsonwebtoken';\nimport { IGraphqlAuthenticationConfig } from './Config';\nimport { ID } from './Adap"
},
{
"path": "packages/graphql-authentication/tsconfig.build.json",
"chars": 146,
"preview": "{\n \"extends\": \"../../tsconfig.base.json\",\n \"compilerOptions\": {\n \"rootDir\": \"src\",\n \"outDir\": \"dist\"\n },\n \"inc"
},
{
"path": "packages/graphql-authentication/tsconfig.json",
"chars": 39,
"preview": "{\n \"extends\": \"../../tsconfig.json\"\n}\n"
},
{
"path": "packages/graphql-authentication-prisma/README.md",
"chars": 1413,
"preview": "# GraphQL Authentication Prisma\n\nA Prisma adapter for [Graphql Authentication](https://github.com/Volst/graphql-authenti"
},
{
"path": "packages/graphql-authentication-prisma/package.json",
"chars": 1967,
"preview": "{\n \"name\": \"graphql-authentication-prisma\",\n \"version\": \"0.1.5\",\n \"description\": \"Prisma adapter for graphql-authenti"
},
{
"path": "packages/graphql-authentication-prisma/src/Prisma.ts",
"chars": 2216,
"preview": "import { Prisma, User } from './generated/prisma';\nimport { GraphqlAuthenticationAdapter, ID } from 'graphql-authenticat"
},
{
"path": "packages/graphql-authentication-prisma/src/generated/prisma.graphql",
"chars": 16508,
"preview": "# source: http://localhost:4466\n# timestamp: Sun Jun 17 2018 19:34:23 GMT+0200 (CEST)\n\ntype AggregateUser {\n count: Int"
},
{
"path": "packages/graphql-authentication-prisma/src/generated/prisma.ts",
"chars": 27830,
"preview": "import { GraphQLResolveInfo, GraphQLSchema } from 'graphql';\nimport { IResolvers } from 'graphql-tools/dist/Interfaces';"
},
{
"path": "packages/graphql-authentication-prisma/src/index.ts",
"chars": 100,
"preview": "export { forwardTo } from './utils';\nexport { GraphqlAuthenticationPrismaAdapter } from './Prisma';\n"
},
{
"path": "packages/graphql-authentication-prisma/src/utils.ts",
"chars": 564,
"preview": "import { forwardTo as pForwardTo } from 'prisma-binding';\nimport { getUserId, Context } from 'graphql-authentication';\n\n"
},
{
"path": "packages/graphql-authentication-prisma/tsconfig.build.json",
"chars": 146,
"preview": "{\n \"extends\": \"../../tsconfig.base.json\",\n \"compilerOptions\": {\n \"rootDir\": \"src\",\n \"outDir\": \"dist\"\n },\n \"inc"
},
{
"path": "packages/graphql-authentication-prisma/tsconfig.json",
"chars": 39,
"preview": "{\n \"extends\": \"../../tsconfig.json\"\n}\n"
},
{
"path": "tsconfig.base.json",
"chars": 362,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2017\",\n \"module\": \"commonjs\",\n \"declaration\": true,\n \"lib\": [\"esnext\""
},
{
"path": "tsconfig.json",
"chars": 183,
"preview": "{\n \"extends\": \"./tsconfig.base.json\",\n \"compilerOptions\": {\n \"baseUrl\": \"./packages\",\n \"paths\": {\n \"graphql"
},
{
"path": "tslint.json",
"chars": 40,
"preview": "{\n \"extends\": \"@volst/tslint-config\"\n}\n"
}
]
About this extraction
This page contains the full source code of the Volst/graphql-authentication GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 94 files (163.0 KB), approximately 45.5k tokens, and a symbol index with 184 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.