Compare commits

...

2 Commits

Author SHA1 Message Date
Nan Yu 8260f973e2 wip 2020-10-17 16:54:45 -07:00
Nan Yu 044a920e38 add some more hooks to unfurls 2020-10-17 15:19:29 -07:00
2 changed files with 95 additions and 46 deletions
+23 -28
View File
@@ -1,5 +1,3 @@
<p align="center">
<img src="https://user-images.githubusercontent.com/31465/34380645-bd67f474-eb0b-11e7-8d03-0151c1730654.png" height="29" />
</p>
@@ -29,7 +27,6 @@ Outline requires the following dependencies:
- AWS S3 bucket or compatible API for file storage
- Slack or Google developer application for authentication
### Production
For a manual self-hosted production installation these are the suggested steps:
@@ -37,44 +34,42 @@ For a manual self-hosted production installation these are the suggested steps:
1. Clone this repo and install dependencies with `yarn install`
1. Build the source code with `yarn build`
1. Using the `.env.sample` as a reference, set the required variables in your production environment. The following are required as a minimum:
1. `SECRET_KEY` (follow instructions in the comments at the top of `.env`)
1. `SLACK_KEY` (this is called "Client ID" in Slack admin)
1. `SLACK_SECRET` (this is called "Client Secret" in Slack admin)
1. `DATABASE_URL` (run your own local copy of Postgres, or use a cloud service)
1. `REDIS_URL` (run your own local copy of Redis, or use a cloud service)
1. `URL` (the public facing URL of your installation)
1. `AWS_` (all of the keys beginning with AWS)
1. `SECRET_KEY` (follow instructions in the comments at the top of `.env`)
1. `SLACK_KEY` (this is called "Client ID" in Slack admin)
1. `SLACK_SECRET` (this is called "Client Secret" in Slack admin)
1. `DATABASE_URL` (run your own local copy of Postgres, or use a cloud service)
1. `REDIS_URL` (run your own local copy of Redis, or use a cloud service)
1. `URL` (the public facing URL of your installation)
1. `AWS_` (all of the keys beginning with AWS)
1. Migrate database schema with `yarn sequelize:migrate`. Production assumes an SSL connection, if
Postgres is on the same machine and is not SSL you can migrate with `yarn sequelize:migrate --env=production-ssl-disabled`.
1. Start the service with any daemon tools you prefer. Take PM2 for example, `NODE_ENV=production pm2 start ./build/server/index.js --name outline `
Postgres is on the same machine and is not SSL you can migrate with `yarn sequelize:migrate --env=production-ssl-disabled`.
1. Start the service with any daemon tools you prefer. Take PM2 for example, `NODE_ENV=production pm2 start ./build/server/index.js --name outline`
1. Visit http://you_server_ip:3000 and you should be able to see Outline page
> Port number can be changed using the `PORT` environment variable
1. (Optional) You can add an `nginx` reverse proxy to serve your instance of Outline for a clean URL without the port number, support SSL, etc.
### Development
In development you can quickly get an environment running using Docker by following these steps:
1. Install these dependencies if you don't already have them
1. [Docker for Desktop](https://www.docker.com)
1. [Node.js](https://nodejs.org/) (v12 LTS preferred)
1. [Yarn](https://yarnpkg.com)
1. [Docker for Desktop](https://www.docker.com)
1. [Node.js](https://nodejs.org/) (v12 LTS preferred)
1. [Yarn](https://yarnpkg.com)
1. Clone this repo
1. Register a Slack app at https://api.slack.com/apps
1. Copy the file `.env.sample` to `.env`
1. Fill out the following fields:
1. `SECRET_KEY` (follow instructions in the comments at the top of `.env`)
1. `SLACK_KEY` (this is called "Client ID" in Slack admin)
1. `SLACK_SECRET` (this is called "Client Secret" in Slack admin)
1. Configure your Slack app's Oauth & Permissions settings
1. Add `http://localhost:3000/auth/slack.callback` as an Oauth redirect URL
1. Ensure that the bot token scope contains at least `users:read`
1. `SECRET_KEY` (follow instructions in the comments at the top of `.env`)
1. `SLACK_KEY` (this is called "Client ID" in Slack admin)
1. `SLACK_SECRET` (this is called "Client Secret" in Slack admin)
1. Configure your Slack app's Oauth & Permissions settings
1. Add `http://localhost:3000/auth/slack.callback` as an Oauth redirect URL. If you plan to work on the Slack integrations, add `http://localhost:3000/auth/slack.commands`, and `http://localhost:3000/auth/slack.post` as well.
1. Ensure that the bot token scope contains at least `users:read`. If you plan to work on Slack integrations, add `chat:write`, `links:read`, `links:write` as well.
1. Run `make up`. This will download dependencies, build and launch a development version of Outline
## Development
### Server
@@ -123,7 +118,7 @@ Backend is driven by [Koa](http://koajs.com/) (API, web server), [Sequelize](htt
- `server/api` - API endpoints
- `server/commands` - Domain logic, currently being refactored from /models
- `server/emails` - React rendered email templates
- `server/emails` - React rendered email templates
- `server/models` - Database models
- `server/policies` - Authorization logic
- `server/presenters` - API responses for database models
@@ -156,10 +151,10 @@ However, before working on a pull request please let the core team know by creat
If youre looking for ways to get started, here's a list of ways to help us improve Outline:
* Issues with [`good first issue`](https://github.com/outline/outline/labels/good%20first%20issue) label
* Performance improvements, both on server and frontend
* Developer happiness and documentation
* Bugs and other issues listed on GitHub
- Issues with [`good first issue`](https://github.com/outline/outline/labels/good%20first%20issue) label
- Performance improvements, both on server and frontend
- Developer happiness and documentation
- Bugs and other issues listed on GitHub
## License
+72 -18
View File
@@ -15,6 +15,7 @@ import * as Slack from "../slack";
const router = new Router();
// triggered by a user posting a getoutline.com link in Slack
// TODO this is not really semantically correct because it's the endpoitn for every event hook, not just unfurl
router.post("hooks.unfurl", async (ctx) => {
const { challenge, token, event } = ctx.body;
if (challenge) return (ctx.body = ctx.body.challenge);
@@ -33,26 +34,79 @@ router.post("hooks.unfurl", async (ctx) => {
});
if (!auth) return;
// get content for unfurled links
let unfurls = {};
for (let link of event.links) {
const id = link.url.substr(link.url.lastIndexOf("/") + 1);
const doc = await Document.findByPk(id);
if (!doc || doc.teamId !== user.teamId) continue;
switch (event.type) {
// handles link unfurl when a link is shared (see https://api.slack.com/reference/messaging/link-unfurling)
// and also adds backlinks to the document
//TODO errors seem to get swallowed
case "link_shared": {
let unfurls = {};
for (let link of event.links) {
// TODO needs to handle share link URLs too
const id = link.url.substr(link.url.lastIndexOf("/") + 1);
const doc = await Document.findByPk(id);
unfurls[link.url] = {
title: doc.title,
text: doc.getSummary(),
color: doc.collection.color,
};
if (!doc || doc.teamId !== user.teamId) continue;
unfurls[link.url] = {
title: doc.title,
text: doc.getSummary(),
color: doc.collection.color,
};
}
// respond to slack with unfurl data
await Slack.post("chat.unfurl", {
token: auth.token,
channel: event.channel,
ts: event.message_ts,
unfurls,
});
// get the permalink and message contents to construct a backlink
// TODO test with private messages, threads and private channels
await Slack.post("chat.unfurl", {
token: auth.token,
channel: event.channel,
ts: event.message_ts,
unfurls,
});
try {
const { permalink } = await Slack.request("chat.getPermalink", {
token: auth.token,
channel: event.channel,
message_ts: event.message_ts,
});
const { messages } = await Slack.request("conversations.history", {
token: auth.token,
channel: event.channel,
latest: event.message_ts,
limit: 1,
inclusive: true,
});
const { user } = await Slack.request("users.info", {
token: auth.token,
user: messages[0].user,
});
console.warn({ event, permalink, messages, user });
console.log(
`${user["real_name"]} shared this document on Slack at ${messages[0].ts} with the message ${messages[0].text}`
);
} catch (e) {
// TODO: log 4xx errors and re-throw (debug module) expected for private chanells for right now
console.log({ e });
}
break;
}
default: {
console.warn(`unhandled event type #{event.type}`);
}
}
await Slack.post("chat.unfurl", {
token: auth.token,
channel: event.channel,
ts: event.message_ts,
unfurls,
});
});
// triggered by interactions with actions, dialogs, message buttons in Slack