Add GraphQL register/login (#3879)

* Add GraphQL login

* Add GraphQL register

* Add graphql login/register/delete End2End test

* Update from requests

* Remove logging

* Update to beta.16

* Update

* Add error handling

* Util function

* Update
This commit is contained in:
KalanyuZ 2019-10-16 00:17:54 +09:00 committed by Alexandre BODIN
parent 71c4745417
commit edbff44c82
5 changed files with 229 additions and 26 deletions

View File

@ -201,7 +201,7 @@ async function watchAdmin({ dir, port, options }) {
clientLogLevel: 'silent',
hot: true,
quiet: true,
open: true,
open: true,
publicPath: options.publicPath,
historyApiFallback: {
index: options.publicPath,

View File

@ -1,4 +1,18 @@
const _ = require('lodash');
const { ApolloError } = require('apollo-server-koa');
/**
* Throws an ApolloError if context body contains a bad request
* @param contextBody - body of the context object given to the resolver
* @throws ApolloError if the body is a bad request
*/
function checkBadRequest(contextBody) {
if (_.get(contextBody, 'output.payload.statusCode', 200) !== 200) {
const statusCode = _.get(contextBody, 'output.payload.statusCode', 400);
const message = _.get(contextBody, 'output.payload.message', 'Bad Request');
throw new ApolloError(message, statusCode, _.omit(contextBody, ['output']));
}
}
module.exports = {
type: {
@ -20,10 +34,25 @@ module.exports = {
description: String
type: String
}
input UsersPermissionsLoginInput {
identifier: String!
password: String!
provider: String = "local"
}
type UsersPermissionsLoginPayload {
jwt: String!
user: UsersPermissionsUser!
}
`,
query: `
me: UsersPermissionsMe
`,
mutation: `
login(input: UsersPermissionsLoginInput!): UsersPermissionsLoginPayload!
register(input: UserInput!): UsersPermissionsLoginPayload!
`,
resolver: {
Query: {
me: {
@ -158,8 +187,40 @@ module.exports = {
return {
user,
};
},
}
},
},
},
register: {
description: 'Register a user',
plugin: 'users-permissions',
resolverOf: 'Auth.register',
resolver: async (obj, options, {context}) => {
context.request.body = _.toPlainObject(options.input);
await strapi.plugins['users-permissions'].controllers.auth.register(context);
let output = context.body.toJSON ? context.body.toJSON() : context.body;
checkBadRequest(output);
return {
user: output.user || output, jwt: output.jwt
};
}
},
login: {
resolverOf: 'Auth.callback',
plugin: 'users-permissions',
resolver: async (obj, options, {context}) => {
context.params = {...context.params, provider: options.input.provider};
context.request.body = _.toPlainObject(options.input);
await strapi.plugins['users-permissions'].controllers.auth.callback(context);
let output = context.body.toJSON ? context.body.toJSON() : context.body;
checkBadRequest(output);
return {
user: output.user || output, jwt: output.jwt
};
}
}
}
}
};

View File

@ -246,7 +246,6 @@ module.exports = {
const data = await strapi.plugins['users-permissions'].services.user.remove(
{ id }
);
ctx.send(data);
},

View File

@ -0,0 +1,138 @@
// Test a simple default API with no relations
const { registerAndLogin } = require('../../../test/helpers/auth');
const { createAuthRequest } = require('../../../test/helpers/request');
let rq;
let graphqlQuery;
let data = {};
describe('Test Graphql Users API End to End', () => {
beforeAll(async () => {
const token = await registerAndLogin();
rq = createAuthRequest(token);
graphqlQuery = body => {
return rq({
url: '/graphql',
method: 'POST',
body,
});
};
}, 60000);
describe('Test register and login', () => {
const user = {
username: 'User 1',
email: 'user1@strapi.io',
password: 'test1234',
};
test('Register a user', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
mutation register($input: UserInput!) {
register(input: $input) {
jwt
user {
id
email
}
}
}
`,
variables: {
input: user,
},
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
register: {
jwt: expect.any(String),
user: {
id: expect.any(String),
email: user.email,
},
},
},
});
data.user = res.body.data.register.user;
});
test('Log in a user', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
mutation login($input: UsersPermissionsLoginInput!) {
login(input: $input) {
jwt
user {
id
email
}
}
}
`,
variables: {
input: {
identifier: user.username,
password: user.password,
},
},
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
login: {
jwt: expect.any(String),
user: {
id: expect.any(String),
email: user.email,
},
},
},
});
data.user = res.body.data.login.user;
});
test('Delete a user', async () => {
const res = await graphqlQuery({
query: /* GraphQL */ `
mutation deleteUser($input: deleteUserInput) {
deleteUser(input: $input) {
user {
email
}
}
}
`,
variables: {
input: {
where: {
id: data.user.id,
},
},
},
});
const { body } = res;
expect(res.statusCode).toBe(200);
expect(body).toMatchObject({
data: {
deleteUser: {
user: {
email: data.user.email,
},
},
},
});
});
});
});

View File

@ -7,7 +7,7 @@
// Public node modules.
const _ = require('lodash');
const sendmail = require('sendmail')({
silent: true
silent: true,
});
/* eslint-disable no-unused-vars */
@ -17,14 +17,14 @@ module.exports = {
auth: {
sendmail_default_from: {
label: 'Sendmail Default From',
type: 'text'
type: 'text',
},
sendmail_default_replyto: {
label: 'Sendmail Default Reply-To',
type: 'text'
}
type: 'text',
},
},
init: (config) => {
init: config => {
return {
send: (options, cb) => {
return new Promise((resolve, reject) => {
@ -35,23 +35,28 @@ module.exports = {
options.text = options.text || options.html;
options.html = options.html || options.text;
sendmail({
from: options.from,
to: options.to,
replyTo: options.replyTo,
subject: options.subject,
text: options.text,
html: options.html,
attachments: options.attachments
}, function (err) {
if (err) {
reject([{ messages: [{ id: 'Auth.form.error.email.invalid' }] }]);
} else {
resolve();
sendmail(
{
from: options.from,
to: options.to,
replyTo: options.replyTo,
subject: options.subject,
text: options.text,
html: options.html,
attachments: options.attachments,
},
function(err) {
if (err) {
reject([
{ messages: [{ id: 'Auth.form.error.email.invalid' }] },
]);
} else {
resolve();
}
}
});
);
});
}
},
};
}
},
};