Skip to content

Commit

Permalink
Merge pull request #2 from ujwal-setlur/master
Browse files Browse the repository at this point in the history
phone login support
  • Loading branch information
theodorDiaconu authored Oct 22, 2018
2 parents 4f5a5c4 + 3b30e58 commit a3a04d5
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 12 deletions.
89 changes: 88 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ Initialize the package.

```js
import { makeExecutableSchema } from 'graphql-tools';
import { initAccounts } from 'meteor/nicolaslopezj:apollo-accounts';
import { initAccounts } from 'meteor/cultofcoders:apollo-accounts';
import { load, getSchema } from 'graphql-load';

const { typeDefs, resolvers } = initAccounts({
loginWithFacebook: false,
loginWithGoogle: false,
loginWithLinkedIn: false,
loginWithPhone: false,
loginWithPassword: true,
overrideCreateUser: (createUser, _, args, context) {
// Optionally override createUser if you need custom logic
Expand Down Expand Up @@ -202,6 +203,92 @@ loginWithGoogle({ accessToken }, apollo);

- `apollo`: Apollo client instance.

#### Phone support

Login support using phone number and verification code. Requires ujwal:accounts-phone package.

```
meteor add ujwal:accounts-phone
```

From your client, execute the following mutation:

```graphql
mutation createUserWithPhone {
createUserWithPhone (phone: "+11234567890", profile: {name: "A Phone User"}) {
success
}
}
```

Server response:
```js
{
"data": {
"createUserWithPhone": {
"success": true
}
}
}
```

If Twilio has been set up on the server, a verification code will be sent to the phone via SMS.

To login with the verification code, use the following mutation:

```graphql
mutation loginWithPhone {
loginWithPhone (phone: "+11234567890", verificationCode: "6593") {
id
token
tokenExpires
}
}
```

Server response:
```js
{
"data": {
"loginWithPhone": {
"id": "eHMzRW9B685curZ63",
"token": "Kg9mESwmEAs6xraKZ_hPv0tzOvQpTgMPhWTNXDFCet0",
"tokenExpires": 1535581386595
}
}
}
```

You can use the response to store the login token:

```js
await setTokenStore.set(id, token, new Date(tokenExpires));
```

To request a new verification code, use the following mutation:

```graphql
mutation resendPhoneVerification {
resendPhoneVerification (phone: "+11234567890") {
success
}
}
```

Server response:

```js
{
"data": {
"resendPhoneVerification": {
"success": true
}
}
}
```

If Twilio has been set up, then the verification code will sent via SMS.

#### onTokenChange

Register a function to be called when a user is logged in or out.
Expand Down
1 change: 1 addition & 0 deletions package.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Package.onUse(function(api) {
'oauth',
'service-configuration',
'accounts-oauth',
'sha',
],
'server'
);
Expand Down
2 changes: 1 addition & 1 deletion src/Auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type LoginMethodResponse {
# Token of the connection
token: String!
# Expiration date for the token
tokenExpires: Float!
tokenExpires: String!
# The logged in user
user: User
}
Expand Down
15 changes: 15 additions & 0 deletions src/Mutation/createUserWithPhone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {Meteor} from 'meteor/meteor'
import {Accounts} from 'meteor/accounts-base'

export default async function (root, options, context) {
Meteor._nodeCodeMustBeInFiber()
if (!options.phone) {
throw new Error('Phone number is required')
}

let userId = Accounts.createUserWithPhone(options)
if(userId) {
Accounts.sendPhoneVerificationCode(userId, options.phone);
}
return ({success: !!userId})
}
29 changes: 19 additions & 10 deletions src/Mutation/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import loginWithPassword from './loginWithPassword';
import logout from './logout';
import changePassword from './changePassword';
import createUser from './createUser';
import verifyEmail from './verifyEmail';
import resendVerificationEmail from './resendVerificationEmail';
import forgotPassword from './forgotPassword';
import resetPassword from './resetPassword';
import oauth from './oauth';
import hasService from './oauth/hasService';
import loginWithPassword from './loginWithPassword'
import loginWithPhone from './loginWithPhone'
import logout from './logout'
import changePassword from './changePassword'
import createUser from './createUser'
import createUserWithPhone from './createUserWithPhone'
import verifyEmail from './verifyEmail'
import resendVerificationEmail from './resendVerificationEmail'
import resendPhoneVerification from './resendPhoneVerification'
import forgotPassword from './forgotPassword'
import resetPassword from './resetPassword'
import oauth from './oauth'
import hasService from './oauth/hasService'

export default function(options) {
const resolvers = {
Expand Down Expand Up @@ -35,5 +38,11 @@ export default function(options) {
resolvers.resetPassword = resetPassword;
}

if (hasService(options, 'phone')) {
resolvers.loginWithPhone = loginWithPhone
resolvers.createUserWithPhone = createUserWithPhone
resolvers.resendPhoneVerification = resendPhoneVerification
}

return { Mutation: resolvers };
}
14 changes: 14 additions & 0 deletions src/Mutation/loginWithPhone.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import callMethod from '../callMethod'
import {Meteor} from 'meteor/meteor'


export default async function (root, options, context) {
if (!options.phone) {
throw new Error('Phone number is required')
}
if (!options.verificationCode) {
throw new Error('Verification code is required')
}

return callMethod(context, 'verifyPhone', options.phone, options.verificationCode)
}
4 changes: 4 additions & 0 deletions src/Mutation/oauth/hasService.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@ export default function (options, service) {
return options.loginWithLinkedIn
}

if (service === 'phone') {
return options.loginWithPhone
}

return false
}
15 changes: 15 additions & 0 deletions src/Mutation/resendPhoneVerification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import callMethod from '../callMethod'
import {Meteor} from 'meteor/meteor'


export default async function (root, options, context) {
if (!options.phone) {
throw new Error('Phone number is required')
}

callMethod(context, 'requestPhoneVerification', options.phone)

return {
success: true
}
}
14 changes: 14 additions & 0 deletions src/Mutations.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ export default function(options) {
}`);
}

if (hasService(options, 'phone')) {
mutations.push(`
type Mutation {
# Log the user in with a phone.
loginWithPhone (phone: String, verificationCode: String): LoginMethodResponse
# Create a new user with a phone.
createUserWithPhone (phone: String, password: String, profile: CreateUserProfileInput): AuthSuccessResponse
# Send verification code to phone.
resendPhoneVerification (phone: String): AuthSuccessResponse
}`)
}

mutations.push(`
type Mutation {
# Log the user out.
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const initAccounts = function(givenOptions) {
loginWithGoogle: false,
loginWithLinkedIn: false,
loginWithPassword: true,
loginWithPhone: false,
overrideCreateUser: null, // createUser, args, context
};
const options = {
Expand Down

0 comments on commit a3a04d5

Please sign in to comment.