Skip to content
Snippets Groups Projects
Commit eb6d82ff authored by Sebastian's avatar Sebastian
Browse files

fix invite and mail service

parent a14c5784
No related branches found
No related tags found
No related merge requests found
# AWS SES # Invite Component
In order to use `component-aws-ses` you first need to have a `.env` file containing AWS data in the root folder of the starting point of your application. ## Configuration
The `.env` file contain the following data: In order to use this component, the following configuration needs to be added to a PubSweet application, like so:
```bash
AWS_SES_SECRET_KEY = <secretKey>
AWS_SES_ACCESS_KEY = <accessKey>
EMAIL_SENDER = verified_ses_sender@domain.com
AWS_SES_REGION = region-name
```
Then, as soon as possible in your app you should add the `dotenv` package: ```json
```js {
require('dotenv').config() 'invite-reset-password': {
url: 'http://localhost:3000/invite',
},
roles: {
global: ['admin', 'editorInChief', 'author'],
collection: ['handlingEditor', 'reviewer'],
inviteRights: {
admin: ['admin', 'editorInChief', 'author'],
editorInChief: ['handlingEditor'],
handlingEditor: ['reviewer'],
},
},
``` ```
# `component-aws-ses` API ## Usage
A list of endpoints that help you upload, download and delete S3 files.
Here's the list of endpoints that'll help you invite new users in your Pubsweet app.
### Upload a file [POST]
This endpoint allows you to create a new user in your app and then send him a confirmation email.
## Send an email [POST] #### Invite request
#### Request
`POST /api/email` `POST /api/users/invite/{collectionId}`
#### Request body | URI Parameter | Requiered | Requirements | Description |
| ------------- | --------- | ------------ | ------------------ |
| collectionId | No | String | The ID of the collection |
#### Invite request body
All parameters are `required`
```json ```json
{ {
"email": "to_email@domain.com", "email": "new_user@domain.com" /* required */,
"subject": "Example subject", "role": "editorInChief" /* required */,
"textBody": "this is an email", "firstName": "Marc",
"htmlBody": "<p><b>This</b> is an <i>email</i>" "lastName": "Twain",
"title": "Prof",
"affiliation": "MIT"
} }
``` ```
#### Response
#### Invite user response
```json ```json
HTTP/1.1 204 HTTP/1.1 200
{
"id": "37463722-c4ca-4e3c-acec-779df8c11ad2",
"username": "9a42b55f",
"email": "new_user@domain.com",
"roles": ["editorInChief"],
"passwordResetToken": "123",
"isConfirmed": false,
"firstName": "Marc",
"lastName": "Twain",
"affiliation": "MIT",
"title": "Prof",
"admin": false,
"type": "user",
"rev": "1-12ebbb6686614791bb08ead305cde4f8"
}
``` ```
---
### Retrieve invited user details [GET]
This endpoint allows you to retrieve an invited users' details so that you can display them in the confirmation form.
#### User details request
`GET /api/users/invite?email=new_user@domain.com&token=123`
| Query Parameter | Requiered | Requirements | Description |
| --------------- | --------- | ------------ | ------------------------ |
| email | Yes | String | The user's email |
| token | Yes | String | The password reset token |
#### User details response
```json
HTTP/1.1 200
{
"firstName": "dsadasd",
"lastName": "fisdadasdasdaasdago",
"affiliation": "asdasasae23",
"title": "131sdadassa"
}
```
---
### Reset password [POST]
This endpoint will reset a user's password and confirm his account.
#### Reset password request
`POST /api/users/invite/password/reset`
#### Reset password request body
```json
// All fields are required
{
"email": "new_user@domain.com",
"token": "123",
"firstName": "Marc",
"lastName": "Twain",
"title": "Prof",
"affiliation": "MIT",
"password": "verySecure"
}
```
#### Response
```json
HTTP/1.1 200
{
"id": "37463722-c4ca-4e3c-acec-779df8c11ad2",
"username": "9a42b55f",
"email": "new_user@domain.com",
"isConfirmed": true,
"firstName": "Marc",
"lastName": "Twain",
"affiliation": "MIT",
"title": "Prof",
"admin": false,
"type": "user",
"roles": [
"editorInChief"
],
"collections": [],
"fragments": [],
"teams": [],
"rev": "2-81fb76ae72f143bb9edc2b4d4deaf7a3"
}
```
---
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
"version": "0.0.1", "version": "0.0.1",
"description": "invite component for pubsweet", "description": "invite component for pubsweet",
"license": "MIT", "license": "MIT",
"files": [ "author": "Collaborative Knowledge Foundation",
"src" "files": ["src"],
], "main": "index.js",
"scripts": { "scripts": {
"test": "jest" "test": "jest"
}, },
...@@ -20,24 +20,18 @@ ...@@ -20,24 +20,18 @@
}, },
"peerDependencies": { "peerDependencies": {
"@pubsweet/logger": "^0.0.1", "@pubsweet/logger": "^0.0.1",
"pubsweet": "^1.1.1", "pubsweet-server": "^1.0.1",
"pubsweet-client": "^1.1.1", "pubsweet-component-mail-service": "0.0.1"
"pubsweet-server": "^1.0.1"
}, },
"devDependencies": { "devDependencies": {
"jest": "^22.1.1", "jest": "^22.1.1",
"supertest": "^3.0.0" "supertest": "^3.0.0"
}, },
"jest": { "jest": {
"moduleNameMapper": { "verbose": true,
"\\.s?css$": "identity-obj-proxy" "testRegex": "/src/.*.test.js$"
}, },
"transformIgnorePatterns": [ "publishConfig": {
"/node_modules/(?!@?pubsweet)" "access": "public"
],
"testPathIgnorePatterns": [
"/node_modules",
"config/"
]
} }
} }
...@@ -51,6 +51,11 @@ const validateEmailAndToken = async (email, token, userModel) => { ...@@ -51,6 +51,11 @@ const validateEmailAndToken = async (email, token, userModel) => {
message: e.details[0].message, message: e.details[0].message,
} }
} }
return {
success: false,
status: 500,
message: 'something went wrong',
}
} }
const hasInviteRight = (configRoles, userRoles, role) => { const hasInviteRight = (configRoles, userRoles, role) => {
...@@ -68,6 +73,8 @@ const hasInviteRight = (configRoles, userRoles, role) => { ...@@ -68,6 +73,8 @@ const hasInviteRight = (configRoles, userRoles, role) => {
return { return {
success: true, success: true,
status: null,
message: null,
} }
} }
......
...@@ -97,7 +97,7 @@ module.exports = models => async (req, res) => { ...@@ -97,7 +97,7 @@ module.exports = models => async (req, res) => {
if (collection) if (collection)
await helpers.createNewTeam(collection.id, newUser, models.Team) await helpers.createNewTeam(collection.id, newUser, models.Team)
await mailService.setupEmail( await mailService.setupInviteEmail(
newUser.email, newUser.email,
'invite', 'invite',
newUser.passwordResetToken, newUser.passwordResetToken,
......
...@@ -8,7 +8,9 @@ const UserMock = require('./mocks/User') ...@@ -8,7 +8,9 @@ const UserMock = require('./mocks/User')
const Chance = require('chance') const Chance = require('chance')
const TeamMock = require('./mocks/Team') const TeamMock = require('./mocks/Team')
jest.mock('pubsweet-component-mail-service', () => ({ setupEmail: jest.fn() })) jest.mock('pubsweet-component-mail-service', () => ({
setupInviteEmail: jest.fn(),
}))
const chance = new Chance() const chance = new Chance()
const globalRoles = ['editorInChief', 'author', 'admin'] const globalRoles = ['editorInChief', 'author', 'admin']
const manuscriptRoles = ['handlingEditor', 'reviewer'] const manuscriptRoles = ['handlingEditor', 'reviewer']
......
# Mail Service
## Configuration
In order to use this component, simply add the desired templates in the `src/templates/` folder and use them by matching the `emailType` parameter with the template name.
## Usage
Once you have your template setup, simply add a a case in the `switch` statement from `src/Mail.js`:
```js
switch (emailType) {
case 'invitation-email':
subject = 'You have been invited!'
break
default:
subject = 'Welcome!'
break
}
```
...@@ -3,12 +3,13 @@ ...@@ -3,12 +3,13 @@
"version": "0.0.1", "version": "0.0.1",
"description": "mail service component for pubsweet", "description": "mail service component for pubsweet",
"license": "MIT", "license": "MIT",
"files": [ "author": "Collaborative Knowledge Foundation",
"src" "files": ["src"],
], "main": "index.js",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://gitlab.coko.foundation/xpub/xpub" "url": "https://gitlab.coko.foundation/xpub/xpub",
"path": "component-mail-service"
}, },
"dependencies": { "dependencies": {
"body-parser": "^1.17.2", "body-parser": "^1.17.2",
...@@ -16,12 +17,10 @@ ...@@ -16,12 +17,10 @@
}, },
"peerDependencies": { "peerDependencies": {
"@pubsweet/logger": "^0.0.1", "@pubsweet/logger": "^0.0.1",
"pubsweet": "^1.1.1", "pubsweet-server": "^1.0.1",
"pubsweet-client": "^1.1.1", "@pubsweet/component-aws-ses": "^0.2.0"
"pubsweet-server": "^1.0.1"
}, },
"devDependencies": { "publishConfig": {
"jest": "^22.1.1", "access": "public"
"supertest": "^3.0.0"
} }
} }
const fs = require('fs') const fs = require('fs')
const handlebars = require('handlebars') const handlebars = require('handlebars')
const querystring = require('querystring') const querystring = require('querystring')
const SES = require('pubsweet-components-aws-ses') const SES = require('@pubsweet/component-aws-ses')
const config = require('config') const config = require('config')
const resetUrl = config.get('invite-reset-password.url') const resetUrl = config.get('invite-reset-password.url')
module.exports = { module.exports = {
setupEmail: async (email, emailType, token, comment = '') => { setupInviteEmail: async (email, emailType, token, comment = '') => {
console.log('asereke', emailType)
let subject let subject
const htmlFile = readFile(`${__dirname}/templates/${emailType}.html`) const htmlFile = readFile(`${__dirname}/templates/${emailType}.html`)
const textFile = readFile(`${__dirname}/templates/${emailType}.txt`) const textFile = readFile(`${__dirname}/templates/${emailType}.txt`)
...@@ -16,7 +17,7 @@ module.exports = { ...@@ -16,7 +17,7 @@ module.exports = {
const textTemplate = handlebars.compile(textFile) const textTemplate = handlebars.compile(textFile)
switch (emailType) { switch (emailType) {
case 'invite-editor-in-chief': case 'invite':
subject = 'Hindawi Invitation' subject = 'Hindawi Invitation'
replacements = { replacements = {
url: `${resetUrl}?${querystring.encode({ url: `${resetUrl}?${querystring.encode({
......
...@@ -178,7 +178,7 @@ ...@@ -178,7 +178,7 @@
<td style="padding:30px 23px 0px 23px;background-color:#ffffff;" height="100%" valign="top" bgcolor="#ffffff"> <td style="padding:30px 23px 0px 23px;background-color:#ffffff;" height="100%" valign="top" bgcolor="#ffffff">
<h1 style="text-align: center;">You have been invited to join Hindawi</h1> <h1 style="text-align: center;">You have been invited to join Hindawi</h1>
<div style="text-align: center;">You can now join Hindawi as an Editor in Chief.</div> <div style="text-align: center;">You can now join Hindawi</div>
<div style="text-align: center;">Please confirm your account and set your account details by clicking on the link below.</div> <div style="text-align: center;">Please confirm your account and set your account details by clicking on the link below.</div>
......
You have been invited to Hindawi You have been invited to Hindawi
You can now join Hindawi as an Editor in Chief. You can now join Hindawi.
Please confirm your account and set your account details by clicking on the link below. Please confirm your account and set your account details by clicking on the link below.
{{ url }} CONFIRM {{ url }} CONFIRM
Hindawi Publishing Corporation Hindawi Publishing Corporation
......
...@@ -29,8 +29,8 @@ ...@@ -29,8 +29,8 @@
"pubsweet-component-login": "^1.0.1", "pubsweet-component-login": "^1.0.1",
"pubsweet-component-signup": "^1.0.0", "pubsweet-component-signup": "^1.0.0",
"pubsweet-component-xpub-manuscript": "^0.0.2", "pubsweet-component-xpub-manuscript": "^0.0.2",
"pubsweet-component-invite": "^0.0.1",
"pubsweet-server": "^1.0.1", "pubsweet-server": "^1.0.1",
"pubsweet-component-invite": "^0.0.1",
"react": "^16.2.0", "react": "^16.2.0",
"react-dom": "^16.2.0", "react-dom": "^16.2.0",
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment