Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document email adapter #1144

Merged
merged 8 commits into from
Mar 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ We have provided a basic [Node.js application](https://github.com/ParsePlatform/
* [Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-run-parse-server-on-ubuntu-14-04)
* [NodeChef](https://nodechef.com/blog/post/6/migrate-from-parse-to-nodechef%E2%80%99s-managed-parse-server)
* [Google App Engine](https://medium.com/@justinbeckwith/deploying-parse-server-to-google-app-engine-6bc0b7451d50)
* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/)
* [Microsoft Azure](https://azure.microsoft.com/en-us/blog/azure-welcomes-parse-developers/)
* [Pivotal Web Services](https://github.com/cf-platform-eng/pws-parse-server)
* [Back4app](http://blog.back4app.com/2016/03/01/quick-wizard-migration/)

Expand Down Expand Up @@ -187,6 +187,36 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
* `loggerAdapter` - The default behavior/transport (File) can be changed by creating an adapter class (see [`LoggerAdapter.js`](https://github.com/ParsePlatform/parse-server/blob/master/src/Adapters/Logger/LoggerAdapter.js)).
* `databaseAdapter` - The backing store can be changed by creating an adapter class (see `DatabaseAdapter.js`). Defaults to `MongoStorageAdapter`.

##### Email verification and password reset

Verifying user email addresses and enabling password reset via email requries an email adapter. As part of the `parse-server` package we provide an adapter for sending email through Mailgun. To use it, sign up for Mailgun, and add this to your initialization code:

```js
var server = ParseServer({
...otherOptions,
// Enable email verification
verifyUserEmails: true,
// The public URL of your app.
// This will appear in the link that is used to verify email addresses and reset passwords.
publicServerURL: 'https://example.com',
// Your apps name. This will appear in the subject and body of the emails that are sent.
appName: 'Parse App',
// The email adapter
emailAdapter: {
module: 'parse-server-simple-mailgun-adapter',
options: {
// The address that your emails come from
fromAddress: 'parse@example.com',
// Your domain from mailgun.com
domain: 'example.com',
// Your API key from mailgun.com
apiKey: 'key-mykey',
}
}
});

You can also use other email adapters contributed by the community such as [parse-server-sendgrid-adapter](https://www.npmjs.com/package/parse-server-sendgrid-adapter).

### Using environment variables to configure Parse Server

You may configure the Parse Server using environment variables:
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"parse-server-fs-adapter": "^1.0.0",
"parse-server-gcs-adapter": "^1.0.0",
"parse-server-s3-adapter": "^1.0.0",
"parse-server-simple-mailgun-adapter": "^1.0.0",
"redis": "^2.5.0-1",
"request": "^2.65.0",
"tv4": "^1.2.7",
Expand Down
13 changes: 8 additions & 5 deletions spec/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe('server', () => {
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: MockEmailAdapterWithOptions({
fromAddress: 'parse@example.com',
apiKey: 'k',
domain: 'd',
}),
Expand All @@ -80,6 +81,7 @@ describe('server', () => {
emailAdapter: {
class: MockEmailAdapterWithOptions,
options: {
fromAddress: 'parse@example.com',
apiKey: 'k',
domain: 'd',
}
Expand All @@ -103,8 +105,9 @@ describe('server', () => {
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
module: './Email/SimpleMailgunAdapter',
module: 'parse-server-simple-mailgun-adapter',
options: {
fromAddress: 'parse@example.com',
apiKey: 'k',
domain: 'd',
}
Expand All @@ -127,9 +130,9 @@ describe('server', () => {
collectionPrefix: 'test_',
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: './Email/SimpleMailgunAdapter',
emailAdapter: 'parse-server-simple-mailgun-adapter',
publicServerURL: 'http://localhost:8378/1'
})).toThrow('SimpleMailgunAdapter requires an API Key and domain.');
})).toThrow('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
done();
});

Expand All @@ -147,13 +150,13 @@ describe('server', () => {
fileKey: 'test',
verifyUserEmails: true,
emailAdapter: {
module: './Email/SimpleMailgunAdapter',
module: 'parse-server-simple-mailgun-adapter',
options: {
domain: 'd',
}
},
publicServerURL: 'http://localhost:8378/1'
})).toThrow('SimpleMailgunAdapter requires an API Key and domain.');
})).toThrow('SimpleMailgunAdapter requires an API Key, domain, and fromAddress.');
done();
});

Expand Down
9 changes: 6 additions & 3 deletions src/Adapters/AdapterLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ export function loadAdapter(adapter, defaultAdapter, options) {
try {
return adapter(options);
} catch(e) {
var Adapter = adapter;
return new Adapter(options);
if (e.name === 'TypeError') {
var Adapter = adapter;
return new Adapter(options);
} else {
throw e;
}
}
} else if (typeof adapter === "string") {
adapter = require(adapter);
// If it's define as a module, get the default
if (adapter.default) {
adapter = adapter.default;
}

return loadAdapter(adapter, undefined, options);
} else if (adapter.module) {
return loadAdapter(adapter.module, undefined, adapter.options);
Expand Down
32 changes: 0 additions & 32 deletions src/Adapters/Email/SimpleMailgunAdapter.js

This file was deleted.

10 changes: 5 additions & 5 deletions src/Controllers/UserController.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { randomString } from '../cryptoUtils';
import { inflate } from '../triggers';
import { randomString } from '../cryptoUtils';
import { inflate } from '../triggers';
import AdaptableController from './AdaptableController';
import MailAdapter from '../Adapters/Email/MailAdapter';
import rest from '../rest';
import MailAdapter from '../Adapters/Email/MailAdapter';
import rest from '../rest';

var DatabaseAdapter = require('../DatabaseAdapter');
var RestWrite = require('../RestWrite');
Expand Down Expand Up @@ -181,7 +181,7 @@ export class UserController extends AdaptableController {

defaultVerificationEmail({link, user, appName, }) {
let text = "Hi,\n\n" +
"You are being asked to confirm the e-mail address " + user.email + " with " + appName + "\n\n" +
"You are being asked to confirm the e-mail address " + user.get("email") + " with " + appName + "\n\n" +
"" +
"Click here to confirm it:\n" + link;
let to = user.get("email");
Expand Down
69 changes: 34 additions & 35 deletions src/ParseServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,40 @@ var batch = require('./batch'),
Parse = require('parse/node').Parse,
authDataManager = require('./authDataManager');

//import passwordReset from './passwordReset';
import cache from './cache';
import Config from './Config';
import parseServerPackage from '../package.json';
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
import PromiseRouter from './PromiseRouter';
import requiredParameter from './requiredParameter';
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
import { ClassesRouter } from './Routers/ClassesRouter';
import { FeaturesRouter } from './Routers/FeaturesRouter';
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
import { FilesController } from './Controllers/FilesController';
import { FilesRouter } from './Routers/FilesRouter';
import { FunctionsRouter } from './Routers/FunctionsRouter';
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
import { HooksController } from './Controllers/HooksController';
import { HooksRouter } from './Routers/HooksRouter';
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
import { InstallationsRouter } from './Routers/InstallationsRouter';
import { loadAdapter } from './Adapters/AdapterLoader';
import { LiveQueryController } from './Controllers/LiveQueryController';
import { LoggerController } from './Controllers/LoggerController';
import { LogsRouter } from './Routers/LogsRouter';
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
import { PushController } from './Controllers/PushController';
import { PushRouter } from './Routers/PushRouter';
import { randomString } from './cryptoUtils';
import { RolesRouter } from './Routers/RolesRouter';
import { SchemasRouter } from './Routers/SchemasRouter';
import { SessionsRouter } from './Routers/SessionsRouter';
import { setFeature } from './features';
import { UserController } from './Controllers/UserController';
import { UsersRouter } from './Routers/UsersRouter';
import cache from './cache';
import Config from './Config';
import parseServerPackage from '../package.json';
import ParsePushAdapter from './Adapters/Push/ParsePushAdapter';
import PromiseRouter from './PromiseRouter';
import requiredParameter from './requiredParameter';
import { AnalyticsRouter } from './Routers/AnalyticsRouter';
import { ClassesRouter } from './Routers/ClassesRouter';
import { FeaturesRouter } from './Routers/FeaturesRouter';
import { FileLoggerAdapter } from './Adapters/Logger/FileLoggerAdapter';
import { FilesController } from './Controllers/FilesController';
import { FilesRouter } from './Routers/FilesRouter';
import { FunctionsRouter } from './Routers/FunctionsRouter';
import { GlobalConfigRouter } from './Routers/GlobalConfigRouter';
import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter';
import { HooksController } from './Controllers/HooksController';
import { HooksRouter } from './Routers/HooksRouter';
import { IAPValidationRouter } from './Routers/IAPValidationRouter';
import { InstallationsRouter } from './Routers/InstallationsRouter';
import { loadAdapter } from './Adapters/AdapterLoader';
import { LiveQueryController } from './Controllers/LiveQueryController';
import { LoggerController } from './Controllers/LoggerController';
import { LogsRouter } from './Routers/LogsRouter';
import { ParseLiveQueryServer } from './LiveQuery/ParseLiveQueryServer';
import { PublicAPIRouter } from './Routers/PublicAPIRouter';
import { PushController } from './Controllers/PushController';
import { PushRouter } from './Routers/PushRouter';
import { randomString } from './cryptoUtils';
import { RolesRouter } from './Routers/RolesRouter';
import { SchemasRouter } from './Routers/SchemasRouter';
import { SessionsRouter } from './Routers/SessionsRouter';
import { setFeature } from './features';
import { UserController } from './Controllers/UserController';
import { UsersRouter } from './Routers/UsersRouter';

// Mutate the Parse object to add the Cloud Code handlers
addParseCloud();
Expand Down
8 changes: 4 additions & 4 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import ParseServer from './ParseServer'
import { GCSAdapter } from 'parse-server-gcs-adapter';
import { S3Adapter } from 'parse-server-s3-adapter';
import { FileSystemAdapter } from 'parse-server-fs-adapter';
import ParseServer from './ParseServer';
import { GCSAdapter } from 'parse-server-gcs-adapter';
import { S3Adapter } from 'parse-server-s3-adapter';
import { FileSystemAdapter } from 'parse-server-fs-adapter';

// Factory function
let _ParseServer = function(options) {
Expand Down