diff --git a/.gitignore b/.gitignore index 7f4f91f..41d99c0 100644 --- a/.gitignore +++ b/.gitignore @@ -142,3 +142,5 @@ fabric.properties /src/staticfiles/ node_modules /bend/static/ +/fend/src/server/data/schema.json +screenshots diff --git a/bend/deps/testing.txt b/bend/deps/testing.txt index 253d8b3..10f9ea7 100644 --- a/bend/deps/testing.txt +++ b/bend/deps/testing.txt @@ -1,2 +1,3 @@ prospector==0.12.4 -coverage==4.2 \ No newline at end of file +coverage==4.2 +selenium==3.0.2 diff --git a/bend/src/ango/settings/base.py b/bend/src/ango/settings/base.py index 07cabbb..0711957 100644 --- a/bend/src/ango/settings/base.py +++ b/bend/src/ango/settings/base.py @@ -3,13 +3,16 @@ """ from os.path import dirname, join +import datetime # Build paths inside the project like this: join(BASE_DIR, "directory") BASE_DIR = dirname(dirname(dirname(dirname(__file__)))) # Define STATIC_ROOT for the collectstatic command STATIC_ROOT = join(BASE_DIR, 'static') - +STATIC_URL = '/static/' +MEDIA_ROOT = join(BASE_DIR, 'media') +MEDIA_URL = "/media/" # Application definition INSTALLED_APPS = [ @@ -87,19 +90,17 @@ USE_TZ = True -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.10/howto/static-files/ - -STATIC_URL = '/static/' GRAPHENE = { 'SCHEMA': 'ango.schema.schema', # Where your Graphene schema lives - 'SCHEMA_OUTPUT': 'fend/server/data/schema.json' # defaults to schema.json + 'SCHEMA_OUTPUT': 'fend/src/server/data/schema.json' # defaults to schema.json } WEBPACK_LOADER = { 'DEFAULT': { 'BUNDLE_DIR_NAME': 'bundles/', - 'STATS_FILE': join('static', 'webpack-stats.json'), + 'STATS_FILE': join(BASE_DIR, 'static', 'webpack-stats.json'), } -} \ No newline at end of file +} + +JWT_EXPIRATION_DELTA = datetime.timedelta(days=7) diff --git a/bend/src/ango/settings/prod.py b/bend/src/ango/settings/prod.py index d44acfc..0edf69f 100644 --- a/bend/src/ango/settings/prod.py +++ b/bend/src/ango/settings/prod.py @@ -26,10 +26,6 @@ } -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/1.9/howto/static-files/ -STATIC_ROOT = join(BASE_DIR, 'staticfiles') -STATIC_URL = '/static/' # Simplified static file serving. # https://warehouse.python.org/project/whitenoise/ diff --git a/bend/src/ango/tests.py b/bend/src/ango/tests.py new file mode 100644 index 0000000..e278919 --- /dev/null +++ b/bend/src/ango/tests.py @@ -0,0 +1,25 @@ +from django.test import LiveServerTestCase +from selenium import webdriver +import os + + +if not os.path.exists('./screenshots'): + os.makedirs('./screenshots') + + +class HomePageTest(LiveServerTestCase): + def setUp(self): + self.selenium = webdriver.Firefox() + super(HomePageTest, self).setUp() + + def tearDown(self): + self.selenium.quit() + super(HomePageTest, self).tearDown() + + def test_home_page(self): + selenium = self.selenium + selenium.implicitly_wait(10) # seconds + # Opening the link we want to test + selenium.get(self.live_server_url) + selenium.save_screenshot('./screenshots/ff_landing.png') + assert 'Relay Fullstack' in selenium.page_source diff --git a/bend/src/ango/urls.py b/bend/src/ango/urls.py index ab15735..861907b 100644 --- a/bend/src/ango/urls.py +++ b/bend/src/ango/urls.py @@ -17,11 +17,12 @@ from django.contrib import admin from django.views.generic import TemplateView from graphene_django.views import GraphQLView +from django.views.decorators.csrf import csrf_exempt urlpatterns = [ url(r'^$', TemplateView.as_view(template_name='index.html'), name='home'), url(r'^admin/', admin.site.urls), - url(r'^graphql', GraphQLView.as_view(graphiql=True)), - url(r'^.*/$', TemplateView.as_view(template_name='index.html')), + url(r'^graphql', csrf_exempt(GraphQLView.as_view(graphiql=True))), + url(r'^.*$', TemplateView.as_view(template_name='index.html')), ] diff --git a/bend/src/users/jwt_util.py b/bend/src/users/jwt_util.py index 5d55ef4..baa5e3f 100644 --- a/bend/src/users/jwt_util.py +++ b/bend/src/users/jwt_util.py @@ -1,4 +1,16 @@ from jwt_auth.forms import JSONWebTokenForm +from jwt_auth.mixins import JSONWebTokenAuthMixin + +jwtMixin = JSONWebTokenAuthMixin.authenticate_header + +import jwt + +from jwt_auth import settings, exceptions +from jwt_auth.utils import get_authorization_header +from jwt_auth.compat import json, smart_text, User + +jwt_decode_handler = settings.JWT_DECODE_HANDLER +jwt_get_user_id_from_payload = settings.JWT_PAYLOAD_GET_USER_ID_HANDLER def loginUser(username, password): @@ -8,8 +20,53 @@ def loginUser(username, password): if not form.is_valid(): return print("JWT form not valid") - context_dict = { - 'token': form.object['token'] - } + return form.object['token'] + + +def authenticate(request): + auth = get_authorization_header(request).split() + auth_header_prefix = settings.JWT_AUTH_HEADER_PREFIX.lower() + if not auth or smart_text(auth[0].lower()) != auth_header_prefix: + raise exceptions.AuthenticationFailed() + + if len(auth) == 1: + msg = 'Invalid Authorization header. No credentials provided.' + raise exceptions.AuthenticationFailed(msg) + elif len(auth) > 2: + msg = ('Invalid Authorization header. Credentials string ' + 'should not contain spaces.') + raise exceptions.AuthenticationFailed(msg) + + + try: + payload = jwt_decode_handler(auth[1]) + except jwt.ExpiredSignature: + msg = 'Signature has expired.' + print(msg, auth[1]) + raise exceptions.AuthenticationFailed(msg) + except jwt.DecodeError: + msg = 'Error decoding signature.' + raise exceptions.AuthenticationFailed(msg) + + user = authenticate_credentials(payload) + + return (user, auth[1]) + + +def authenticate_credentials(payload): + """ + Returns an active user that matches the payload's user id and email. + """ + try: + user_id = jwt_get_user_id_from_payload(payload) + + if user_id: + user = User.objects.get(pk=user_id, is_active=True) + else: + msg = 'Invalid payload' + raise exceptions.AuthenticationFailed(msg) + except User.DoesNotExist: + msg = 'Invalid signature' + raise exceptions.AuthenticationFailed(msg) - return context_dict + return user diff --git a/bend/src/users/readme.md b/bend/src/users/readme.md index 064871d..7a41743 100644 --- a/bend/src/users/readme.md +++ b/bend/src/users/readme.md @@ -74,16 +74,67 @@ query { ``` mutation { - loginUser(input: { - username: "ncrmro", - password: "testpassword" - }) { - user { - username, - email, + loginUser(input: {username: "ncrmro", password: "testpassword"}) { + viewer { + username + email + todomodel(first: 2) { + edges { + node { + text + } + } + } + } + jwtToken + } +} + +query { + login(username:"ncrmro", password: "testpassword") { + viewer{ + username, + dateJoined }, - token + jwtToken } } + +query {viewer(jwtToken: ""){ + viewer { + username, + isAuthenticated, + isAnonymous + } +}} + + ``` +``` +{"input_0": {"username": "ncrmro", "password": "testpassword"}} + +mutation LoginUserMutation($input_0:LogInUserInput!) { + loginUser(input:$input_0) { + clientMutationId, + ...F0 + } +} +fragment F0 on LogInUserPayload { + viewer { + username, + id + } +} + +{ + "data": { + "loginUser": { + "clientMutationId": null, + "viewer": { + "id": "VXNlck5vZGU6MQ==" + } + } + } +} +``` \ No newline at end of file diff --git a/bend/src/users/schema.py b/bend/src/users/schema.py index 105706f..9d485a0 100644 --- a/bend/src/users/schema.py +++ b/bend/src/users/schema.py @@ -1,43 +1,51 @@ -from graphene import AbstractType, Node, Field, String, relay, ObjectType, Int, Boolean, ID +from graphene import AbstractType, Node, Field, String, relay, ObjectType, Int, Boolean, ID, InputObjectType from django.contrib.auth.models import AnonymousUser, User from graphene import AbstractType, Node, relay from graphene_django.filter import DjangoFilterConnectionField from graphene_django.types import DjangoObjectType -from .jwt_util import loginUser +from .jwt_util import loginUser, authenticate +from jwt_auth import settings, exceptions +import jwt + +jwt_decode_handler = settings.JWT_DECODE_HANDLER class UserNode(DjangoObjectType): class Meta: model = User + only_fields = ( + 'id', + 'last_login', + 'is_superuser', + 'username', + 'first_name', + 'last_name', + 'email', + 'is_staff', + 'is_active', + 'date_joined', + 'todomodel' + ) interfaces = (Node,) -class CurrentUser(ObjectType): - id = ID() - username = String() - password = String() - is_anonymous = Boolean() - is_authenticated = Boolean() - is_staff = Boolean() - is_active = Boolean() - - class UserQueries(AbstractType): - user = Node.Field(UserNode) + user = Field(UserNode) all_users = DjangoFilterConnectionField(UserNode) + viewer = Field(UserNode) - current_user = Field(CurrentUser) - - def resolve_current_user(self, args, context, info): - anon = AnonymousUser - return CurrentUser( - id=anon.id, - username=anon.username, - is_anonymous=anon.is_anonymous, - is_authenticated=anon.is_authenticated, - is_staff=anon.is_staff, - is_active=anon.is_active, - ) + def resolve_viewer(self, args, context, info): + try: + check_token = authenticate(context) + print('Found Token in Auth Header', check_token) + token_user = check_token[0] + user = User.objects.get(id=token_user.id, username=token_user.username) + return user + except: + return User( + id=0, + username="" + ) class LogInUser(relay.ClientIDMutation): @@ -45,16 +53,37 @@ class Input: username = String(required=True) password = String(required=True) - user = Field(UserNode) - token = String() + viewer = Field(UserNode) + jwt_token = String() + + @classmethod + def mutate_and_get_payload(cls, input, context, info): + print("Logging user in", input, context, info) + username = input.get('username') + password = input.get('password') + jwt_token = loginUser(username, password) + viewer = User.objects.get(username=username) + return LogInUser(viewer, jwt_token) + + +class CreateUser(relay.ClientIDMutation): + class Input: + username = String(required=True) + password = String(required=True) + + viewer = Field(UserNode) + jwt_token = String() @classmethod def mutate_and_get_payload(cls, input, context, info): + print("Logging user in", input, context, info) username = input.get('username') password = input.get('password') - token = loginUser(username, password) - return LogInUser(token=token) + viewer = User.objects.create_user(username=username, password=password) + jwt_token = loginUser(username, password) + return CreateUser(viewer, jwt_token) class UserMutations(AbstractType): login_user = LogInUser.Field() + create_user = CreateUser.Field() diff --git a/circle.yml b/circle.yml index b0e6a38..a123ba2 100644 --- a/circle.yml +++ b/circle.yml @@ -9,8 +9,11 @@ machine: general: artifacts: - ".coverage" + - "screenshots" dependencies: pre: + - wget -qO- https://github.com/mozilla/geckodriver/releases/download/v0.13.0/geckodriver-v0.13.0-linux64.tar.gz | tar -xvz -C /home/ubuntu/bin + - chmod +x /home/ubuntu/bin/geckodriver - | if [[ ! -e ~/.yarn/bin/yarn || $(yarn --version) != "${YARN_VERSION}" ]]; then echo "Download and install Yarn." @@ -26,6 +29,8 @@ dependencies: - ~/.cache/yarn post: - pip install -r ./bend/deps/testing.txt + - ./bend/manage.py collectstatic --no-input + test: override: diff --git a/fend/src/client/components/App/AppComponent.js b/fend/src/client/components/App/AppComponent.js index 1be0e7f..f7c96f7 100644 --- a/fend/src/client/components/App/AppComponent.js +++ b/fend/src/client/components/App/AppComponent.js @@ -8,14 +8,20 @@ import "react-mdl/extra/css/material.cyan-red.min.css"; export default class App extends React.Component { static propTypes = { + router: React.PropTypes.object.isRequired, children: React.PropTypes.object.isRequired, viewer: React.PropTypes.object.isRequired }; + render() { + const viewer = this.props.viewer; + const userLoggedIn = viewer.username ? true : false; + return (
- + +

Sawasdee, Sawasdee!

Always a pleasure scaffolding your apps

diff --git a/fend/src/client/components/App/AppContainer.js b/fend/src/client/components/App/AppContainer.js index 6d44699..75a2f8f 100644 --- a/fend/src/client/components/App/AppContainer.js +++ b/fend/src/client/components/App/AppContainer.js @@ -5,7 +5,11 @@ import Footer from "../Footer/FooterContainer"; export default Relay.createContainer(App, { fragments: { viewer: () => Relay.QL` - fragment on User { + fragment on UserNode { + id, + username, + email, + dateJoined, ${Footer.getFragment('viewer')} }` } diff --git a/fend/src/client/components/Dashboard/DashboardComponent.js b/fend/src/client/components/Dashboard/DashboardComponent.js index a859132..e1f1ec7 100644 --- a/fend/src/client/components/Dashboard/DashboardComponent.js +++ b/fend/src/client/components/Dashboard/DashboardComponent.js @@ -2,7 +2,7 @@ import React from "react"; -export default class Feature extends React.Component { +export default class Dashboard extends React.Component { static propTypes = { viewer: React.PropTypes.object.isRequired }; @@ -10,6 +10,9 @@ export default class Feature extends React.Component { render() { return (
+ {this.props.viewer.username} +
+ {this.props.viewer.email}

This is the dashboard

); diff --git a/fend/src/client/components/Dashboard/DashboardContainer.js b/fend/src/client/components/Dashboard/DashboardContainer.js new file mode 100644 index 0000000..f6fc624 --- /dev/null +++ b/fend/src/client/components/Dashboard/DashboardContainer.js @@ -0,0 +1,12 @@ +import Relay from "react-relay"; +import Dashboard from "./DashboardComponent"; + +export default Relay.createContainer(Dashboard, { + fragments: { + viewer: () => Relay.QL` + fragment on UserNode { + username, + email + }` + } +}); diff --git a/fend/src/client/components/Footer/FooterComponent.js b/fend/src/client/components/Footer/FooterComponent.js index 7de13af..5597330 100644 --- a/fend/src/client/components/Footer/FooterComponent.js +++ b/fend/src/client/components/Footer/FooterComponent.js @@ -3,9 +3,7 @@ import {Footer as MDLFooter, FooterSection} from "react-mdl"; import styles from "./Footer.scss"; export default class Footer extends React.Component { - static propTypes = { - viewer: React.PropTypes.object.isRequired, - }; + render() { return ( diff --git a/fend/src/client/components/Footer/FooterContainer.js b/fend/src/client/components/Footer/FooterContainer.js index b905f1a..56cf3ef 100644 --- a/fend/src/client/components/Footer/FooterContainer.js +++ b/fend/src/client/components/Footer/FooterContainer.js @@ -4,7 +4,7 @@ import Footer from "./FooterComponent"; export default Relay.createContainer(Footer, { fragments: { viewer: () => Relay.QL` - fragment on User { + fragment on UserNode { username }` } diff --git a/fend/src/client/components/Landing/LandingComponent.js b/fend/src/client/components/Landing/LandingComponent.js new file mode 100644 index 0000000..0f0b0d2 --- /dev/null +++ b/fend/src/client/components/Landing/LandingComponent.js @@ -0,0 +1,17 @@ +/* eslint-disable global-require */ +import React from "react"; + + +export default class Landing extends React.Component { + static propTypes = { + viewer: React.PropTypes.object.isRequired + }; + + render() { + return ( +
+

This is the landing page

+
+ ); + } +} diff --git a/fend/src/client/components/Landing/LandingContainer.js b/fend/src/client/components/Landing/LandingContainer.js new file mode 100644 index 0000000..fbfedb6 --- /dev/null +++ b/fend/src/client/components/Landing/LandingContainer.js @@ -0,0 +1,12 @@ +import Relay from "react-relay"; +import Landing from "./LandingComponent"; + +export default Relay.createContainer(Landing, { + fragments: { + viewer: () => Relay.QL` + fragment on UserNode { + username, + email + }` + } +}); diff --git a/fend/src/client/components/Login/LoginComponent.js b/fend/src/client/components/Login/LoginComponent.js index 39e5990..ef48c70 100644 --- a/fend/src/client/components/Login/LoginComponent.js +++ b/fend/src/client/components/Login/LoginComponent.js @@ -1,20 +1,62 @@ /* eslint-disable jsx-a11y/href-no-hash */ import React from "react"; +import Relay from "react-relay"; import {Grid, Cell, Textfield, Button, Checkbox} from "react-mdl"; import Page from "../Page/PageComponent"; +import LoginUserMutation from "./LoginUserMutation"; export default class Login extends React.Component { + static propTypes = { + viewer: React.PropTypes.object.isRequired, + router: React.PropTypes.object.isRequired + }; + + constructor(props) { + super(props); + this.state = { + username: '', + password: '' + }; + } + + + loginUser = (form) => { + form.preventDefault(); + const username = this.state.username; + const password = this.state.password; + const viewer = this.props.viewer; + const loginUserMutation = new LoginUserMutation({ + viewer, + username, + password + }); + var onFailure = (transaction) => { + console.log("failure", transaction) + }; + + var onSuccess = (response) => { + console.log("Success", response); + const jwtToken = response.loginUser.jwtToken; + localStorage.setItem('jwtToken', jwtToken); + this.props.router.push('/dashboard'); + window.location.reload() + }; + + Relay.Store.commitUpdate(loginUserMutation, {onSuccess, onFailure} + ); + }; + render() { return (
-
+ - {}} label='Username'/> + - {}} label='Password' type='password'/> + @@ -29,4 +71,12 @@ export default class Login extends React.Component { ); } + + handleUsernameChange(e) { + this.setState({username: e.target.value}); + } + + handlePasswordChange(e) { + this.setState({password: e.target.value}); + } } diff --git a/fend/src/client/components/Login/LoginContainer.js b/fend/src/client/components/Login/LoginContainer.js new file mode 100644 index 0000000..ce3a43e --- /dev/null +++ b/fend/src/client/components/Login/LoginContainer.js @@ -0,0 +1,14 @@ +import Relay from "react-relay"; +import Landing from "./LoginComponent"; + +export default Relay.createContainer(Landing, { + fragments: { + viewer: () => Relay.QL` + fragment on UserNode { + id + username + email + dateJoined + }` + } +}); diff --git a/fend/src/client/components/Login/LoginUserMutation.js b/fend/src/client/components/Login/LoginUserMutation.js new file mode 100644 index 0000000..7b3a86a --- /dev/null +++ b/fend/src/client/components/Login/LoginUserMutation.js @@ -0,0 +1,54 @@ +import Relay from "react-relay"; + +class LoginMutation extends Relay.Mutation { + // This method should return a GraphQL operation that represents + // the mutation to be performed. This presumes that the server + // implements a mutation type named ‘loginUser’. + getMutation() { + return Relay.QL` + mutation { loginUser } + `; + } + + getVariables() { + return { + username: this.props.username, + password: this.props.password + }; + } + + getFatQuery() { + return Relay.QL` + fragment on LogInUserPayload { + viewer{ + id, + username, + email, + dateJoined, + }, + jwtToken + } + `; + } + + getConfigs() { + return [{ + type: 'REQUIRED_CHILDREN', + // Forces these fragments to be included in the query + children: [Relay.QL` + fragment on LogInUserPayload { + viewer { + id, + username, + email, + dateJoined, + }, + jwtToken + } + `], + }]; + } + +} + +export default LoginMutation; diff --git a/fend/src/client/components/Navbar/NavbarComponent.js b/fend/src/client/components/Navbar/NavbarComponent.js index d9c98d9..c400950 100644 --- a/fend/src/client/components/Navbar/NavbarComponent.js +++ b/fend/src/client/components/Navbar/NavbarComponent.js @@ -4,24 +4,52 @@ import {Layout, Header, Navigation, Drawer} from "react-mdl"; import styles from "./Navbar.scss"; export default class Navbar extends React.Component { + static propTypes = { + userLoggedIn: React.PropTypes.bool.isRequired, + router: React.PropTypes.object.isRequired + + }; + render() { const title = 'Relay Fullstack'; return (
{title}} scroll> - - Sign up - Login - + {this.props.userLoggedIn ? this.renderLoggedIn() : this.renderLoggedOut()}
{title}} className='mdl-layout--small-screen-only'> - - Sign up - Login - + {this.props.userLoggedIn ? this.renderLoggedIn() : this.renderLoggedOut()} +
); } + + handleSignOut() { + localStorage.removeItem('jwtToken'); + // Causes crash + this.props.router.push('/'); + window.location.reload() + + } + + renderLoggedIn() { + return ( + + Sign out + Dashboard + + + ); + } + + renderLoggedOut() { + return ( + + Sign up + Login + + ); + } } diff --git a/fend/src/client/components/Signup/SignupComponent.js b/fend/src/client/components/Signup/SignupComponent.js index d8732a0..79e8eea 100644 --- a/fend/src/client/components/Signup/SignupComponent.js +++ b/fend/src/client/components/Signup/SignupComponent.js @@ -1,19 +1,53 @@ import React from "react"; +import Relay from "react-relay"; import {Grid, Cell, Textfield, Button} from "react-mdl"; import Page from "../Page/PageComponent"; +import SignupUserMutation from "./SignupUserMutation"; + export default class Signup extends React.Component { + constructor(props) { + super(props); + this.state = { + username: '', + password: '' + }; + } + + + signupUser = (form) => { + form.preventDefault(); + const username = this.state.username; + const password = this.state.password; + const signupUserMutation = new SignupUserMutation({ + username, + password + }); + var onFailure = (transaction) => { + console.log("failure", transaction) + }; + + var onSuccess = (response) => { + console.log("Success", response); + const jwtToken = response.createUser.jwtToken; + localStorage.setItem('jwtToken', jwtToken); + this.props.router.push('/dashboard'); + window.location.reload() + }; + Relay.Store.commitUpdate(signupUserMutation, {onSuccess, onFailure}); + }; + render() { return (
- + - {}} label='Username'/> + - {}} label='Password' type='password'/> + @@ -24,4 +58,12 @@ export default class Signup extends React.Component { ); } + + handleUsernameChange(e) { + this.setState({username: e.target.value}); + } + + handlePasswordChange(e) { + this.setState({password: e.target.value}); + } } diff --git a/fend/src/client/components/Signup/SignupUserMutation.js b/fend/src/client/components/Signup/SignupUserMutation.js new file mode 100644 index 0000000..572202c --- /dev/null +++ b/fend/src/client/components/Signup/SignupUserMutation.js @@ -0,0 +1,45 @@ +import Relay from "react-relay"; + +class SignupUserMutation extends Relay.Mutation { + + getMutation() { + return Relay.QL` + mutation { createUser } + `; + } + + getVariables() { + return { + username: this.props.username, + password: this.props.password + }; + } + + getFatQuery() { + return Relay.QL` + fragment on CreateUserPayload { + viewer { username, firstName, email } + } + `; + } + + getConfigs() { + return [{ + type: 'REQUIRED_CHILDREN', + // Forces these fragments to be included in the query + children: [Relay.QL` + fragment on CreateUserPayload { + viewer { + id, + username, + email, + dateJoined, + }, + jwtToken + } + `], + }]; + } +} + +export default SignupUserMutation; diff --git a/fend/src/client/index.js b/fend/src/client/index.js index 2c56ad4..748d5af 100644 --- a/fend/src/client/index.js +++ b/fend/src/client/index.js @@ -6,10 +6,21 @@ import useRelay from "react-router-relay"; import Routes from "./routes/index"; import "../../../node_modules/react-mdl/extra/material"; +let jwtToken = localStorage.getItem("jwtToken"); + +Relay.injectNetworkLayer( + new Relay.DefaultNetworkLayer('/graphql', { + headers: { + Authorization: 'Bearer ' + jwtToken + } + }) +); + const rootNode = document.createElement('div'); document.body.appendChild(rootNode); ReactDOM.render( - , + , rootNode ); diff --git a/fend/src/client/routes/Route.js b/fend/src/client/routes/Route.js deleted file mode 100644 index c5162b8..0000000 --- a/fend/src/client/routes/Route.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from "react"; -import {IndexRoute, Route, Redirect} from "react-router"; -import AppContainer from "../components/App/AppContainer"; -import Dashboard from "../components/Dashboard/DashboardComponent"; -import SignupComponent from "../components/Signup/SignupComponent"; -import LoginComponent from "../components/Login/LoginComponent"; -//import ViewerQuery from "./ViewerQuery"; -//import FeatureContainer from "../components/Feature/FeatureContainer"; - -export default ( - - - - - - -); - diff --git a/fend/src/client/routes/accounts/login.js b/fend/src/client/routes/accounts/login.js deleted file mode 100644 index e69de29..0000000 diff --git a/fend/src/client/routes/accounts/signup.js b/fend/src/client/routes/accounts/signup.js deleted file mode 100644 index e69de29..0000000 diff --git a/fend/src/client/routes/dashboard.js b/fend/src/client/routes/dashboard.js new file mode 100644 index 0000000..047caf6 --- /dev/null +++ b/fend/src/client/routes/dashboard.js @@ -0,0 +1,11 @@ +import ViewerQuery from './ViewerQuery'; + +export default { + path: 'dashboard', + queries: ViewerQuery, + getComponent(nextState, cb) { + require.ensure([], (require) => { + cb(null, require('../components/Dashboard/DashboardContainer').default); + }); + } +}; diff --git a/fend/src/client/routes/index.js b/fend/src/client/routes/index.js index db93da5..d4b6d63 100644 --- a/fend/src/client/routes/index.js +++ b/fend/src/client/routes/index.js @@ -1,13 +1,28 @@ import AppContainer from "../components/App/AppContainer"; -import Dashboard from "../components/Dashboard/DashboardComponent"; +import Landing from "../components/Landing/LandingContainer"; +import ViewerQuery from './ViewerQuery'; -export default { - component: AppContainer, - path: '/', - indexRoute: { - component: Dashboard - }, - childRoutes: [ - require('./landing') - ] -}; + +export default () => { + return { + childRoutes: [{ + path: '/', + component: AppContainer, + queries: ViewerQuery, + indexRoute: { + queries: ViewerQuery, + component: Landing, + }, + childRoutes: [ + require('./signup').default, + require('./login').default, + require('./dashboard').default, + + { + path: '*', + component: Landing + } + ] + }] + } +} diff --git a/fend/src/client/routes/landing.js b/fend/src/client/routes/landing.js index d73b20a..b2408f0 100644 --- a/fend/src/client/routes/landing.js +++ b/fend/src/client/routes/landing.js @@ -1,8 +1,9 @@ -import Dashboard from "../components/Dashboard/DashboardComponent"; +module.exports = { + path: 'landing', -export default { - path: '/', - indexRoute: { - component: Dashboard + getComponent(nextState, cb) { + require.ensure([], (require) => { + cb(null, require('../components/Landing/LandingContainer')); + }); } }; diff --git a/fend/src/client/routes/login.js b/fend/src/client/routes/login.js new file mode 100644 index 0000000..834cf4c --- /dev/null +++ b/fend/src/client/routes/login.js @@ -0,0 +1,12 @@ +import ViewerQuery from './ViewerQuery'; + + +export default { + path: 'login', + queries: ViewerQuery, + getComponent(nextState, cb) { + require.ensure([], (require) => { + cb(null, require('../components/Login/LoginContainer').default); + }); + } +}; diff --git a/fend/src/client/routes/signup.js b/fend/src/client/routes/signup.js new file mode 100644 index 0000000..c1e8704 --- /dev/null +++ b/fend/src/client/routes/signup.js @@ -0,0 +1,8 @@ +export default { + path: 'signup', + getComponent(nextState, cb) { + require.ensure([], (require) => { + cb(null, require('../components/Signup/SignupComponent').default); + }); + } +}; diff --git a/fend/src/client/utils/jwt_token.js b/fend/src/client/utils/jwt_token.js new file mode 100644 index 0000000..c842f55 --- /dev/null +++ b/fend/src/client/utils/jwt_token.js @@ -0,0 +1,42 @@ +let jwtToken = localStorage.getItem("jwtToken"); + +function parseJwt(token) { + var base64Url = token.split('.')[1]; + var base64 = base64Url.replace('-', '+').replace('_', '/'); + return JSON.parse(window.atob(base64)); +} +function getExpirationDate(parsedToken) { + var date = new Date(0); + date.setUTCSeconds(parsedToken.exp); + return date + +} +function dateTime() { + var today = new Date(); + var date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate(); + var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds(); + var dateTime = date + ' ' + time; + return dateTime +} + +export default function jwtTokenParam() { + if (jwtToken) { + const parsedToken = parseJwt(jwtToken); + console.log("Found JWT Token", parsedToken); + + console.log("Current Date Time", dateTime()); + console.log("Token Expiration Time", getExpirationDate(parsedToken)); + + + return jwtToken + + } + else { + console.log("jwtToken not set"); + + jwtToken = ""; + return jwtToken + + + } +} diff --git a/fend/src/server/data/schema.json b/fend/src/server/data/schema.json index d205309..5a9365d 100644 --- a/fend/src/server/data/schema.json +++ b/fend/src/server/data/schema.json @@ -1,1529 +1 @@ -{ - "data": { - "__schema": { - "queryType": { - "name": "Query" - }, - "mutationType": { - "name": "Mutation" - }, - "subscriptionType": null, - "types": [ - { - "kind": "OBJECT", - "name": "Query", - "description": null, - "fields": [ - { - "name": "node", - "description": "Fetches an object given its ID", - "args": [ - { - "name": "id", - "description": "The ID of an object", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "viewer", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "ID", - "description": "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.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INTERFACE", - "name": "Node", - "description": "An object with an ID", - "fields": [ - { - "name": "id", - "description": "The id of the object.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": [ - { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - { - "kind": "OBJECT", - "name": "Feature", - "ofType": null - } - ] - }, - { - "kind": "OBJECT", - "name": "User", - "description": "A person who uses our app", - "fields": [ - { - "name": "id", - "description": "The ID of an object", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "features", - "description": "Features that I have", - "args": [ - { - "name": "after", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "first", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "before", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "last", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "FeatureConnection", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "username", - "description": "Users's username", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "website", - "description": "User's website", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "String", - "description": "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.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Int", - "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1. ", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FeatureConnection", - "description": "A connection to a list of items.", - "fields": [ - { - "name": "pageInfo", - "description": "Information to aid in pagination.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "PageInfo", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "edges", - "description": "A list of edges.", - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "FeatureEdge", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "PageInfo", - "description": "Information about pagination in a connection.", - "fields": [ - { - "name": "hasNextPage", - "description": "When paginating forwards, are there more items?", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "hasPreviousPage", - "description": "When paginating backwards, are there more items?", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "startCursor", - "description": "When paginating backwards, the cursor to continue.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "endCursor", - "description": "When paginating forwards, the cursor to continue.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "SCALAR", - "name": "Boolean", - "description": "The `Boolean` scalar type represents `true` or `false`.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "FeatureEdge", - "description": "An edge in a connection.", - "fields": [ - { - "name": "node", - "description": "The item at the end of the edge", - "args": [], - "type": { - "kind": "OBJECT", - "name": "Feature", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "cursor", - "description": "A cursor for use in pagination", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Feature", - "description": "Feature integrated in our starter kit", - "fields": [ - { - "name": "id", - "description": "The ID of an object", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": "Name of the feature", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": "Description of the feature", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "url", - "description": "Url of the feature", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [ - { - "kind": "INTERFACE", - "name": "Node", - "ofType": null - } - ], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "Mutation", - "description": null, - "fields": [ - { - "name": "addFeature", - "description": null, - "args": [ - { - "name": "input", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "AddFeatureInput", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "AddFeaturePayload", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "INPUT_OBJECT", - "name": "AddFeatureInput", - "description": null, - "fields": null, - "inputFields": [ - { - "name": "name", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "description", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "url", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "clientMutationId", - "description": null, - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - } - ], - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "AddFeaturePayload", - "description": null, - "fields": [ - { - "name": "featureEdge", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "FeatureEdge", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "viewer", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "User", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "clientMutationId", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Schema", - "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation, and subscription operations.", - "fields": [ - { - "name": "types", - "description": "A list of all types supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queryType", - "description": "The type that query operations will be rooted at.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "mutationType", - "description": "If this server supports mutation, the type that mutation operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "subscriptionType", - "description": "If this server support subscription, the type that subscription operations will be rooted at.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "directives", - "description": "A list of all directives supported by this server.", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Directive", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Type", - "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", - "fields": [ - { - "name": "kind", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__TypeKind", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "fields", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Field", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "interfaces", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "possibleTypes", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "enumValues", - "description": null, - "args": [ - { - "name": "includeDeprecated", - "description": null, - "type": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - }, - "defaultValue": "false" - } - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__EnumValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "inputFields", - "description": null, - "args": [], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ofType", - "description": null, - "args": [], - "type": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__TypeKind", - "description": "An enum describing what kind of type a given `__Type` is.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "SCALAR", - "description": "Indicates this type is a scalar.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Indicates this type is a union. `possibleTypes` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Indicates this type is an enum. `enumValues` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Indicates this type is an input object. `inputFields` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "LIST", - "description": "Indicates this type is a list. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "NON_NULL", - "description": "Indicates this type is a non-null. `ofType` is a valid field.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Field", - "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__InputValue", - "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "type", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__Type", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "defaultValue", - "description": "A GraphQL-formatted string representing the default value for this input value.", - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__EnumValue", - "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "isDeprecated", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "deprecationReason", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "OBJECT", - "name": "__Directive", - "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", - "fields": [ - { - "name": "name", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "description", - "description": null, - "args": [], - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "locations", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "__DirectiveLocation", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "args", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "__InputValue", - "ofType": null - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "onOperation", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onFragment", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - }, - { - "name": "onField", - "description": null, - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "isDeprecated": true, - "deprecationReason": "Use `locations`." - } - ], - "inputFields": null, - "interfaces": [], - "enumValues": null, - "possibleTypes": null - }, - { - "kind": "ENUM", - "name": "__DirectiveLocation", - "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": [ - { - "name": "QUERY", - "description": "Location adjacent to a query operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "MUTATION", - "description": "Location adjacent to a mutation operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SUBSCRIPTION", - "description": "Location adjacent to a subscription operation.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD", - "description": "Location adjacent to a field.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_DEFINITION", - "description": "Location adjacent to a fragment definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FRAGMENT_SPREAD", - "description": "Location adjacent to a fragment spread.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INLINE_FRAGMENT", - "description": "Location adjacent to an inline fragment.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCHEMA", - "description": "Location adjacent to a schema definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "SCALAR", - "description": "Location adjacent to a scalar definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "OBJECT", - "description": "Location adjacent to an object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "FIELD_DEFINITION", - "description": "Location adjacent to a field definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ARGUMENT_DEFINITION", - "description": "Location adjacent to an argument definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INTERFACE", - "description": "Location adjacent to an interface definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "UNION", - "description": "Location adjacent to a union definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM", - "description": "Location adjacent to an enum definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "ENUM_VALUE", - "description": "Location adjacent to an enum value definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_OBJECT", - "description": "Location adjacent to an input object type definition.", - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "INPUT_FIELD_DEFINITION", - "description": "Location adjacent to an input object field definition.", - "isDeprecated": false, - "deprecationReason": null - } - ], - "possibleTypes": null - } - ], - "directives": [ - { - "name": "include", - "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], - "args": [ - { - "name": "if", - "description": "Included when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "skip", - "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", - "locations": [ - "FIELD", - "FRAGMENT_SPREAD", - "INLINE_FRAGMENT" - ], - "args": [ - { - "name": "if", - "description": "Skipped when true.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Boolean", - "ofType": null - } - }, - "defaultValue": null - } - ] - }, - { - "name": "deprecated", - "description": "Marks an element of a GraphQL schema as no longer supported.", - "locations": [ - "FIELD_DEFINITION", - "ENUM_VALUE" - ], - "args": [ - { - "name": "reason", - "description": "Explains why this element was deprecated, usually also including a suggestion for how to access supported similar data. Formatted in [Markdown](https://daringfireball.net/projects/markdown/).", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": "\"No longer supported\"" - } - ] - } - ] - } - } -} \ No newline at end of file +{"data": {"__schema": {"queryType": {"name": "Query"}, "mutationType": {"name": "Mutation"}, "subscriptionType": null, "types": [{"kind": "OBJECT", "name": "Query", "description": null, "fields": [{"name": "user", "description": null, "args": [], "type": {"kind": "OBJECT", "name": "UserNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "allUsers", "description": null, "args": [{"name": "before", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}, {"name": "after", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}, {"name": "first", "description": null, "type": {"kind": "SCALAR", "name": "Int", "ofType": null}, "defaultValue": null}, {"name": "last", "description": null, "type": {"kind": "SCALAR", "name": "Int", "ofType": null}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "UserNodeConnection", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "viewer", "description": null, "args": [{"name": "jwtToken", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "UserNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "todo", "description": "The ID of the object", "args": [{"name": "id", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "ID", "ofType": null}}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "TodoNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "allTodos", "description": null, "args": [{"name": "before", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}, {"name": "after", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}, {"name": "first", "description": null, "type": {"kind": "SCALAR", "name": "Int", "ofType": null}, "defaultValue": null}, {"name": "last", "description": null, "type": {"kind": "SCALAR", "name": "Int", "ofType": null}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "TodoNodeConnection", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "__debug", "description": null, "args": [], "type": {"kind": "OBJECT", "name": "DjangoDebug", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "UserNode", "description": null, "fields": [{"name": "id", "description": "The ID of the object.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "ID", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "lastLogin", "description": "", "args": [], "type": {"kind": "SCALAR", "name": "DateTime", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "isSuperuser", "description": "Designates that this user has all permissions without explicitly assigning them.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "username", "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "firstName", "description": "", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "lastName", "description": "", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "email", "description": "", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "isStaff", "description": "Designates whether the user can log into this admin site.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "isActive", "description": "Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "dateJoined", "description": "", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "DateTime", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "todomodel", "description": null, "args": [{"name": "before", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}, {"name": "after", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}, {"name": "first", "description": null, "type": {"kind": "SCALAR", "name": "Int", "ofType": null}, "defaultValue": null}, {"name": "last", "description": null, "type": {"kind": "SCALAR", "name": "Int", "ofType": null}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "TodoNodeConnection", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [{"kind": "INTERFACE", "name": "Node", "ofType": null}], "enumValues": null, "possibleTypes": null}, {"kind": "INTERFACE", "name": "Node", "description": "An object with an ID", "fields": [{"name": "id", "description": "The ID of the object.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "ID", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": [{"kind": "OBJECT", "name": "UserNode", "ofType": null}, {"kind": "OBJECT", "name": "TodoNode", "ofType": null}]}, {"kind": "SCALAR", "name": "ID", "description": "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.", "fields": null, "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "SCALAR", "name": "DateTime", "description": "\n The `DateTime` scalar type represents a DateTime\n value as specified by\n [iso8601](https://en.wikipedia.org/wiki/ISO_8601).\n ", "fields": null, "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "SCALAR", "name": "Boolean", "description": "The `Boolean` scalar type represents `true` or `false`.", "fields": null, "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "SCALAR", "name": "String", "description": "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.", "fields": null, "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "TodoNodeConnection", "description": null, "fields": [{"name": "pageInfo", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "PageInfo", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "edges", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "OBJECT", "name": "TodoNodeEdge", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "PageInfo", "description": null, "fields": [{"name": "hasNextPage", "description": "When paginating forwards, are there more items?", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "hasPreviousPage", "description": "When paginating backwards, are there more items?", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "startCursor", "description": "When paginating backwards, the cursor to continue.", "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "endCursor", "description": "When paginating forwards, the cursor to continue.", "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "TodoNodeEdge", "description": null, "fields": [{"name": "node", "description": "The item at the end of the edge", "args": [], "type": {"kind": "OBJECT", "name": "TodoNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "cursor", "description": "A cursor for use in pagination", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "TodoNode", "description": null, "fields": [{"name": "id", "description": "The ID of the object.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "ID", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "user", "description": "", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "UserNode", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "text", "description": "", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [{"kind": "INTERFACE", "name": "Node", "ofType": null}], "enumValues": null, "possibleTypes": null}, {"kind": "SCALAR", "name": "Int", "description": "The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^53 - 1) and 2^53 - 1 since represented in JSON as double-precision floating point numbers specifiedby [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point).", "fields": null, "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "UserNodeConnection", "description": null, "fields": [{"name": "pageInfo", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "PageInfo", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "edges", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "OBJECT", "name": "UserNodeEdge", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "UserNodeEdge", "description": null, "fields": [{"name": "node", "description": "The item at the end of the edge", "args": [], "type": {"kind": "OBJECT", "name": "UserNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "cursor", "description": "A cursor for use in pagination", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "DjangoDebug", "description": null, "fields": [{"name": "sql", "description": null, "args": [], "type": {"kind": "LIST", "name": null, "ofType": {"kind": "OBJECT", "name": "DjangoDebugSQL", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "DjangoDebugSQL", "description": null, "fields": [{"name": "vendor", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "alias", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "sql", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "duration", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "Float", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "rawSql", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "params", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "startTime", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "Float", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "stopTime", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "Float", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "isSlow", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "Boolean", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "isSelect", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "Boolean", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "transId", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "transStatus", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "isoLevel", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "encoding", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "SCALAR", "name": "Float", "description": "The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](http://en.wikipedia.org/wiki/IEEE_floating_point). ", "fields": null, "inputFields": null, "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "Mutation", "description": null, "fields": [{"name": "loginUser", "description": null, "args": [{"name": "input", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "INPUT_OBJECT", "name": "LogInUserInput", "ofType": null}}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "LogInUserPayload", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "createTodo", "description": null, "args": [{"name": "input", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "INPUT_OBJECT", "name": "CreateTodoInput", "ofType": null}}, "defaultValue": null}], "type": {"kind": "OBJECT", "name": "CreateTodoPayload", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "LogInUserPayload", "description": null, "fields": [{"name": "viewer", "description": null, "args": [], "type": {"kind": "OBJECT", "name": "UserNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "jwtToken", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "clientMutationId", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "INPUT_OBJECT", "name": "LogInUserInput", "description": null, "fields": null, "inputFields": [{"name": "username", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "defaultValue": null}, {"name": "password", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "defaultValue": null}, {"name": "jwtToken", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "defaultValue": null}, {"name": "clientMutationId", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}], "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "CreateTodoPayload", "description": null, "fields": [{"name": "todo", "description": null, "args": [], "type": {"kind": "OBJECT", "name": "TodoNode", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "clientMutationId", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "INPUT_OBJECT", "name": "CreateTodoInput", "description": null, "fields": null, "inputFields": [{"name": "userId", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Int", "ofType": null}}, "defaultValue": null}, {"name": "text", "description": null, "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "defaultValue": null}, {"name": "clientMutationId", "description": null, "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "defaultValue": null}], "interfaces": null, "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "__Schema", "description": "A GraphQL Schema defines the capabilities of a GraphQL server. It exposes all available types and directives on the server, as well as the entry points for query, mutation and subscription operations.", "fields": [{"name": "types", "description": "A list of all types supported by this server.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Type", "ofType": null}}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "queryType", "description": "The type that query operations will be rooted at.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Type", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "mutationType", "description": "If this server supports mutation, the type that mutation operations will be rooted at.", "args": [], "type": {"kind": "OBJECT", "name": "__Type", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "subscriptionType", "description": "If this server support subscription, the type that subscription operations will be rooted at.", "args": [], "type": {"kind": "OBJECT", "name": "__Type", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "directives", "description": "A list of all directives supported by this server.", "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Directive", "ofType": null}}}}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "__Type", "description": "The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.\n\nDepending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.", "fields": [{"name": "kind", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "ENUM", "name": "__TypeKind", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "name", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "description", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "fields", "description": null, "args": [{"name": "includeDeprecated", "description": null, "type": {"kind": "SCALAR", "name": "Boolean", "ofType": null}, "defaultValue": "false"}], "type": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Field", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "interfaces", "description": null, "args": [], "type": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Type", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "possibleTypes", "description": null, "args": [], "type": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Type", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "enumValues", "description": null, "args": [{"name": "includeDeprecated", "description": null, "type": {"kind": "SCALAR", "name": "Boolean", "ofType": null}, "defaultValue": "false"}], "type": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__EnumValue", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "inputFields", "description": null, "args": [], "type": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__InputValue", "ofType": null}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "ofType", "description": null, "args": [], "type": {"kind": "OBJECT", "name": "__Type", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "ENUM", "name": "__TypeKind", "description": "An enum describing what kind of type a given `__Type` is", "fields": null, "inputFields": null, "interfaces": null, "enumValues": [{"name": "SCALAR", "description": "Indicates this type is a scalar.", "isDeprecated": false, "deprecationReason": null}, {"name": "OBJECT", "description": "Indicates this type is an object. `fields` and `interfaces` are valid fields.", "isDeprecated": false, "deprecationReason": null}, {"name": "INTERFACE", "description": "Indicates this type is an interface. `fields` and `possibleTypes` are valid fields.", "isDeprecated": false, "deprecationReason": null}, {"name": "UNION", "description": "Indicates this type is a union. `possibleTypes` is a valid field.", "isDeprecated": false, "deprecationReason": null}, {"name": "ENUM", "description": "Indicates this type is an enum. `enumValues` is a valid field.", "isDeprecated": false, "deprecationReason": null}, {"name": "INPUT_OBJECT", "description": "Indicates this type is an input object. `inputFields` is a valid field.", "isDeprecated": false, "deprecationReason": null}, {"name": "LIST", "description": "Indicates this type is a list. `ofType` is a valid field.", "isDeprecated": false, "deprecationReason": null}, {"name": "NON_NULL", "description": "Indicates this type is a non-null. `ofType` is a valid field.", "isDeprecated": false, "deprecationReason": null}], "possibleTypes": null}, {"kind": "OBJECT", "name": "__Field", "description": "Object and Interface types are described by a list of Fields, each of which has a name, potentially a list of arguments, and a return type.", "fields": [{"name": "name", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "description", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "args", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__InputValue", "ofType": null}}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "type", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Type", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "isDeprecated", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "deprecationReason", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "__InputValue", "description": "Arguments provided to Fields or Directives and the input fields of an InputObject are represented as Input Values which describe their type and optionally a default value.", "fields": [{"name": "name", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "description", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "type", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__Type", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "defaultValue", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "__EnumValue", "description": "One possible value for a given Enum. Enum values are unique values, not a placeholder for a string or numeric value. However an Enum value is returned in a JSON response as a string.", "fields": [{"name": "name", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "description", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "isDeprecated", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "deprecationReason", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "OBJECT", "name": "__Directive", "description": "A Directive provides a way to describe alternate runtime execution and type validation behavior in a GraphQL document.\n\nIn some cases, you need to provide options to alter GraphQL's execution behavior in ways field arguments will not suffice, such as conditionally including or skipping a field. Directives provide this by describing additional information to the executor.", "fields": [{"name": "name", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "String", "ofType": null}}, "isDeprecated": false, "deprecationReason": null}, {"name": "description", "description": null, "args": [], "type": {"kind": "SCALAR", "name": "String", "ofType": null}, "isDeprecated": false, "deprecationReason": null}, {"name": "locations", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "ENUM", "name": "__DirectiveLocation", "ofType": null}}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "args", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "LIST", "name": null, "ofType": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "OBJECT", "name": "__InputValue", "ofType": null}}}}, "isDeprecated": false, "deprecationReason": null}, {"name": "onOperation", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": true, "deprecationReason": "Use `locations`."}, {"name": "onFragment", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": true, "deprecationReason": "Use `locations`."}, {"name": "onField", "description": null, "args": [], "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "isDeprecated": true, "deprecationReason": "Use `locations`."}], "inputFields": null, "interfaces": [], "enumValues": null, "possibleTypes": null}, {"kind": "ENUM", "name": "__DirectiveLocation", "description": "A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies.", "fields": null, "inputFields": null, "interfaces": null, "enumValues": [{"name": "QUERY", "description": "Location adjacent to a query operation.", "isDeprecated": false, "deprecationReason": null}, {"name": "MUTATION", "description": "Location adjacent to a mutation operation.", "isDeprecated": false, "deprecationReason": null}, {"name": "SUBSCRIPTION", "description": "Location adjacent to a subscription operation.", "isDeprecated": false, "deprecationReason": null}, {"name": "FIELD", "description": "Location adjacent to a field.", "isDeprecated": false, "deprecationReason": null}, {"name": "FRAGMENT_DEFINITION", "description": "Location adjacent to a fragment definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "FRAGMENT_SPREAD", "description": "Location adjacent to a fragment spread.", "isDeprecated": false, "deprecationReason": null}, {"name": "INLINE_FRAGMENT", "description": "Location adjacent to an inline fragment.", "isDeprecated": false, "deprecationReason": null}, {"name": "SCHEMA", "description": "Location adjacent to a schema definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "SCALAR", "description": "Location adjacent to a scalar definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "OBJECT", "description": "Location adjacent to an object definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "FIELD_DEFINITION", "description": "Location adjacent to a field definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "ARGUMENT_DEFINITION", "description": "Location adjacent to an argument definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "INTERFACE", "description": "Location adjacent to an interface definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "UNION", "description": "Location adjacent to a union definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "ENUM", "description": "Location adjacent to an enum definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "ENUM_VALUE", "description": "Location adjacent to an enum value definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "INPUT_OBJECT", "description": "Location adjacent to an input object definition.", "isDeprecated": false, "deprecationReason": null}, {"name": "INPUT_FIELD_DEFINITION", "description": "Location adjacent to an input object field definition.", "isDeprecated": false, "deprecationReason": null}], "possibleTypes": null}], "directives": [{"name": "include", "description": "Directs the executor to include this field or fragment only when the `if` argument is true.", "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], "args": [{"name": "if", "description": "Included when true.", "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "defaultValue": null}]}, {"name": "skip", "description": "Directs the executor to skip this field or fragment when the `if` argument is true.", "locations": ["FIELD", "FRAGMENT_SPREAD", "INLINE_FRAGMENT"], "args": [{"name": "if", "description": "Skipped when true.", "type": {"kind": "NON_NULL", "name": null, "ofType": {"kind": "SCALAR", "name": "Boolean", "ofType": null}}, "defaultValue": null}]}]}}} \ No newline at end of file diff --git a/package.json b/package.json index ccf64db..9edec30 100644 --- a/package.json +++ b/package.json @@ -18,8 +18,8 @@ "url": "git+https://github.com/lvarayut/relay-fullstack.git" }, "engines": { - "node": "6.6.0", - "npm": "3.10.8" + "node": "7.4.0", + "npm": "4.0.5" }, "author": "Nicholas Romero", "license": "MIT", @@ -67,7 +67,7 @@ "react-dropdown": "^1.2.0", "react-mdl": "^1.9.0", "react-relay": "^0.9.3", - "react-router": "^3.0.0", + "react-router": "^3.0.2", "react-router-relay": "^0.13.5", "style-loader": "^0.13.1", "url-loader": "^0.5.7", diff --git a/yarn.lock b/yarn.lock index c498f1d..c1732a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1655,11 +1655,7 @@ domain-browser@^1.1.1: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" -domelementtype@1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - -domelementtype@~1.1.1: +domelementtype@1, domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" @@ -4452,7 +4448,7 @@ react-router-relay@^0.13.5: lodash "^4.15.0" react-static-container "^1.0.1" -react-router@^3.0.0: +react-router@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.0.2.tgz#5a19156678810e01d81901f9c0fef63284b8a514" dependencies: