Skip to content
This repository has been archived by the owner on Aug 14, 2021. It is now read-only.

Commit

Permalink
Enhance resolvers with integration (#25)
Browse files Browse the repository at this point in the history
- Move signInEmail query to mutation with lacking useLazyQuery
    - Currently, useLazyQuery does not return promises apollographql/react-apollo#3499.

- Change `status` to `statusMessage` and do migration
   - Fix some of migration scripts.
* Add and update types for User
   - Add `isOnline`, `lastSignedIn` fields.
   - Changed to DATEONLY type for birthday and prevent being parsed to javascript date (sequelize/sequelize#4858).'
  • Loading branch information
hyochan authored Jan 26, 2020
1 parent 9515590 commit 0ca28d9
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 70 deletions.
34 changes: 13 additions & 21 deletions config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ const path = require('path');

const env = process.env.NODE_ENV;

const envPath =
env === 'development'
? path.resolve(__dirname, '../dotenv/dev.env')
: env === 'test'
? path.resolve(__dirname, '../dotenv/test.env')
: path.resolve(__dirname, '../dotenv/.env');
const envPath = env === 'development'
? path.resolve(__dirname, '../dotenv/dev.env')
: env === 'test'
? path.resolve(__dirname, '../dotenv/test.env')
: path.resolve(__dirname, '../dotenv/.env');

dotenv.config({ path: envPath });

const similarOption = {
let config = {
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
Expand All @@ -26,21 +25,14 @@ const similarOption = {
},
};

module.exports = {
local: {
...similarOption,
},
development: {
...similarOption,
},
test: {
...similarOption,
},
production: {
...similarOption,
if (process.env.NODE_ENV === 'production') {
config = {
...config,
dialectOptions: {
ssl: {},
},
pool: { max: 5, min: 0, idle: 10000 },
},
};
};
}

module.exports = config;
19 changes: 19 additions & 0 deletions migrations/20200126063808-User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'use strict';

module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.renameColumn(
'users',
'status',
'statusMessage',
);
},

down: (queryInterface, Sequelize) => {
return queryInterface.renameColumn(
'users',
'statusMessage',
'status',
);
}
};
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
"codegen": "graphql-codegen",
"generate": "graphql-codegen --config codegen.yml",
"codecov": "codecov",
"migrate:dev": "dotenv -e ./dotenv/dev.env sequelize db:migrate --env development",
"migrate:test": "dotenv -e ./dotenv/test.env sequelize db:migrate --env test",
"migrate:prod": "npx dotenv -e ./dotenv/prod.env sequelize db:migrate --env prod",
"migrate:generate": "sequelize-cli migration:generate --name",
"migrate:dev": "cross-env NODE_ENV=development sequelize db:migrate",
"migrate:test": "cross-env NODE_ENV=test sequelize db:migrate",
"migrate:prod": "cross-env NODE_ENV=production sequelize db:migrate",
"migrate": "yarn migrate:dev && yarn migrate:test && yarn migrate:prod"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion schemas/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ type Query {
users(includeUser: Boolean): [User!]!
user(id: ID!): User
me: User
signInEmail(email: String! password: String!): AuthPayload!
findPassword(email: String!): Boolean
messages: [Message!]!
channels: [Channel!]!
friends: [Friend!]!
}

type Mutation {
signInEmail(email: String! password: String!): AuthPayload!
signInGoogle(socialUser: SocialUserInput!): AuthPayload!
signInFacebook(socialUser: SocialUserInput!): AuthPayload!
signInApple(socialUser: SocialUserInput!): AuthPayload!
Expand Down
5 changes: 4 additions & 1 deletion schemas/user.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type User {
authType: AuthType
phone: String
verified: Boolean
statusMessage: String
isOnline: Boolean
lastSignedIn: DateTime
notifications: [Notification]
channels: [Channel]
friends: [User]
Expand All @@ -44,7 +47,7 @@ input UserInput {
birthday: Date
gender: Gender
phone: String
status: String
statusMessage: String
}

input SocialUserInput {
Expand Down
4 changes: 2 additions & 2 deletions src/db/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Op, Sequelize } from 'sequelize';
const env = process.env.NODE_ENV || 'development';
const config = require('../../config/config')[env];

import config from '../../config/config';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const operatorsAliases = {
Expand Down
32 changes: 19 additions & 13 deletions src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export type Message = {

export type Mutation = {
__typename?: 'Mutation',
signInEmail: AuthPayload,
signInGoogle: AuthPayload,
signInFacebook: AuthPayload,
signInApple: AuthPayload,
Expand All @@ -99,6 +100,12 @@ export type Mutation = {
};


export type MutationSignInEmailArgs = {
email: Scalars['String'],
password: Scalars['String']
};


export type MutationSignInGoogleArgs = {
socialUser: SocialUserInput
};
Expand Down Expand Up @@ -160,7 +167,6 @@ export type Query = {
users: Array<User>,
user?: Maybe<User>,
me?: Maybe<User>,
signInEmail: AuthPayload,
findPassword?: Maybe<Scalars['Boolean']>,
messages: Array<Message>,
channels: Array<Channel>,
Expand All @@ -178,12 +184,6 @@ export type QueryUserArgs = {
};


export type QuerySignInEmailArgs = {
email: Scalars['String'],
password: Scalars['String']
};


export type QueryFindPasswordArgs = {
email: Scalars['String']
};
Expand Down Expand Up @@ -238,6 +238,9 @@ export type User = {
authType?: Maybe<AuthType>,
phone?: Maybe<Scalars['String']>,
verified?: Maybe<Scalars['Boolean']>,
statusMessage?: Maybe<Scalars['String']>,
isOnline?: Maybe<Scalars['Boolean']>,
lastSignedIn?: Maybe<Scalars['DateTime']>,
notifications?: Maybe<Array<Maybe<Notification>>>,
channels?: Maybe<Array<Maybe<Channel>>>,
friends?: Maybe<Array<Maybe<User>>>,
Expand All @@ -254,7 +257,7 @@ export type UserInput = {
birthday?: Maybe<Scalars['Date']>,
gender?: Maybe<Gender>,
phone?: Maybe<Scalars['String']>,
status?: Maybe<Scalars['String']>,
statusMessage?: Maybe<Scalars['String']>,
};

export enum UserModeType {
Expand Down Expand Up @@ -342,17 +345,17 @@ export type ResolversTypes = {
Date: ResolverTypeWrapper<Scalars['Date']>,
Gender: Gender,
AuthType: AuthType,
Notification: ResolverTypeWrapper<Notification>,
DateTime: ResolverTypeWrapper<Scalars['DateTime']>,
Notification: ResolverTypeWrapper<Notification>,
Channel: ResolverTypeWrapper<Channel>,
Message: ResolverTypeWrapper<Message>,
Reply: ResolverTypeWrapper<Reply>,
Membership: ResolverTypeWrapper<Membership>,
MemberType: MemberType,
UserModeType: UserModeType,
AuthPayload: ResolverTypeWrapper<AuthPayload>,
Friend: ResolverTypeWrapper<Friend>,
Mutation: ResolverTypeWrapper<{}>,
AuthPayload: ResolverTypeWrapper<AuthPayload>,
SocialUserInput: SocialUserInput,
UserInput: UserInput,
NotificationCreateInput: NotificationCreateInput,
Expand All @@ -369,17 +372,17 @@ export type ResolversParentTypes = {
Date: Scalars['Date'],
Gender: Gender,
AuthType: AuthType,
Notification: Notification,
DateTime: Scalars['DateTime'],
Notification: Notification,
Channel: Channel,
Message: Message,
Reply: Reply,
Membership: Membership,
MemberType: MemberType,
UserModeType: UserModeType,
AuthPayload: AuthPayload,
Friend: Friend,
Mutation: {},
AuthPayload: AuthPayload,
SocialUserInput: SocialUserInput,
UserInput: UserInput,
NotificationCreateInput: NotificationCreateInput,
Expand Down Expand Up @@ -444,6 +447,7 @@ export type MessageResolvers<ContextType = MyContext, ParentType extends Resolve
};

export type MutationResolvers<ContextType = MyContext, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = {
signInEmail?: Resolver<ResolversTypes['AuthPayload'], ParentType, ContextType, RequireFields<MutationSignInEmailArgs, 'email' | 'password'>>,
signInGoogle?: Resolver<ResolversTypes['AuthPayload'], ParentType, ContextType, RequireFields<MutationSignInGoogleArgs, 'socialUser'>>,
signInFacebook?: Resolver<ResolversTypes['AuthPayload'], ParentType, ContextType, RequireFields<MutationSignInFacebookArgs, 'socialUser'>>,
signInApple?: Resolver<ResolversTypes['AuthPayload'], ParentType, ContextType, RequireFields<MutationSignInAppleArgs, 'socialUser'>>,
Expand All @@ -467,7 +471,6 @@ export type QueryResolvers<ContextType = MyContext, ParentType extends Resolvers
users?: Resolver<Array<ResolversTypes['User']>, ParentType, ContextType, QueryUsersArgs>,
user?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType, RequireFields<QueryUserArgs, 'id'>>,
me?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType>,
signInEmail?: Resolver<ResolversTypes['AuthPayload'], ParentType, ContextType, RequireFields<QuerySignInEmailArgs, 'email' | 'password'>>,
findPassword?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType, RequireFields<QueryFindPasswordArgs, 'email'>>,
messages?: Resolver<Array<ResolversTypes['Message']>, ParentType, ContextType>,
channels?: Resolver<Array<ResolversTypes['Channel']>, ParentType, ContextType>,
Expand Down Expand Up @@ -504,6 +507,9 @@ export type UserResolvers<ContextType = MyContext, ParentType extends ResolversP
authType?: Resolver<Maybe<ResolversTypes['AuthType']>, ParentType, ContextType>,
phone?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
verified?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>,
statusMessage?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>,
isOnline?: Resolver<Maybe<ResolversTypes['Boolean']>, ParentType, ContextType>,
lastSignedIn?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>,
notifications?: Resolver<Maybe<Array<Maybe<ResolversTypes['Notification']>>>, ParentType, ContextType>,
channels?: Resolver<Maybe<Array<Maybe<ResolversTypes['Channel']>>>, ParentType, ContextType>,
friends?: Resolver<Maybe<Array<Maybe<ResolversTypes['User']>>>, ParentType, ContextType>,
Expand Down
16 changes: 14 additions & 2 deletions src/models/User.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { BuildOptions, DataTypes, Model } from 'sequelize';

import moment from 'moment';
import sequelize from '../db';

const {
STRING,
BOOLEAN,
DATE,
DATEONLY,
UUID,
UUIDV1,
ENUM,
Expand Down Expand Up @@ -36,6 +38,9 @@ export class User extends Model {
public socialId: string;
public authType: AuthType;
public verified: boolean;
public statusMessage: string;
public isOnline: boolean;
public lastSignedIn: Date;
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
public readonly deletedAt!: Date;
Expand All @@ -58,7 +63,12 @@ User.init({
name: STRING,
nickname: STRING,
photoURL: STRING,
birthday: DATE,
birthday: {
type: DATEONLY,
get: function(): string {
return moment.utc(this.getDataValue('regDate')).format('YYYY-MM-DD');
},
},
gender: ENUM('MALE', 'FEMALE'),
phone: STRING,
socialId: STRING,
Expand All @@ -67,7 +77,9 @@ User.init({
type: BOOLEAN,
defaultValue: false,
},
status: TEXT,
statusMessage: TEXT,
isOnline: BOOLEAN,
lastSignedIn: DATE,
}, {
sequelize,
modelName: 'user',
Expand Down
54 changes: 27 additions & 27 deletions src/resolvers/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,33 +96,6 @@ const resolver: Resolvers = {

return User.findOne({ where: args });
},
signInEmail: async (_, args, { models, appSecret, pubsub }): Promise<AuthPayload> => {
const { User: userModel } = models;

const user = await userModel.findOne({
where: {
email: args.email,
},
raw: true,
});

if (!user) throw new AuthenticationError('User does not exsists');

const validate = await validateCredential(args.password, user.password);

if (!validate) throw new AuthenticationError('Password is not correct');

const token: string = jwt.sign(
{
userId: user.id,
role: Role.User,
},
appSecret,
);

pubsub.publish(USER_SIGNED_IN, { userSignedIn: user });
return { token, user };
},
findPassword: async (_, args): Promise<boolean> => {
const email = args.email;

Expand Down Expand Up @@ -153,6 +126,33 @@ your password will reset to <strong>dooboolab2017</strong>.
},
},
Mutation: {
signInEmail: async (_, args, { models, appSecret, pubsub }): Promise<AuthPayload> => {
const { User: userModel } = models;

const user = await userModel.findOne({
where: {
email: args.email,
},
raw: true,
});

if (!user) throw new AuthenticationError('User does not exsists');

const validate = await validateCredential(args.password, user.password);

if (!validate) throw new AuthenticationError('Password is not correct');

const token: string = jwt.sign(
{
userId: user.id,
role: Role.User,
},
appSecret,
);

pubsub.publish(USER_SIGNED_IN, { userSignedIn: user });
return { token, user };
},
signInGoogle: async (_, { socialUser }, { appSecret, models }): Promise<AuthPayload> =>
signInWithSocialAccount(socialUser, models, appSecret),

Expand Down

0 comments on commit 0ca28d9

Please sign in to comment.