diff --git a/src/controllers/integration.ts b/src/controllers/integration.ts
index 262325b..f252342 100644
--- a/src/controllers/integration.ts
+++ b/src/controllers/integration.ts
@@ -47,7 +47,7 @@ export const initializeIntegration: Middleware = async ctx => {
await sendMail({
from: config.emailSender,
to: email,
- subject: 'TODO',
+ subject: 'Verify your email for sleepy.bike notifications',
html: `Please verify your email click here`,
text: `Please verify your email ${emailVerificationLink}`,
})
@@ -103,12 +103,18 @@ export const finishIntegration: Middleware = async ctx => {
// save the integration to database
await Integration.create(integrationData)
- // subscribe to the inbox' webhook notifications
- await subscribeForNotifications(integrationData.inbox)
-
- ctx.response.body =
- 'Email notifications have been successfully integrated to your inbox'
- ctx.response.status = 200
+ try {
+ // subscribe to the inbox' webhook notifications
+ await subscribeForNotifications(integrationData.inbox)
+ ctx.response.body =
+ 'Email notifications have been successfully integrated to your inbox'
+ } catch (e) {
+ ctx.response.body =
+ "Email was successfully verified, but notifications won't work, yet. It looks like your Solid Pod doesn't support notifications. We'll implement a workaround in the future.\nError: " +
+ (e as Error).message
+ } finally {
+ ctx.response.status = 200
+ }
}
type Fetch = typeof fetch
diff --git a/src/test/css-config-no-notifications.json b/src/test/css-config-no-notifications.json
new file mode 100644
index 0000000..17c089e
--- /dev/null
+++ b/src/test/css-config-no-notifications.json
@@ -0,0 +1,41 @@
+{
+ "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^6.0.0/components/context.jsonld",
+ "import": [
+ "css:config/app/main/default.json",
+ "css:config/app/init/initialize-prefilled-root.json",
+ "css:config/app/setup/optional.json",
+ "css:config/app/variables/default.json",
+ "css:config/http/handler/default.json",
+ "css:config/http/middleware/default.json",
+ "css:config/http/notifications/disabled.json",
+ "css:config/http/server-factory/http.json",
+ "css:config/http/static/default.json",
+ "css:config/identity/access/public.json",
+ "css:config/identity/email/default.json",
+ "css:config/identity/handler/default.json",
+ "css:config/identity/ownership/token.json",
+ "css:config/identity/pod/static.json",
+ "css:config/identity/registration/enabled.json",
+ "css:config/ldp/authentication/dpop-bearer.json",
+ "css:config/ldp/authorization/webacl.json",
+ "css:config/ldp/handler/default.json",
+ "css:config/ldp/metadata-parser/default.json",
+ "css:config/ldp/metadata-writer/default.json",
+ "css:config/ldp/modes/default.json",
+ "css:config/storage/backend/memory.json",
+ "css:config/storage/key-value/resource-store.json",
+ "css:config/storage/middleware/default.json",
+ "css:config/util/auxiliary/acl.json",
+ "css:config/util/identifiers/suffix.json",
+ "css:config/util/index/default.json",
+ "css:config/util/logging/winston.json",
+ "css:config/util/representation-conversion/default.json",
+ "css:config/util/resource-locker/memory.json",
+ "css:config/util/variables/default.json"
+ ],
+ "@graph": [
+ {
+ "comment": "A Solid server that stores its resources in memory and uses WAC for authorization."
+ }
+ ]
+}
diff --git a/src/test/integration-finish.spec.ts b/src/test/integration-finish.spec.ts
index 33ccc7b..8bdb6d9 100644
--- a/src/test/integration-finish.spec.ts
+++ b/src/test/integration-finish.spec.ts
@@ -6,7 +6,12 @@ import Mail from 'nodemailer/lib/mailer'
import { SinonSandbox, SinonSpy, createSandbox } from 'sinon'
import { baseUrl } from '../config'
import * as mailerService from '../services/mailerService'
-import { authenticatedFetch, person } from './testSetup.spec'
+import {
+ authenticatedFetch,
+ authenticatedFetchNoNotifications,
+ person,
+ personNoNotifications,
+} from './testSetup.spec'
describe('email verification via /verify-email?id=webId&token=base64Token', () => {
let sendMailSpy: SinonSpy<[options: Mail.Options], Promise>
@@ -85,4 +90,39 @@ describe('email verification via /verify-email?id=webId&token=base64Token', () =
})
it('when we send out multiple verification emails, the last link should work')
+
+ context("server doesn't support webhook notifications", () => {
+ beforeEach(async () => {
+ // initialize the integration
+ const initResponse = await authenticatedFetchNoNotifications(
+ `${baseUrl}/inbox`,
+ {
+ method: 'post',
+ headers: {
+ 'content-type':
+ 'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
+ },
+ body: JSON.stringify({
+ '@context': 'https://www.w3.org/ns/activitystreams',
+ '@id': '',
+ '@type': 'Add',
+ actor: personNoNotifications.webId,
+ object: personNoNotifications.podUrl + 'profile/card',
+ target: 'email@example.com',
+ }),
+ },
+ )
+
+ expect(initResponse.status).to.equal(200)
+ // email was sent
+ const emailMessage = sendMailSpy.secondCall.firstArg.html
+ const $ = cheerio.load(emailMessage)
+ verificationLink = $('a').first().attr('href') as string
+ expect(verificationLink).to.not.be.null
+ })
+ it("should verify email, but inform user that notifications aren't supported", async () => {
+ const response = await fetch(verificationLink)
+ expect(response.status).to.equal(200)
+ })
+ })
})
diff --git a/src/test/testSetup.spec.ts b/src/test/testSetup.spec.ts
index a2750cc..05ca329 100644
--- a/src/test/testSetup.spec.ts
+++ b/src/test/testSetup.spec.ts
@@ -8,6 +8,7 @@ import { createRandomAccount, getAuthenticatedFetch } from '../helpers'
let server: Server
let authenticatedFetch: typeof fetch
+let authenticatedFetchNoNotifications: typeof fetch
let person: {
idp: string
podUrl: string
@@ -16,7 +17,16 @@ let person: {
password: string
email: string
}
+let personNoNotifications: {
+ idp: string
+ podUrl: string
+ webId: string
+ username: string
+ password: string
+ email: string
+}
let cssServer: css.App
+let cssServerNoNotifications: css.App
before(async function () {
this.timeout(60000)
@@ -51,6 +61,39 @@ after(async () => {
await cssServer.stop()
})
+before(async function () {
+ this.timeout(60000)
+ const start = Date.now()
+
+ // eslint-disable-next-line no-console
+ console.log('Starting CSS server without notifications')
+ // Community Solid Server (CSS) set up following example in https://github.com/CommunitySolidServer/hello-world-component/blob/main/test/integration/Server.test.ts
+ cssServerNoNotifications = await new css.AppRunner().create(
+ {
+ mainModulePath: css.joinFilePath(__dirname, '../../'), // ?
+ typeChecking: false, // ?
+ dumpErrorState: false, // disable CSS error dump
+ },
+ css.joinFilePath(__dirname, './css-config-no-notifications.json'), // CSS config
+ {},
+ // CSS cli options
+ // https://github.com/CommunitySolidServer/CommunitySolidServer/tree/main#-parameters
+ {
+ port: 3457,
+ loggingLevel: 'off',
+ // seededPodConfigJson: css.joinFilePath(__dirname, './css-pod-seed.json'), // set up some Solid accounts
+ },
+ )
+ await cssServerNoNotifications.start()
+
+ // eslint-disable-next-line no-console
+ console.log('CSS server started in', (Date.now() - start) / 1000, 'seconds')
+})
+
+after(async () => {
+ await cssServerNoNotifications.stop()
+})
+
before(done => {
server = app.listen(port, done)
})
@@ -89,4 +132,23 @@ beforeEach(async () => {
})
})
-export { authenticatedFetch, cssServer, person, server }
+beforeEach(async () => {
+ personNoNotifications = await createRandomAccount({
+ solidServer: 'http://localhost:3457',
+ })
+ authenticatedFetchNoNotifications = await getAuthenticatedFetch({
+ email: personNoNotifications.email,
+ password: personNoNotifications.password,
+ solidServer: 'http://localhost:3457',
+ })
+})
+
+export {
+ authenticatedFetch,
+ authenticatedFetchNoNotifications,
+ cssServer,
+ cssServerNoNotifications,
+ person,
+ personNoNotifications,
+ server,
+}