mirror of
https://github.com/wassname/talk.git
synced 2026-09-13 13:10:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64800ffaee | ||
|
|
637605a002 | ||
|
|
5580e14bf3 | ||
|
|
109d9e93f5 | ||
|
|
ff72d79748 | ||
|
|
0645735d2b | ||
|
|
f1a0febd6c | ||
|
|
16d0b39ebc | ||
|
|
66c7430ff1 | ||
|
|
ac06f0d13b | ||
|
|
ca10062498 | ||
|
|
c9381c6367 | ||
|
|
13853ef87e | ||
|
|
fb2f36d0ee | ||
|
|
1a2fa73941 | ||
|
|
d3931db285 | ||
|
|
093202f9e2 | ||
|
|
60be682a5f | ||
|
|
41c9ae32b1 | ||
|
|
4445479237 | ||
|
|
aab44587a6 | ||
|
|
0af28edbd9 | ||
|
|
9db7571fe2 | ||
|
|
683adceec4 | ||
|
|
aa6058e9d1 | ||
|
|
a4c4032b0d | ||
|
|
2ea0d51613 | ||
|
|
f2564f4eda | ||
|
|
73040b1314 | ||
|
|
c3c106c7b0 | ||
|
|
8faf69ce48 |
+25
-27
@@ -1,4 +1,3 @@
|
||||
|
||||
# job_environment will setup the environment for any job being executed.
|
||||
job_environment: &job_environment
|
||||
NODE_ENV: test
|
||||
@@ -54,7 +53,6 @@ integration_job: &integration_job
|
||||
when: always
|
||||
path: /tmp/circleci-test-results
|
||||
|
||||
|
||||
version: 2
|
||||
jobs:
|
||||
# npm_dependencies will install the dependencies used by all other steps.
|
||||
@@ -223,20 +221,17 @@ jobs:
|
||||
# only execute on a deploy related job.
|
||||
filter_deploy: &filter_deploy
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- next
|
||||
tags:
|
||||
only: /v[0-9]+(\.[0-9]+)*/
|
||||
branches:
|
||||
ignore: /.*/
|
||||
|
||||
# filter_develop will add the filters for a development related commit.
|
||||
filter_develop: &filter_develop
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- master
|
||||
- next
|
||||
- /release\/.*/
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
@@ -258,10 +253,11 @@ workflows:
|
||||
<<: *filter_develop
|
||||
requires:
|
||||
- npm_dependencies
|
||||
- test_integration_chrome_local:
|
||||
<<: *filter_develop
|
||||
requires:
|
||||
- build_assets
|
||||
# TODO: uncomment when we revisit browserstack
|
||||
# - test_integration_chrome_local:
|
||||
# <<: *filter_develop
|
||||
# requires:
|
||||
# - build_assets
|
||||
# TODO: uncomment when more reliable
|
||||
# - test_integration_firefox_local:
|
||||
# <<: *filter_develop
|
||||
@@ -283,18 +279,19 @@ workflows:
|
||||
<<: *filter_deploy
|
||||
requires:
|
||||
- npm_dependencies
|
||||
- test_integration_chrome:
|
||||
<<: *filter_deploy
|
||||
requires:
|
||||
- build_assets
|
||||
- test_integration_firefox:
|
||||
<<: *filter_deploy
|
||||
requires:
|
||||
- build_assets
|
||||
- test_integration_edge:
|
||||
<<: *filter_deploy
|
||||
requires:
|
||||
- build_assets
|
||||
# TODO: uncomment when we revisit browserstack
|
||||
# - test_integration_chrome:
|
||||
# <<: *filter_deploy
|
||||
# requires:
|
||||
# - build_assets
|
||||
# - test_integration_firefox:
|
||||
# <<: *filter_deploy
|
||||
# requires:
|
||||
# - build_assets
|
||||
# - test_integration_edge:
|
||||
# <<: *filter_deploy
|
||||
# requires:
|
||||
# - build_assets
|
||||
# TODO: uncomment when more reliable
|
||||
# - test_integration_ie:
|
||||
# <<: *filter_deploy
|
||||
@@ -309,9 +306,10 @@ workflows:
|
||||
requires:
|
||||
- lint
|
||||
- test_unit
|
||||
- test_integration_chrome
|
||||
- test_integration_firefox
|
||||
- test_integration_edge
|
||||
# TODO: uncomment when we revisit browserstack
|
||||
# - test_integration_chrome
|
||||
# - test_integration_firefox
|
||||
# - test_integration_edge
|
||||
# TODO: uncomment when more reliable
|
||||
# - test_integration_ie
|
||||
# - test_integration_safari
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright 2018 Mozilla Foundation
|
||||
Copyright 2019 Vox Media, Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Talk · [](https://circleci.com/gh/coralproject/talk) · [](CONTRIBUTING.md#pull-requests)
|
||||
|
||||
---
|
||||
|
||||
> :construction: **NOTE:** We're currently building v5 of this platform, check it out in our [next branch](https://github.com/coralproject/talk/tree/next) :construction_worker_man: :construction_worker_woman:
|
||||
|
||||
---
|
||||
|
||||
Online comments are broken. Our open-source commenting platform, Talk, rethinks how moderation, comment display, and conversation function, creating the opportunity for safer, smarter discussions around your work. [Read more about Talk here](https://coralproject.net/talk).
|
||||
|
||||
Built with <3 by The Coral Project, a part of [Vox Media](https://www.voxmedia.com/).
|
||||
|
||||
@@ -11,7 +11,12 @@ const { HELMET_CONFIGURATION } = require('./config');
|
||||
const { MOUNT_PATH } = require('./url');
|
||||
const routes = require('./routes');
|
||||
const debug = require('debug')('talk:app');
|
||||
const { ENABLE_TRACING, APOLLO_ENGINE_KEY, PORT } = require('./config');
|
||||
const {
|
||||
ENABLE_TRACING,
|
||||
APOLLO_ENGINE_KEY,
|
||||
PORT,
|
||||
TRUST_PROXY,
|
||||
} = require('./config');
|
||||
|
||||
const app = express();
|
||||
|
||||
@@ -58,7 +63,26 @@ if (ENABLE_TRACING && APOLLO_ENGINE_KEY) {
|
||||
|
||||
// Trust the first proxy in front of us, this will enable us to trust the fact
|
||||
// that SSL was terminated correctly.
|
||||
app.set('trust proxy', 1);
|
||||
app.set(
|
||||
'trust proxy',
|
||||
(function() {
|
||||
if (!TRUST_PROXY) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const lowercase = TRUST_PROXY.toLowerCase();
|
||||
if (lowercase === 'true' || lowercase === 'false') {
|
||||
return lowercase === 'true';
|
||||
}
|
||||
|
||||
const parsed = Number(TRUST_PROXY);
|
||||
if (!isNaN(parsed)) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
return TRUST_PROXY;
|
||||
})()
|
||||
);
|
||||
|
||||
// Enable a suite of security good practices through helmet. We disable
|
||||
// frameguard to allow crossdomain injection of the embed.
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import LinkifyIt from 'linkify-it';
|
||||
import tlds from 'tlds';
|
||||
|
||||
export function createLinkify() {
|
||||
const linkify = new LinkifyIt();
|
||||
linkify.tlds(tlds);
|
||||
return linkify;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class EmbedContainer extends React.Component {
|
||||
},
|
||||
}
|
||||
) => {
|
||||
notify('info', t('your_username_has_been_rejected'));
|
||||
notify('info', t('your_username_has_been_rejected_not_in_line'));
|
||||
props.updateStatus(state.status);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -48,7 +48,7 @@ class ChangeUsername extends Component {
|
||||
return (
|
||||
<RestrictedMessageBox>
|
||||
<div className="talk-change-username">
|
||||
<span>{t('framework.edit_name.msg')}</span>
|
||||
<span>{t('framework.edit_name.rejected')}</span>
|
||||
<div className={styles.alert}>{alert}</div>
|
||||
<label htmlFor="username" className="screen-reader-text">
|
||||
{t('framework.edit_name.label')}
|
||||
|
||||
+1
-7
@@ -7,7 +7,6 @@ import { createReduxEmitter } from './events';
|
||||
import { createRestClient } from './rest';
|
||||
import thunk from 'redux-thunk';
|
||||
import { loadTranslations } from './i18n';
|
||||
import bowser from 'bowser';
|
||||
import noop from 'lodash/noop';
|
||||
import { BASE_PATH } from 'coral-framework/constants/url';
|
||||
import { createPluginsService } from './plugins';
|
||||
@@ -65,12 +64,7 @@ const getAuthToken = (store, storage) => {
|
||||
}
|
||||
|
||||
return token;
|
||||
} else if (
|
||||
!bowser.safari &&
|
||||
!bowser.ios &&
|
||||
storage &&
|
||||
storage.getItem('token')
|
||||
) {
|
||||
} else if (storage && storage.getItem('token')) {
|
||||
// Use local storage auth tokens where there's a stable api.
|
||||
return storage.getItem('token');
|
||||
}
|
||||
|
||||
@@ -85,6 +85,9 @@ const CONFIG = {
|
||||
// as report CSP violations.
|
||||
ENABLE_STRICT_CSP: process.env.TALK_ENABLE_STRICT_CSP === 'TRUE',
|
||||
|
||||
// TRUST_PROXY allows control over the `trust proxy` configuration on express.
|
||||
TRUST_PROXY: process.env.TALK_TRUST_PROXY || '1',
|
||||
|
||||
// LOGGING_LEVEL specifies the logging level used by the bunyan logger.
|
||||
LOGGING_LEVEL: ['fatal', 'error', 'warn', 'info', 'debug', 'trace'].includes(
|
||||
process.env.TALK_LOGGING_LEVEL
|
||||
|
||||
+134
-106
@@ -6,7 +6,7 @@
|
||||
title: Talk Documentation
|
||||
subtitle:
|
||||
description: >
|
||||
Documentation and guides for Talk from The Coral Project.
|
||||
Documentation and guides for Coral by Vox Media
|
||||
google_analytics: UA-73335347-5
|
||||
author:
|
||||
language: en
|
||||
@@ -47,7 +47,7 @@ highlight:
|
||||
# per_page: Posts displayed per page. (0 = disable pagination)
|
||||
# order_by: Posts order. (Order by date descending by default)
|
||||
index_generator:
|
||||
path: ''
|
||||
path: ""
|
||||
|
||||
# Category & Tag
|
||||
default_category: uncategorized
|
||||
@@ -78,112 +78,140 @@ sidebar:
|
||||
- title: Docker
|
||||
url: https://hub.docker.com/r/coralproject/talk/
|
||||
side:
|
||||
- title: Installation
|
||||
- title: Version 5
|
||||
children:
|
||||
- title: Talk Quickstart
|
||||
url: /
|
||||
- title: Installation from Docker
|
||||
url: /installation-from-docker/
|
||||
- title: Installation from Source
|
||||
url: /installation-from-source/
|
||||
- title: Planning your Talk Architecture
|
||||
url: /planning-architecture/
|
||||
- title: Pre-Launch Checklist
|
||||
url: /pre-launch-checklist/
|
||||
- title: Configuration
|
||||
- title: Getting Started
|
||||
children:
|
||||
- title: Installing
|
||||
url: /
|
||||
- title: Configuration
|
||||
url: /v5/configuration/
|
||||
- title: Developing
|
||||
url: /v5/developing/
|
||||
- title: Integration
|
||||
children:
|
||||
- title: CMS Integration
|
||||
url: /v5/integrating/cms/
|
||||
- title: Single Sign On
|
||||
url: /v5/integrating/sso/
|
||||
- title: GDPR
|
||||
url: /v5/integrating/gdpr/
|
||||
- title: Comment Count
|
||||
url: /v5/integrating/counts/
|
||||
- title: Slack
|
||||
url: /v5/integrating/slack/
|
||||
- title: API
|
||||
children:
|
||||
- title: GraphQL Overview
|
||||
url: /v5/api/overview/
|
||||
- title: Version 4
|
||||
children:
|
||||
- title: Required Configuration
|
||||
url: /configuration/
|
||||
- title: Advanced Configuration
|
||||
url: /advanced-configuration/
|
||||
- title: Configuration with CLI tools
|
||||
url: /configuration-cli-tools/
|
||||
- title: Integrating
|
||||
children:
|
||||
- title: Authentication
|
||||
url: /integrating/authentication/
|
||||
- title: CMS Integration
|
||||
url: /integrating/cms-integration/
|
||||
- title: Asset Scraping
|
||||
url: /integrating/asset-scraping/
|
||||
- title: Configuring the Comment Stream
|
||||
url: /integrating/configuring-comment-stream/
|
||||
- title: Configuring the Admin
|
||||
url: /integrating/configuring-admin/
|
||||
- title: Notifications
|
||||
url: /integrating/notifications/
|
||||
- title: Event Tracking and Metrics
|
||||
url: /integrating/event-tracking-metrics/
|
||||
- title: Styling and CSS
|
||||
url: /integrating/styling-css/
|
||||
- title: Translations and i18n
|
||||
url: /integrating/translations-i18n/
|
||||
- title: GDPR Compliance
|
||||
url: /integrating/gdpr/
|
||||
- title: Accelerated Mobile Page
|
||||
url: /integrating/amp/
|
||||
- title: Product Guide
|
||||
children:
|
||||
- title: How Talk Works
|
||||
url: /how-talk-works/
|
||||
- title: Commenter Features
|
||||
url: /commenter-features/
|
||||
- title: Moderator Features
|
||||
url: /moderator-features/
|
||||
- title: User Roles in Talk
|
||||
url: /roles/
|
||||
- title: Trust
|
||||
url: /trust/
|
||||
- title: Toxic Comments
|
||||
url: /toxic-comments/
|
||||
- title: Configuring Talk
|
||||
url: /configuring-talk/
|
||||
- title: Plugins
|
||||
children:
|
||||
- title: Plugins Overview
|
||||
url: /plugins/
|
||||
- title: Plugin Directory
|
||||
url: /plugins-directory/
|
||||
- title: Plugin Recipes
|
||||
url: /plugin-recipes/
|
||||
- title: API
|
||||
children:
|
||||
- title: GraphQL Overview
|
||||
url: /api/overview/
|
||||
- title: GraphQL Reference
|
||||
url: /api/graphql/
|
||||
- title: Server Plugin API
|
||||
url: /api/server/
|
||||
- title: Client Plugin API
|
||||
url: /api/client/
|
||||
- title: Plugin Slots API
|
||||
url: /api/slots/
|
||||
- title: Tutorials
|
||||
children:
|
||||
- title: Creating a Basic Plugin
|
||||
url: /building-basic-plugin/
|
||||
- title: Customizing Plugins with Coral UI
|
||||
url: /customizing-plugins-coral-ui/
|
||||
- title: When You've Installed Talk
|
||||
url: /when-youve-installed-talk/
|
||||
- title: Embedding Talk in Native Mobile Apps
|
||||
url: /embedding-in-native-mobile-apps/
|
||||
- title: Migrating
|
||||
children:
|
||||
- title: Migrating from v3.x.x
|
||||
url: /migration/3/
|
||||
- title: Migrating to v4.0.0
|
||||
url: /migration/4/
|
||||
- title: Migrating to v4.1.0
|
||||
url: /migration/4.1/
|
||||
- title: FAQ & Troubleshooting
|
||||
children:
|
||||
- title: FAQ
|
||||
url: /faq/
|
||||
- title: Troubleshooting Tips
|
||||
url: /troubleshooting-tips/
|
||||
- title: Contact
|
||||
url: /contact/
|
||||
- title: Installation
|
||||
children:
|
||||
- title: Talk Quickstart
|
||||
url: /installation-quickstart
|
||||
- title: Installation from Docker
|
||||
url: /installation-from-docker/
|
||||
- title: Installation from Source
|
||||
url: /installation-from-source/
|
||||
- title: Planning your Talk Architecture
|
||||
url: /planning-architecture/
|
||||
- title: Pre-Launch Checklist
|
||||
url: /pre-launch-checklist/
|
||||
- title: Configuration
|
||||
children:
|
||||
- title: Required Configuration
|
||||
url: /configuration/
|
||||
- title: Advanced Configuration
|
||||
url: /advanced-configuration/
|
||||
- title: Configuration with CLI tools
|
||||
url: /configuration-cli-tools/
|
||||
- title: Integrating
|
||||
children:
|
||||
- title: Authentication
|
||||
url: /integrating/authentication/
|
||||
- title: CMS Integration
|
||||
url: /integrating/cms-integration/
|
||||
- title: Asset Scraping
|
||||
url: /integrating/asset-scraping/
|
||||
- title: Configuring the Comment Stream
|
||||
url: /integrating/configuring-comment-stream/
|
||||
- title: Configuring the Admin
|
||||
url: /integrating/configuring-admin/
|
||||
- title: Notifications
|
||||
url: /integrating/notifications/
|
||||
- title: Event Tracking and Metrics
|
||||
url: /integrating/event-tracking-metrics/
|
||||
- title: Styling and CSS
|
||||
url: /integrating/styling-css/
|
||||
- title: Translations and i18n
|
||||
url: /integrating/translations-i18n/
|
||||
- title: GDPR Compliance
|
||||
url: /integrating/gdpr/
|
||||
- title: Accelerated Mobile Page
|
||||
url: /integrating/amp/
|
||||
- title: Product Guide
|
||||
children:
|
||||
- title: How Talk Works
|
||||
url: /how-talk-works/
|
||||
- title: Commenter Features
|
||||
url: /commenter-features/
|
||||
- title: Moderator Features
|
||||
url: /moderator-features/
|
||||
- title: User Roles in Talk
|
||||
url: /roles/
|
||||
- title: Trust
|
||||
url: /trust/
|
||||
- title: Toxic Comments
|
||||
url: /toxic-comments/
|
||||
- title: Configuring Talk
|
||||
url: /configuring-talk/
|
||||
- title: Plugins
|
||||
children:
|
||||
- title: Plugins Overview
|
||||
url: /plugins/
|
||||
- title: Plugin Directory
|
||||
url: /plugins-directory/
|
||||
- title: Plugin Recipes
|
||||
url: /plugin-recipes/
|
||||
- title: API
|
||||
children:
|
||||
- title: GraphQL Overview
|
||||
url: /api/overview/
|
||||
- title: GraphQL Reference
|
||||
url: /api/graphql/
|
||||
- title: Server Plugin API
|
||||
url: /api/server/
|
||||
- title: Client Plugin API
|
||||
url: /api/client/
|
||||
- title: Plugin Slots API
|
||||
url: /api/slots/
|
||||
- title: Tutorials
|
||||
children:
|
||||
- title: Creating a Basic Plugin
|
||||
url: /building-basic-plugin/
|
||||
- title: Customizing Plugins with Coral UI
|
||||
url: /customizing-plugins-coral-ui/
|
||||
- title: When You've Installed Talk
|
||||
url: /when-youve-installed-talk/
|
||||
- title: Embedding Talk in Native Mobile Apps
|
||||
url: /embedding-in-native-mobile-apps/
|
||||
- title: Migrating
|
||||
children:
|
||||
- title: Migrating from v3.x.x
|
||||
url: /migration/3/
|
||||
- title: Migrating to v4.0.0
|
||||
url: /migration/4/
|
||||
- title: Migrating to v4.1.0
|
||||
url: /migration/4.1/
|
||||
- title: FAQ & Troubleshooting
|
||||
children:
|
||||
- title: FAQ
|
||||
url: /faq/
|
||||
- title: Troubleshooting Tips
|
||||
url: /troubleshooting-tips/
|
||||
- title: Contact
|
||||
url: /contact/
|
||||
|
||||
marked:
|
||||
gfm: true
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"hexo": {
|
||||
"version": "3.8.0"
|
||||
"version": "3.7.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "hexo serve",
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/ /talk/
|
||||
/talk/reference/server/ /talk/api/server/
|
||||
/talk/reference/graphql/ /talk/api/graphql/
|
||||
/talk/integrating/asset-management/ /talk/integrating/cms-integration/
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
title: Talk Quickstart
|
||||
permalink: /
|
||||
permalink: /installation-quickstart/
|
||||
---
|
||||
|
||||
Online comments are broken. Our open-source Talk tool rethinks how moderation,
|
||||
comment display, and conversation function, creating the opportunity for safer,
|
||||
smarter discussions around your work.
|
||||
smarter discussions around your work.
|
||||
|
||||
More than 60 newsrooms use Talk to run their on-site communities, including the Washington Post, the Wall Street Journal, and IGN.
|
||||
More than 60 newsrooms use Talk to run their on-site communities, including the Washington Post, the Wall Street Journal, and IGN.
|
||||
|
||||
[Read more about our product features and
|
||||
goals here](https://coralproject.net/talk).
|
||||
goals here](https://coralproject.net/).
|
||||
|
||||
<div class="callout">
|
||||
We offer hosting and support packages for Talk. [Contact us for more information.](https://coralproject.net/pricing/)
|
||||
@@ -31,7 +31,7 @@ to persist data. The following versions are supported:
|
||||
- MongoDB 3.2+
|
||||
- Redis 3.2.5+
|
||||
|
||||
You can run Talk (and its dependencies) locally or from [Docker](https://www.docker.com/community-edition#/download) containers. Docker is used in the local example below for the database and cache, however it is possible to run Talk without Docker by configuring your own MongoDB and Redis instances. We have tested Talk
|
||||
You can run Talk (and its dependencies) locally or from [Docker](https://www.docker.com/community-edition#/download) containers. Docker is used in the local example below for the database and cache, however it is possible to run Talk without Docker by configuring your own MongoDB and Redis instances. We have tested Talk
|
||||
and this documentation with Docker versions 17.06.2+.
|
||||
|
||||
An optional dependency for Talk is
|
||||
@@ -44,7 +44,7 @@ and this documentation with versions 1.14.0+.
|
||||
### Installation from Docker
|
||||
|
||||
To use Talk without major customization you can run the application using our
|
||||
provided docker image.
|
||||
provided docker image.
|
||||
|
||||
Start by making a new directory and create a file called `docker-compose.yml` and copy the following:
|
||||
|
||||
@@ -52,7 +52,7 @@ Start by making a new directory and create a file called `docker-compose.yml` an
|
||||
# For details on the syntax of docker-compose.yml files, check out:
|
||||
# https://docs.docker.com/compose/compose-file/compose-file-v2/
|
||||
|
||||
version: '2'
|
||||
version: "2"
|
||||
services:
|
||||
talk:
|
||||
image: coralproject/talk:4
|
||||
@@ -89,7 +89,6 @@ volumes:
|
||||
The environment variables listed above are the bare minimum needed to run the demo, for more configuration
|
||||
variables, check out the [Configuration](/talk/configuration/) section.
|
||||
|
||||
|
||||
And you can then start it with:
|
||||
|
||||
```bash
|
||||
@@ -121,7 +120,6 @@ redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
|
||||
talk_1 yarn start Up 0.0.0.0:3000->3000/tcp
|
||||
```
|
||||
|
||||
|
||||
You now have a Talk instance up and running! Continue on to the [Setup](#setup) section for details on how to complete the
|
||||
initial setup and get started using Talk.
|
||||
|
||||
@@ -157,7 +155,6 @@ Didn't work? Sometimes you may already have a container running on these ports,
|
||||
run `docker ps` to see what other containers you have running and running
|
||||
`docker stop <id>` on those containers to stop them.
|
||||
|
||||
|
||||
_This documentation assumes that you will be running MongoDB on
|
||||
`127.0.0.1:27017` and Redis on `127.0.0.1:6379`. The above Docker commands bind
|
||||
MongoDB and Redis on these interfaces for you._
|
||||
@@ -188,27 +185,26 @@ Continue onto the [Setup](#setup) section for details on how to complete the
|
||||
installation and get started using Talk.
|
||||
|
||||
## Setup
|
||||
|
||||
### Create Admin Account
|
||||
|
||||
With Talk running, you can now navigate to
|
||||
[http://127.0.0.1:3000/admin/install](http://127.0.0.1:3000/admin/install)
|
||||
and walk through the initial setup steps.
|
||||
and walk through the initial setup steps.
|
||||
|
||||
* First, enter your **Organization Name** and **Organization Contact Email**. This will appear in emails when inviting new team members.
|
||||
* Next, create your Admin user. You can specify an **Email Address**, **Username**, and **Password**
|
||||
|
||||
* Finally, enter your list of **Permitted Domains**, read [here](/talk/configuring-talk/#permitted-domains) about whitelisting domains
|
||||
- First, enter your **Organization Name** and **Organization Contact Email**. This will appear in emails when inviting new team members.
|
||||
- Next, create your Admin user. You can specify an **Email Address**, **Username**, and **Password**
|
||||
|
||||
- Finally, enter your list of **Permitted Domains**, read [here](/talk/configuring-talk/#permitted-domains) about whitelisting domains
|
||||
|
||||
_During development, ensure you whitelist 127.0.0.1:3000 otherwise the
|
||||
[http://127.0.0.1:3000/](http://127.0.0.1:3000/) page will not
|
||||
load._
|
||||
|
||||
Once the setup wizard has been completed you can log into Talk ([http://127.0.0.1:3000/](http://127.0.0.1:3000/)) using the email address and password for the Admin user account that you just created.
|
||||
|
||||
From here you can test out features in Talk, see comments in the admin interface where you can do moderation, and configure the user experience.
|
||||
In the next step you'll create some user comments to moderate.
|
||||
Once the setup wizard has been completed you can log into Talk ([http://127.0.0.1:3000/](http://127.0.0.1:3000/)) using the email address and password for the Admin user account that you just created.
|
||||
|
||||
From here you can test out features in Talk, see comments in the admin interface where you can do moderation, and configure the user experience.
|
||||
In the next step you'll create some user comments to moderate.
|
||||
|
||||
### Demo Embedded Comments
|
||||
|
||||
@@ -221,7 +217,7 @@ In order for the demo to work, you must add
|
||||
`https://docs.coralproject.net/` to your
|
||||
permitted domains list. You can do this by visiting
|
||||
[http://127.0.0.1:3000/admin/configure](http://127.0.0.1:3000/admin/configure)
|
||||
now and selecting *Tech Settings* from the sidebar.
|
||||
now and selecting _Tech Settings_ from the sidebar.
|
||||
|
||||
Once you have added the domain of these docs, you can click the button below.
|
||||
|
||||
@@ -235,13 +231,12 @@ Once you have added the domain of these docs, you can click the button below.
|
||||
|
||||
With your local instance of Talk running in development mode (env variable `NODE_ENV=development`) you should now also be able to access the following developer routes:
|
||||
|
||||
* [http://127.0.0.1:3000/dev](http://127.0.0.1:3000/dev]) provides a sample comment stream
|
||||
- [http://127.0.0.1:3000/dev](http://127.0.0.1:3000/dev]) provides a sample comment stream
|
||||
|
||||
* [http://127.0.0.1:3000/dev/assets](http://127.0.0.1:3000/dev/assets]) provides a list of all stories in Talk and can generate new sample assets
|
||||
- [http://127.0.0.1:3000/dev/assets](http://127.0.0.1:3000/dev/assets]) provides a list of all stories in Talk and can generate new sample assets
|
||||
|
||||
### Conclusion
|
||||
|
||||
At this point you've successfully installed, configured, and ran your very own
|
||||
instance of Talk! Continue through this documentation on this site to learn more
|
||||
on how to configure, develop with, and contribute to Talk!
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
---
|
||||
title: GraphQL API Overview
|
||||
permalink: /v5/api/overview/
|
||||
---
|
||||
|
||||
Our API is generally served via GraphQL at `/api/graphql` on your Coral installation. If you're running Coral locally, this would be https://localhost:8080/api/graphql.
|
||||
|
||||
You can enable the GraphiQL interface at https://localhost:3000/graphiql (Note the port number here is not 8080, this is because this route is directly served by the server, and not the webpack development server) when running in development to access a GraphQL playground to use with documentation provided in the sidebar on what edges are available to you. You can do this by setting `ENABLE_GRAPHIQL=true`. **(🚨 Note 🚨) we do not recommend using this in production environments as it disables many safety features used by the application**.
|
||||
|
||||
## Making your first request
|
||||
|
||||
To learn a bit about how to interact with Coral, we'll query for comments on a
|
||||
page of Coral.
|
||||
|
||||
The GraphQL endpoint we have can be used with any HTTP client available, but our
|
||||
examples below will use the common `curl` tool:
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--url "http://localhost:8080/api/graphql" \
|
||||
--header "content-type: application/json" \
|
||||
--data '{"query":"query GetComments($url: String!) {story(url: $url) { id metadata { title } url comments { nodes { id body author { id username } } } } }","variables":{"url":"http://localhost:8080/"},"operationName":"GetComments"}'
|
||||
```
|
||||
|
||||
When you unpack that, it's really quite simple. We're executing a `POST` request
|
||||
to the `/api/graphql` route of the local Talk server with the GraphQL
|
||||
request we want to make. It's composed of the `query`, `variables`, and
|
||||
`operationName`.
|
||||
|
||||
```graphql
|
||||
query GetComments($url: String!) {
|
||||
story(url: $url) {
|
||||
metadata {
|
||||
title
|
||||
}
|
||||
url
|
||||
comments {
|
||||
nodes {
|
||||
body
|
||||
author {
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
We are grabbing the asset with the specified `$url`, and grabbing it's title and the comments under it.
|
||||
|
||||
We can then also specify our variables to the query being executed (in this
|
||||
case, the url for the page where we have comments on our local install of Coral):
|
||||
|
||||
```json
|
||||
{
|
||||
"url": "http://localhost:8080/"
|
||||
}
|
||||
```
|
||||
|
||||
It's also sometimes common to have multiple queries within a query, which is
|
||||
where the `operationName` comes into play, where we simply specify the named
|
||||
query that we want to execute (in this case, `GetComments`).
|
||||
|
||||
To get a deeper understanding of GraphQL queries, read up on
|
||||
[GraphQL Queries and Mutations](http://graphql.org/learn/queries/).
|
||||
|
||||
## Understanding the response
|
||||
|
||||
Once you completed the above GraphQL query with `curl`, you'll get a response
|
||||
sort of like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"story": {
|
||||
"metadata": {
|
||||
"title": "Coral 5.0 – Embed Stream"
|
||||
},
|
||||
"url": "http://localhost:8080/",
|
||||
"comments": {
|
||||
"nodes": [
|
||||
{
|
||||
"body": "First comment!",
|
||||
"author": {
|
||||
"username": "wyatt.johnson"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All of the parameters you requested should be available under the `data`
|
||||
property. Any errors that you get would appear in a `errors` array at the top
|
||||
level, like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"message": "The specified story URL does not exist in the permitted domains list.",
|
||||
"locations": [
|
||||
{
|
||||
"line": 2,
|
||||
"column": 3
|
||||
}
|
||||
],
|
||||
"path": ["story"],
|
||||
"extensions": {
|
||||
"code": "STORY_URL_NOT_PERMITTED",
|
||||
"id": "e255e860-d3ab-11e9-acdf-b9e9700f06fa",
|
||||
"type": "INVALID_REQUEST_ERROR",
|
||||
"message": "The specified story URL does not exist in the permitted domains list."
|
||||
}
|
||||
}
|
||||
],
|
||||
"data": {
|
||||
"story": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You should know that any property that is marked with a `!` is considered
|
||||
required, and non-nullable, which means you can always guarantee on it being
|
||||
there in your request if there were no errors.
|
||||
|
||||
## Authorizing a request
|
||||
|
||||
Some queries you may notice seem to return an error of
|
||||
`USER_NOT_ENTITLED`. It's likely the case that you are making a request to a
|
||||
route that requires authorization. You can perform authorization a few ways in
|
||||
Talk.
|
||||
|
||||
Essentially, you need to get access to a JWT token that you can use to authorize
|
||||
your requests.
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--url http://localhost:3000/api/auth/local \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{ "email": "${EMAIL}", "password": "${PASSWORD}"}'
|
||||
```
|
||||
|
||||
Which returns a response similar to:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "${TOKEN}"
|
||||
}
|
||||
```
|
||||
|
||||
Where `${EMAIL}` is the email address of an admin user, and `${PASSWORD}` is the password for that admin user. This will generate a short term token (valid for 90 days). To generate a long lived access token (or Personal Access Token), you have to exchange the token generated above to create a new long lived token:
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--url "http://localhost:3000/api/graphql" \
|
||||
--header 'authorization: Bearer ${TOKEN}' \
|
||||
--header 'content-type: application/json' \
|
||||
--data '{"query":"mutation CreateAccessToken { createToken(input: { clientMutationId: \"\", name: \"My PAT\" }) { signedToken }}","operationName":"CreateAccessToken"}'
|
||||
```
|
||||
|
||||
Which returns a response similar to:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"createToken": {
|
||||
"signedToken": "${TOKEN}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Where `${TOKEN}` in the request being from the previous set of login steps and returning a new `signedToken` as `${TOKEN}` which can be used instead of the previous `${TOKEN}` value in the below examples.
|
||||
|
||||
Once you have your access token, you can substitute it as `${TOKEN}` in your
|
||||
`curl` request as follows:
|
||||
|
||||
### Bearer Token
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--url "http://localhost:8080/api/graphql" \
|
||||
--header "content-type: application/json" \
|
||||
--header "Authorization: Bearer ${TOKEN}" \
|
||||
--data '{"query":"query GetComments($url: String!) {story(url: $url) { id metadata { title } url comments { nodes { id body author { id username } } } } }","variables":{"url":"http://localhost:8080/"},"operationName":"GetComments"}'
|
||||
```
|
||||
|
||||
### Cookie
|
||||
|
||||
```sh
|
||||
curl --request POST \
|
||||
--url "http://localhost:8080/api/graphql" \
|
||||
--header "content-type: application/json" \
|
||||
--cookie "authorization=${TOKEN}"
|
||||
--data '{"query":"query GetComments($url: String!) {story(url: $url) { id metadata { title } url comments { nodes { id body author { id username } } } } }","variables":{"url":"http://localhost:8080/"},"operationName":"GetComments"}'
|
||||
```
|
||||
|
||||
## Persisted Queries
|
||||
|
||||
You might see an error like `RAW_QUERY_NOT_AUTHORIZED`. This means that you attempted to use either no token, or a token from a user without admin privileges. In Coral, we whitelist the GraphQL mutations and queries that are performed by the applications for security reasons meaning that only admin users can make arbitrary queries against the GraphQL API.
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Configuring Version 5
|
||||
permalink: /v5/configuration/
|
||||
---
|
||||
|
||||
The following environment variables can be set to configure the Coral Server. You
|
||||
can expose them in your shell via `export NODE_ENV=development` or by placing
|
||||
the variables in a `.env` file in the root of the project in a simple
|
||||
`NODE_ENV=development` format delimited by newlines.
|
||||
|
||||
- `NODE_ENV` - Can be one of `production` or `development`. All production
|
||||
deployments should use `production`. Defaults to `production` when ran with
|
||||
`npm run start` and `development` when run with `npm run start:development`.
|
||||
- `PORT` - The port to listen for HTTP and Websocket requests. (Default `3000`)
|
||||
- `MONGODB_URI` - The MongoDB database URI to connect to.
|
||||
(Default `mongodb://127.0.0.1:27017/coral`)
|
||||
- `REDIS_URI` - The Redis database URI to connect to.
|
||||
(Default `redis://127.0.0.1:6379`)
|
||||
- `REDIS_OPTIONS` - A JSON string with optional configuration options to be used
|
||||
when connecting to Redis as specified in the [ioredis](https://github.com/luin/ioredis/blob/1dac50a63753c2afc969315cfe38faf0edc50bc5/API.md#new_Redis_new) documentation.
|
||||
(Default: `{}`)
|
||||
- `SIGNING_SECRET` - The shared secret to use to sign JSON Web Tokens (JWT) with
|
||||
the selected signing algorithm. 🚨 **Don't forget to set this variable!** 🚨
|
||||
(Default: `keyboard cat`)
|
||||
- `SIGNING_ALGORITHM` - The signing algorithm to use for signing JWT's.
|
||||
(Default `HS256`).
|
||||
- `LOGGING_LEVEL` - The logging level that can be set to one of `fatal`,
|
||||
`error`, `warn`, `info`, `debug`, or `trace`. (Default `info`)
|
||||
- `STATIC_URI` - The URI that static assets can be accessed from. This URI can
|
||||
be to a proxy that uses this Coral server on `PORT` as the upstream. Disabled
|
||||
by default.
|
||||
- `DISABLE_TENANT_CACHING` - When `true`, all tenants will be loaded from the
|
||||
database when needed rather than keeping a in-memory copy in sync via
|
||||
published events on Redis. (Default `false`)
|
||||
- `DISABLE_MONGODB_AUTOINDEXING` - When `true`, Coral will not perform indexing
|
||||
operations when it starts up. This can be desired when you've already
|
||||
installed Coral on the target MongoDB, but want to improve start performance.
|
||||
**You should not use this parameter unless you know what you're doing! Upgrades
|
||||
may introduce additional indexes that the application relies on.**
|
||||
(Default `false`)
|
||||
- `LOCALE` - Specify the default locale to use for all requests without a locale
|
||||
specified. (Default `en-US`)
|
||||
- `ENABLE_GRAPHIQL` - When `true`, it will enable the `/graphiql` even in
|
||||
production, use with care. (Default `false`)
|
||||
- `CONCURRENCY` - The number of worker nodes to spawn to handle web traffic,
|
||||
this should be tied to the number of CPU's available. (Default
|
||||
`os.cpus().length`)
|
||||
- `DEV_PORT` - The port where the Webpack Development server is running on.
|
||||
(Default `8080`)
|
||||
- `METRICS_USERNAME` - The username for _Basic Authentication_ at the `/metrics` and `/cluster_metrics`
|
||||
endpoint.
|
||||
- `METRICS_PASSWORD` - The password for _Basic Authentication_ at the `/metrics` and `/cluster_metrics`
|
||||
endpoint.
|
||||
- `CLUSTER_METRICS_PORT` - If `CONCURRENCY` is more than `1`, the metrics are provided at this port under `/cluster_metrics`. (Default `3001`)
|
||||
- `DISABLE_LIVE_UPDATES` - When `true`, disables subscriptions for the comment
|
||||
stream for all stories across all tenants (Default `false`)
|
||||
- `WEBSOCKET_KEEP_ALIVE_TIMEOUT` - A duration in a parsable format (e.g. `30 seconds`
|
||||
, `1 minute`) that should be used to send keep alive messages through the
|
||||
websocket to keep the socket alive (Default `30 seconds`)
|
||||
- `TRUST_PROXY` - When provided, it configures the "trust proxy" settings for Express (See https://expressjs.com/en/guide/behind-proxies.html)
|
||||
|
||||
## `TRUST_PROXY`
|
||||
|
||||
If you are encountering issues where urls in the administration are showing with
|
||||
a `http` instead of `https`, you may need to set the `TRUST_PROXY` setting.
|
||||
Refer to https://expressjs.com/en/guide/behind-proxies.html for possible values
|
||||
of this configuration variable as it pertains to your setup.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: Comment Count Integration
|
||||
permalink: /v5/integrating/counts/
|
||||
---
|
||||
|
||||
Add the `count.js` script to your `html` tree. On a page that includes the _Stream Embed_ this is done for you automatically, however for best performance we recommend to include it into the `<head>` tag.
|
||||
|
||||
```html
|
||||
<script src="//{{ CORAL_DOMAIN_NAME }}/assets/js/count.js" defer></script>
|
||||
```
|
||||
|
||||
> **NOTE:** Replace the value of `{% raw %}{{ CORAL_DOMAIN_NAME }}{% endraw %}` with the location of your running instance of Coral.
|
||||
|
||||
Insert an html element with the class `coral-count` and configure it using `data-coral-*` attributes.
|
||||
|
||||
```html
|
||||
<span class="coral-count" data-coral-url="http://example.com/blog-entry-1/"></span>
|
||||
```
|
||||
|
||||
After successful injection it will become:
|
||||
|
||||
```html
|
||||
<span class="coral-count" data-coral-url="http://example.com/blog-entry-1/">
|
||||
<span class="coral-count-number">5</span>
|
||||
<span class="coral-count-text">Comments</span>
|
||||
</span>
|
||||
```
|
||||
|
||||
### Available `data-coral-*` attributes
|
||||
|
||||
Set the class of your html element to `coral-count` in order to get story counts. The following `data-coral-*` attributes will configure the output:
|
||||
|
||||
- `data-coral-id` – The id of the story of which counts should be injected.
|
||||
- `data-coral-url` – The url of the story of which counts should be injected.
|
||||
- `data-coral-notext` – If set to `"true"`, only the count number will be injected
|
||||
|
||||
Either `data-coral-id` or `data-coral-url` should be set. If none are provided the story url
|
||||
will be retrieved from the [canonical url reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Choosing_between_www_and_non-www_URLs#Using_%3Clink_relcanonical%3E) `<link rel="canonical" href="...">` or inferred using the current page url.
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: Developing
|
||||
permalink: /v5/developing/
|
||||
---
|
||||
|
||||
Running Coral for development is very similar to installing Coral via Source as
|
||||
described above.
|
||||
|
||||
Coral requires NodeJS >=12, we recommend using `nvm` to help manage node
|
||||
versions: https://github.com/creationix/nvm.
|
||||
|
||||
```bash
|
||||
# Clone and cd into the Coral directory.
|
||||
git clone https://github.com/coralproject/talk.git
|
||||
cd talk
|
||||
|
||||
# Install dependencies.
|
||||
npm install
|
||||
```
|
||||
|
||||
Running Coral with default settings assumes that you have:
|
||||
|
||||
- MongoDB >=4.2 running on `127.0.0.1:27017`
|
||||
- Redis >=3.2 running on `127.0.0.1:6379`
|
||||
|
||||
If you don't already have these databases running, you can execute the following
|
||||
assuming you have Docker installed on your local machine:
|
||||
|
||||
```bash
|
||||
docker run -d -p 27017:27017 --restart always --name mongo mongo:4.2
|
||||
docker run -d -p 6379:6379 --restart always --name redis redis:3.2
|
||||
```
|
||||
|
||||
We recommend installing [watchman](https://facebook.github.io/watchman/docs/install.html) for better watch
|
||||
performance.
|
||||
|
||||
```bash
|
||||
# On macOS, you can run the following with Homebrew.
|
||||
brew update
|
||||
brew install watchman
|
||||
```
|
||||
|
||||
Then start Coral with:
|
||||
|
||||
```bash
|
||||
# Run the server in development mode in order to facilitate auto-restarting and
|
||||
# rebuilding when file changes are detected. This might take a while to fully run.
|
||||
npm run watch
|
||||
```
|
||||
|
||||
When the client code has been built, navigate to http://localhost:8080/install
|
||||
to start the installation wizard. **Note: Ensure `localhost:8080` is used in the permitted domains list.**
|
||||
|
||||
To see the comment stream goto http://localhost:8080/.
|
||||
|
||||
To run linting and tests use the following commands:
|
||||
|
||||
```bash
|
||||
# Run the linters.
|
||||
npm run lint
|
||||
|
||||
# Run our unit and integration tests.
|
||||
npm run test
|
||||
```
|
||||
|
||||
## Email
|
||||
|
||||
To test out the email sending functionality, you can run [inbucket](https://www.inbucket.org/)
|
||||
which provides a test SMTP server that can visualize emails in the browser:
|
||||
|
||||
```bash
|
||||
docker run -d --name inbucket --restart always -p 2500:2500 -p 9000:9000 inbucket/inbucket
|
||||
```
|
||||
|
||||
You can then configure the email server on Coral
|
||||
by setting the email settings in
|
||||
`Configure -> Email` in the admin:
|
||||
|
||||
| Field | Value |
|
||||
| -------------- | -------------------- |
|
||||
| From Address | `community@test.com` |
|
||||
| Secure | `No` |
|
||||
| Host | `localhost` |
|
||||
| Port | `2500` |
|
||||
| Authentication | `No` |
|
||||
|
||||
Navigate to http://localhost:9000, click the "Monitor" tab. New emails received
|
||||
on this screen.
|
||||
|
||||
## Design Language System (UI Components)
|
||||
|
||||
We use [docz](https://docz.site) to document and develop our Design Language System. To start docz run:
|
||||
|
||||
```bash
|
||||
# Make sure CSS types are generated.
|
||||
# This is not required when `npm run watch` is already running.
|
||||
npm run generate:css-types
|
||||
|
||||
# Run docz in development.
|
||||
npm run docz -- dev
|
||||
```
|
||||
|
||||
After compilation has finished you can access docz at http://localhost:3030/.
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: GDPR Compliance
|
||||
permalink: /v5/integrating/gdpr/
|
||||
---
|
||||
|
||||
In order to facilitate compliance with the
|
||||
[EU General Data Protection Regulation (GDPR)](https://www.eugdpr.org/), Coral
|
||||
provides features so your users can change and manage their own data.
|
||||
|
||||
Even if GDPR will not apply to you, it is recommended to enable these
|
||||
features as a best practice to provide your users with control over their own
|
||||
data.
|
||||
|
||||
## GDPR Feature Overview
|
||||
|
||||
Integrating our GDPR tools will give your users and organizations the following benefits:
|
||||
|
||||
- **Download my comment data**: Users can request a download of their comments. An email with a link is emailed to them to download a CSV with each comment they've made, what story it was made on, and the comment's ID and timestamp.
|
||||
- **Delete my account**: Users can request deletion of their account. Deleted account requests are pending for 24 hours to allow the user to download their comments, or to change their mind and reactivate their account before the expiry. Account deletions remove all of their comments from the site, all their comments and actions from the database, and their account info from our system.
|
||||
- **Add an email to an OAuth/external account**: Users are prompted to add an email to their non-Coral account (Facebook, Google, external, etc) so that they can take part in GDPR and other features requiring email communication.
|
||||
- **Change my username**: Users can update their username. This is capped at once every 2 weeks.
|
||||
- **Change my email**: Users can change their email.
|
||||
- **Change my password**: Users can change their password.
|
||||
|
||||
## GDPR with SSO
|
||||
|
||||
As many newsrooms often implement their own [SSO solutions](/talk/v5/integrating/sso/),
|
||||
we also provide API support to manage GDPR features directly from your own Account or My Profile page.
|
||||
|
||||
We provide the following GraphQL mutations designed to allow you to integrate it into your existing user
|
||||
interfaces or exports.
|
||||
|
||||
- `requestUserCommentsDownload` - lets you grab the direct link to download a users
|
||||
account in a zip format. From there, you can integrate it into your existing
|
||||
data export or simply proxy it to the user to allow them to download it
|
||||
elsewhere in your UI.
|
||||
- `deleteUserAccount` - lets you delete the specified user
|
||||
|
||||
**Note: These mutations require an administrative token**
|
||||
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: Installing Version 5
|
||||
permalink: /
|
||||
---
|
||||
|
||||
Online comments are broken. Our open-source commenting platform, Coral, reimagines
|
||||
moderation, comment display, and conversation. Use Coral to add safer, smarter discussions to your site without giving away your data.
|
||||
|
||||
More than 70 publishers in 14 countries trust Coral to run their on-site communities, including the Washington Post, the Wall Street Journal, and Der Spiegel.[Read more about Coral here](https://coralproject.net/).
|
||||
|
||||
<div class="callout">
|
||||
We offer hosting and support packages for Coral, as well as exclusive, customer-only resources. [Contact us for more information.](https://coralproject.net/pricing/)
|
||||
</div>
|
||||
|
||||
Built with ❤️ by Coral by [Vox Media](https://product.voxmedia.com/).
|
||||
|
||||
Try out a test version of Coral by running it via a Heroku App:
|
||||
|
||||
[](https://heroku.com/deploy?template=https://github.com/coralproject/talk)
|
||||
|
||||
## Requirements
|
||||
|
||||
- MongoDB >=4.2
|
||||
- Redis >=3.2
|
||||
- NodeJS >=12
|
||||
- NPM >=6.7
|
||||
|
||||
## Running
|
||||
|
||||
You can install Coral using Docker or via Source. We recommend Docker, as it
|
||||
provides the easiest deployment solution going forward, as all the dependencies
|
||||
are baked and shipped with the provided
|
||||
[coralproject/talk:5](https://hub.docker.com/r/coralproject/talk) image.
|
||||
|
||||
### Docker
|
||||
|
||||
The easiest way to get started with Coral is through our published Docker image
|
||||
and provided example `docker-compose.yml` file. The following assumes that you
|
||||
have Docker and Docker Compose installed on your local machine:
|
||||
|
||||
- Install Docker: https://docs.docker.com/install/
|
||||
- Install Docker Compose: https://docs.docker.com/compose/install/ (this is typically included in the Docker Desktop editions already)
|
||||
|
||||
```bash
|
||||
# Create directories to persist the data in MongoDB and Redis.
|
||||
mkdir -p data/{mongo,redis}
|
||||
|
||||
# Create the `docker-compose.yml` file to get started.
|
||||
cat > docker-compose.yml <<EOF
|
||||
version: "2"
|
||||
services:
|
||||
talk:
|
||||
image: coralproject/talk:5
|
||||
restart: always
|
||||
ports:
|
||||
- "127.0.0.1:3000:5000"
|
||||
depends_on:
|
||||
- mongo
|
||||
- redis
|
||||
environment:
|
||||
- MONGODB_URI=mongodb://mongo:27017/coral
|
||||
- REDIS_URI=redis://redis:6379
|
||||
- SIGNING_SECRET=<replace me with something secret>
|
||||
mongo:
|
||||
image: mongo:4.2
|
||||
volumes:
|
||||
- ./data/mongo:/data/db
|
||||
redis:
|
||||
image: redis:3.2
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
EOF
|
||||
|
||||
# Start up Coral using Docker.
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Then head on over to http://localhost:3000 to install Coral!
|
||||
|
||||
### Source
|
||||
|
||||
Coral requires NodeJS >=12, we recommend using `nvm` to help manage node
|
||||
versions: https://github.com/creationix/nvm.
|
||||
|
||||
```bash
|
||||
# Clone and cd into the Coral directory.
|
||||
git clone https://github.com/coralproject/talk.git
|
||||
cd talk
|
||||
|
||||
# Install dependencies.
|
||||
npm install
|
||||
|
||||
# Build the application dependencies.
|
||||
# This might take a while.
|
||||
npm run build
|
||||
```
|
||||
|
||||
This should output all the compiled application code to `./dist`.
|
||||
|
||||
Running Coral with default settings assumes that you have:
|
||||
|
||||
- MongoDB >=4.2 running on `127.0.0.1:27017`
|
||||
- Redis >=3.2 running on `127.0.0.1:6379`
|
||||
|
||||
If you don't already have these databases running, you can execute the following
|
||||
assuming you have Docker installed on your local machine:
|
||||
|
||||
```bash
|
||||
docker run -d -p 27017:27017 --restart always --name mongo mongo:4.2
|
||||
docker run -d -p 6379:6379 --restart always --name redis redis:3.2
|
||||
```
|
||||
|
||||
Then start Coral with:
|
||||
|
||||
```bash
|
||||
# Start the server in production mode.
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then head on over to http://localhost:3000 to install Coral!
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Integrating on your site
|
||||
permalink: /v5/integrating/cms/
|
||||
---
|
||||
|
||||
With Coral setup and running you can embed the comment stream with this sample embed script:
|
||||
|
||||
```
|
||||
<div id="coral_thread"></div>
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
var d = document, s = d.createElement('script');
|
||||
var url = '{{ CORAL_DOMAIN_NAME }}';
|
||||
s.src = '//' + url + '/assets/js/embed.js';
|
||||
s.async = false;
|
||||
s.defer = true;
|
||||
s.onload = function() {
|
||||
Coral.createStreamEmbed({
|
||||
id: "coral_thread",
|
||||
autoRender: true,
|
||||
rootURL: '//' + url,
|
||||
});
|
||||
};
|
||||
(d.head || d.body).appendChild(s);
|
||||
})();
|
||||
</script>`;
|
||||
```
|
||||
|
||||
> **NOTE:** Replace the value of `{% raw %}{{ CORAL_DOMAIN_NAME }}{% endraw %}` with the location of your running instance of Coral.
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: Slack
|
||||
permalink: /v5/integrating/slack/
|
||||
---
|
||||
|
||||
Coral version 5 supports built-in Slack integration to help you forward comments from your moderation queues into appropriate Slack channels.
|
||||
|
||||
## Creating a Slack App
|
||||
|
||||
To enable web hooks that we will use to forward comments, you'll need to create an App and give it permissions over a channel.
|
||||
|
||||
For details on how to create a Slack app with webhooks, please go to:
|
||||
|
||||
https://slack.com/intl/en-ca/help/articles/115005265063-incoming-webhooks-for-slack
|
||||
|
||||
After you have created a Slack app with a webhook, you can use it in your Coral configuration.
|
||||
|
||||
1. Sign into the administration side of your Coral deployment.
|
||||
2. Select _Configure_ from the top navigation.
|
||||
3. Select _Slack_ from the side navigation for the configuration area.
|
||||
4. Here you can configure a Slack channel.
|
||||
5. Paste in the webhook URL you created for your Slack app and select which comment categories you want to receive notifications for.
|
||||
|
||||
## I need to find the webhook URL again, where is it?
|
||||
|
||||
Webhooks options are tied to a Slack app and can be found under your app settings at:
|
||||
|
||||
https://api.slack.com/apps
|
||||
@@ -0,0 +1,127 @@
|
||||
---
|
||||
title: Single Sign On
|
||||
permalink: /v5/integrating/sso/
|
||||
---
|
||||
|
||||
In order to allow seamless connection to an existing authentication system,
|
||||
Coral utilizes the industry standard [JWT Token](https://jwt.io/) to connect. To
|
||||
learn more about how to create a JWT token, see [this introduction](https://jwt.io/introduction/).
|
||||
|
||||
1. Visit: ```https://{{ CORAL_DOMAIN_NAME }} /admin/configure/auth```
|
||||
2. Scroll to the `Login with Single Sign On` section
|
||||
3. Enable the Single Sign On Authentication Integration
|
||||
4. Enable `Allow Registration`
|
||||
5. Copy the string in the `Key` box
|
||||
6. Click Save
|
||||
|
||||
> **NOTE:** Replace the value of ```{{ CORAL_DOMAIN_NAME }}``` with the location of your running instance of Coral.
|
||||
|
||||
You will then have to generate a JWT with the following claims:
|
||||
|
||||
- `jti` _(optional)_ - A unique ID for this particular JWT token. We recommend
|
||||
using a [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier)
|
||||
for this value. Without this parameter, the logout functionality inside the
|
||||
embed stream will not work and you will need to call logout on the embed
|
||||
itself.
|
||||
- `exp` _(optional)_ - When the given SSO token should expire. This is
|
||||
specified as a unix time stamp in seconds. Once the token has expired, a new
|
||||
token should be generated and passed into Coral. Without this parameter, the
|
||||
logout functionality inside the embed stream will not work and you will need
|
||||
to call logout on the embed itself.
|
||||
- `iat` _(optional)_ - When the given SSO token was issued. This is required to
|
||||
utilize the automatic user detail update system. If this time is newer than
|
||||
the time we received the last update, the contents of the token will be used
|
||||
to update the user.
|
||||
- `user.id` **(required)** - the ID of the user from your authentication system.
|
||||
This is required to connect the user in your system to allow a seamless
|
||||
connection to Coral.
|
||||
- `user.email` **(required)** - the email address of the user from your
|
||||
authentication system. This is required to facilitate notification email's
|
||||
about status changes on a user account such as bans or suspensions.
|
||||
- `user.username` **(required)** - the username that should be used when being
|
||||
presented inside Coral to moderators and other users. There are no username validations or restrictions enforced by Coral when you're using SSO.
|
||||
- `user.badges` _(optional)_ - array of strings to be displayed as badges beside
|
||||
username inside Coral, visible to other users and moderators. For example, to indicate
|
||||
a user's subscription status.
|
||||
- `user.role` _(optional)_ - one of "COMMENTER", "STAFF", "MODERATOR", "ADMIN". Will create/update
|
||||
Coral user with this role.
|
||||
|
||||
An example of the claims for this token would be:
|
||||
|
||||
```json
|
||||
{
|
||||
"jti": "151c19fc-ad15-4f80-a49c-09f137789fbb",
|
||||
"exp": 1572172094,
|
||||
"iat": 1562172094,
|
||||
"user": {
|
||||
"id": "628bdc61-6616-4add-bfec-dd79156715d4",
|
||||
"email": "bob@example.com",
|
||||
"username": "bob"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With the claims provided, you can sign them with the `Key` obtained from the
|
||||
Coral administration panel in the previous steps with a `HS256` algorithm. This
|
||||
token can be provided in the above mentioned embed code by adding it to the
|
||||
`createStreamEmbed` function:
|
||||
|
||||
```js
|
||||
Coral.createStreamEmbed({
|
||||
// Don't forget to include the parameters from the
|
||||
// "Embed On Your Site" section.
|
||||
accessToken: "{{ SSO_TOKEN }}"
|
||||
});
|
||||
```
|
||||
|
||||
Or by calling the `login/logout` method on the embed object:
|
||||
|
||||
```js
|
||||
var embed = Coral.createStreamEmbed({
|
||||
// Don't forget to include the parameters from the
|
||||
// "Embed On Your Site" section.
|
||||
});
|
||||
|
||||
// Login the current embed with the generated SSO token.
|
||||
embed.login("{{ SSO_TOKEN }}");
|
||||
|
||||
// Logout the user.
|
||||
embed.logout();
|
||||
```
|
||||
|
||||
## External Integrations
|
||||
|
||||
You can integrate directly with the Coral GraphQL API in order to facilitate
|
||||
account updates for your users when using Coral SSO. The relevant mutations are
|
||||
as follows:
|
||||
|
||||
- `updateUserUsername` lets you update a given user with a new username using
|
||||
an admin token.
|
||||
- `updateUserEmail` lets you update a given user with a new email address
|
||||
using an admin token.
|
||||
- `deleteUser` lets you delete a given account using an admin token.
|
||||
Note that even with an admin token, you may not delete yourself via
|
||||
this method, and instead must use the `requestAccountDeletion`
|
||||
mutation instead. This differs from the `requestAccountDeletion` as
|
||||
it does the operation immediately instead of scheduling it as
|
||||
`requestAccountDeletion` does.
|
||||
- `requestUserCommentsDownload` lets you retrieve a given account's comments download. This mutation will provide you with a `archiveURL` that can be used to download a ZIP file containing the user's comment export.
|
||||
|
||||
If you're unsure on how to call GraphQL API's, refer to the section here on [Making your first GraphQL request](/talk/v5/api/overview/#making-your-first-request).
|
||||
|
||||
## Login Prompts
|
||||
|
||||
In order to handle login prompts (e.g. a user clicks on the sign in button) you can listen to the `loginPrompt` event.
|
||||
|
||||
```js
|
||||
var embed = Coral.createStreamEmbed({
|
||||
// Don't forget to include the parameters from the
|
||||
// "Embed On Your Site" section.
|
||||
events: function(events) {
|
||||
events.on("loginPrompt", function() {
|
||||
// Redirect user to a login page.
|
||||
location.href = "http://example.com/login";
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
<article{% if page.class %} class="{{ page.class }}"{% endif %}>
|
||||
{% if page.title %}
|
||||
<a class="btn btn-sm btn-light float-right suggest-edits plain-link" href="https://github.com/coralproject/talk/edit/master/docs/source/{{ page.source }}" title="Suggest edits to this page">Suggest Edits</a>
|
||||
<a class="btn btn-sm btn-light float-right suggest-edits plain-link" href="https://github.com/coralproject/talk/edit/release/4/docs/source/{{ page.source }}" title="Suggest edits to this page">Suggest Edits</a>
|
||||
<h1>{{ page.title }}</h1>
|
||||
<hr/>
|
||||
{% endif %}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<hr/>
|
||||
<footer class="footer">
|
||||
<p class="text-center">Coral Project Talk Technical Documentation. Design inspired by <a href="https://docs.minio.io/" rel="noreferrer" target="_blank">Minio Docs</a>.</p>
|
||||
<p class="text-center">Coral by Vox Media Technical Documentation. Design inspired by <a href="https://docs.minio.io/" rel="noreferrer" target="_blank">Minio Docs</a>.</p>
|
||||
</footer>
|
||||
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
|
||||
|
||||
+31
-31
@@ -1,35 +1,35 @@
|
||||
<aside class="sidebar">
|
||||
<a class="brand" href="{{ url_for("/") }}">
|
||||
<h2>
|
||||
{{ image_tag('images/logo.svg', {width: 50, height: 50}) }}
|
||||
<span>Talk</span>
|
||||
</h2>
|
||||
</a>
|
||||
<ul class="sidebar__list">
|
||||
{% for item in config.sidebar.side %}
|
||||
{% if item.url %}
|
||||
<li class="sidebar__section{% if is_current(item.url) %} active toggled{% endif %}">
|
||||
<a href="{{ url_for(item.url) }}" class="sidebar__header sidebar__header__link">{{ item.title }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="sidebar__section{% for item in item.children %}{% if is_current(item.url) %} active toggled{% endif %}{% endfor %}">
|
||||
<a href="#" class="sidebar__header">{{ item.title }}</a>
|
||||
<ul class="sidebar__links">
|
||||
{% for item in item.children %}
|
||||
<li class="{% if is_current(item.url) %}active{% endif %}">
|
||||
<a href="{{ url_for(item.url) }}">{{ item.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="notice">
|
||||
<p>Made by <a href="https://coralproject.net/" class="coral-link-invert" target="_blank">The Coral Project</a> by <a href="https://www.voxmedia.com/" class="coral-link-invert" target="_blank" title="Vox Media">Vox Media</a>.</p>
|
||||
<a href="https://www.voxmedia.com/" target="_blank" title="Vox Media"><figure class="voxmedia" alt="Vox Media">{{ image_tag('images/coralproject.png') }}</figure></a>
|
||||
<div>
|
||||
<a class="brand" href="{{ url_for("/") }}">
|
||||
{{ image_tag('images/coralproject_color.svg') }}
|
||||
</a>
|
||||
<ul class="sidebar__list">
|
||||
{% for item in config.sidebar.side %}
|
||||
{% if item.url %}
|
||||
<li class="sidebar__section{% if is_current(item.url) %} active toggled{% endif %}">
|
||||
<a href="{{ url_for(item.url) }}" class="sidebar__header sidebar__header__link">{{ item.title }}</a>
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="sidebar__section{% for item in item.children %}{% for item in item.children %}{% if is_current(item.url) %} active toggled{% endif %}{% endfor %}{% endfor %}">
|
||||
<a href="#" class="sidebar__header">{{ item.title }}</a>
|
||||
<ul class="sidebar__headers">
|
||||
{% for item in item.children %}
|
||||
<li class="sidebar__subsection{% for item in item.children %}{% if is_current(item.url) %} active toggled{% endif %}{% endfor %}">
|
||||
<a href="#" class="sidebar__header">{{ item.title }}</a>
|
||||
<ul class="sidebar__links">
|
||||
{% for item in item.children %}
|
||||
<li class="{% if is_current(item.url) %}active{% endif %}">
|
||||
<a href="{{ url_for(item.url) }}">{{ item.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="sidebar__backdrop"></div>
|
||||
|
||||
+54
-16
@@ -1,21 +1,59 @@
|
||||
$coral_orange: #f67150;
|
||||
// Palate
|
||||
$coral_orange: rgb(245, 100, 85);
|
||||
$coral_dark_blue: rgb(19, 28, 84);
|
||||
$coral_light_blue: rgb(83, 192, 191);
|
||||
$coral_light_gray: rgb(238, 238, 238);
|
||||
$coral_dark_gray: rgb(46, 56, 61);
|
||||
$coral_success: rgb(35, 131, 53);
|
||||
$coral_error: rgb(208, 48, 53);
|
||||
|
||||
// Variables
|
||||
|
||||
// // Sidebar
|
||||
|
||||
$sidebar_width: 320px;
|
||||
$sidebar_background: $coral_orange;
|
||||
$sidebar_color: white;
|
||||
$sidebar_background: white;
|
||||
$sidebar_color: black;
|
||||
$sidebar_gutter: 35px;
|
||||
|
||||
// // Layout
|
||||
|
||||
$content_gutter: 40px;
|
||||
$header_padding_bottom: $content_gutter;
|
||||
$breakpoint: 960px;
|
||||
$hljs_string_color: $coral_orange;
|
||||
$code_background: #F0F0F0;
|
||||
$code_border: 1px solid darken($code_background, 10%);
|
||||
$copy_button_background: white;
|
||||
$coral_button_background: $coral_orange;
|
||||
$coral_button_border: darken($coral_button_background, 5%);
|
||||
$demo_border: lighten($coral_button_border, 30%);
|
||||
$coral_button_border_color: $coral_orange;
|
||||
$coral_button_color: black;
|
||||
$coral_button_hover_color: $coral_button_border_color;
|
||||
$coral_button_invert_border_color: lighten($coral_button_border_color, 20%);
|
||||
$coral_button_invert_color: white;
|
||||
$coral_button_invert_hover_color: $coral_button_invert_border_color;
|
||||
|
||||
// // Code
|
||||
|
||||
$hljs_string_color: $coral_light_blue;
|
||||
$code_background: $coral_light_gray;
|
||||
$code_border: 0;
|
||||
$copy_button_color: white;
|
||||
$copy_button_background: $coral_light_blue;
|
||||
|
||||
// // Call out
|
||||
|
||||
$callout_color: white;
|
||||
$callout_background: $coral_dark_blue;
|
||||
$callout_link_color: darken($callout_color, 20%);
|
||||
$callout_link_hover_color: darken($callout_link_color, 5%);
|
||||
|
||||
// // Buttons
|
||||
|
||||
$coral_button_background: $coral_light_blue;
|
||||
$coral_button_color: $coral_orange;
|
||||
$coral_button_hover_color: darken($coral_button_background, 5%);
|
||||
$coral_button_invert_color: $coral_dark_gray;
|
||||
$coral_button_invert_hover_color: lighten($coral_button_invert_color, 20%);
|
||||
|
||||
// // Search
|
||||
|
||||
$algolia_suggestion_highlight_color: $coral_light_blue;
|
||||
$algolia_suggestion_highlight_background: fade-out(
|
||||
$algolia_suggestion_highlight_color,
|
||||
0.9
|
||||
);
|
||||
|
||||
// // Navigation
|
||||
|
||||
$header_nav_link_color: $coral_dark_gray;
|
||||
$header_nav_icon_color: $coral_dark_gray;
|
||||
|
||||
+62
-59
@@ -3,7 +3,7 @@
|
||||
@import "hljs";
|
||||
|
||||
body {
|
||||
font-family: 'Open Sans';
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
font-weight: 400;
|
||||
@@ -58,31 +58,20 @@ h4 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-coral {
|
||||
color: white;
|
||||
background: $coral_button_background;
|
||||
border: 1px solid $coral_button_border;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
background: darken($coral_button_background, 5%);
|
||||
border-color: darken($coral_button_border, 5%);
|
||||
}
|
||||
}
|
||||
|
||||
.param {
|
||||
font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
|
||||
monospace;
|
||||
}
|
||||
|
||||
article.configuration {
|
||||
h2, .toc {
|
||||
h2,
|
||||
.toc {
|
||||
@extend .param;
|
||||
}
|
||||
}
|
||||
|
||||
.suggest-edits {
|
||||
padding: .20rem .5rem;
|
||||
padding: 0.2rem 0.5rem;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,14 +80,14 @@ article.configuration {
|
||||
|
||||
.demo {
|
||||
background: $coral_orange;
|
||||
border: 1px solid $demo_border;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
margin-bottom: 1rem;
|
||||
max-width: 650px;
|
||||
|
||||
.btn, .alert {
|
||||
.btn,
|
||||
.alert {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
@@ -109,7 +98,6 @@ article.configuration {
|
||||
}
|
||||
|
||||
.mount {
|
||||
border-top: 1px solid $demo_border;
|
||||
display: none;
|
||||
background: white;
|
||||
padding: 10px;
|
||||
@@ -123,6 +111,7 @@ article.configuration {
|
||||
background: $copy_button_background;
|
||||
padding: 3px 10px;
|
||||
border: $code_border;
|
||||
color: $copy_button_color;
|
||||
|
||||
&:hover {
|
||||
background: darken($copy_button_background, 10%);
|
||||
@@ -142,7 +131,6 @@ pre {
|
||||
color: #212529;
|
||||
position: relative;
|
||||
|
||||
|
||||
& > code {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
@@ -196,8 +184,8 @@ pre {
|
||||
left: 0 !important;
|
||||
|
||||
.algolia-docsearch-suggestion--highlight {
|
||||
color: $coral_orange;
|
||||
background: fade-out($coral_orange, 0.9);
|
||||
color: $algolia_suggestion_highlight_color;
|
||||
background: $algolia_suggestion_highlight_background;
|
||||
}
|
||||
|
||||
.ds-dropdown-menu {
|
||||
@@ -207,7 +195,7 @@ pre {
|
||||
|
||||
// Hide the carrot.
|
||||
&:before {
|
||||
display: none
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Fix for smaller screens.
|
||||
@@ -215,7 +203,6 @@ pre {
|
||||
min-width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.header--toggled {
|
||||
@@ -232,7 +219,7 @@ pre {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
margin-left: 15px;
|
||||
color: $coral_orange;
|
||||
color: $header_nav_link_color;
|
||||
white-space: nowrap;
|
||||
|
||||
& > svg {
|
||||
@@ -240,12 +227,12 @@ pre {
|
||||
width: 20px;
|
||||
|
||||
rect {
|
||||
fill: $coral_orange;
|
||||
fill: $header_nav_icon_color;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: darken($coral_orange, 10%);
|
||||
color: darken($header_nav_icon_color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -262,7 +249,6 @@ pre {
|
||||
}
|
||||
|
||||
.coral-link {
|
||||
border-bottom: 1px solid $coral_button_border_color;
|
||||
color: $coral_button_color;
|
||||
text-decoration: none;
|
||||
|
||||
@@ -274,7 +260,6 @@ pre {
|
||||
|
||||
.coral-link-invert {
|
||||
@extend .coral-link;
|
||||
border-color: $coral_button_invert_border_color;
|
||||
color: $coral_button_invert_color;
|
||||
|
||||
&:hover {
|
||||
@@ -310,6 +295,7 @@ a.brand {
|
||||
padding: $sidebar_gutter;
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
min-height: 90px;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
@@ -328,15 +314,9 @@ a.brand {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.logo {
|
||||
img {
|
||||
vertical-align: middle;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
@include transition(all, 250ms);
|
||||
|
||||
&:hover {
|
||||
@include transform(rotate(8deg));
|
||||
}
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,6 +338,9 @@ a.brand {
|
||||
color: $sidebar_color;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
@@ -369,7 +352,7 @@ a.brand {
|
||||
@media (max-width: $breakpoint) {
|
||||
&.sidebar--toggled {
|
||||
@include transform(translate3d(0, 0, 0));
|
||||
box-shadow: 0 0 30px rgba(0,0,0,0.3);
|
||||
box-shadow: 0 0 30px rgba(0, 0, 0, 0.3);
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
@@ -382,26 +365,49 @@ a.brand {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.notice {
|
||||
padding: $sidebar_gutter $sidebar_gutter 0;
|
||||
color: fade-out($sidebar_color, 0.5);
|
||||
}
|
||||
|
||||
.sidebar__section {
|
||||
list-style: none;
|
||||
border-bottom: 1px solid lighten($sidebar_background, 3%);
|
||||
|
||||
&.active {
|
||||
.sidebar__header {
|
||||
background-color: darken($sidebar_background, 2%);
|
||||
}
|
||||
}
|
||||
|
||||
&.toggled {
|
||||
& > .sidebar__header {
|
||||
background: darken($sidebar_background, 10%);
|
||||
// color: white;
|
||||
}
|
||||
|
||||
.sidebar__subsection {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar__links {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
& > .sidebar__header {
|
||||
background: darken($sidebar_background, 30%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar__subsection {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar__subsection {
|
||||
list-style: none;
|
||||
|
||||
&.active {
|
||||
& > .sidebar__header {
|
||||
color: fade-out($sidebar_color, 0.3);
|
||||
background-color: darken($sidebar_background, 2%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar__headers {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a.sidebar__header {
|
||||
@@ -425,7 +431,6 @@ a.brand {
|
||||
overflow-y: hidden;
|
||||
|
||||
& > li {
|
||||
|
||||
& > a {
|
||||
display: block;
|
||||
padding: 6px $sidebar_gutter;
|
||||
@@ -438,11 +443,11 @@ a.brand {
|
||||
}
|
||||
|
||||
&.active > a {
|
||||
color: fade-out($sidebar_color, 0.3);
|
||||
color: fade-out($sidebar_color, 0.2);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: darken($sidebar_background, 5%);
|
||||
background: darken($sidebar_background, 1%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -467,20 +472,18 @@ a.brand {
|
||||
}
|
||||
|
||||
.callout {
|
||||
background-color: $coral_button_background;
|
||||
color: white;
|
||||
background-color: $callout_background;
|
||||
color: $callout_color;
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
@extend .coral-link;
|
||||
color: #FFF;
|
||||
border-color: #FFF;
|
||||
color: $callout_link_color;
|
||||
|
||||
&:hover {
|
||||
color: #FFF;
|
||||
border-color: darken(#FFF, 5%);
|
||||
color: $callout_link_hover_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.5 KiB |
-41
@@ -1,41 +0,0 @@
|
||||
<svg version="1.1" class="logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 255 255" style="enable-background:new 0 0 255 255;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<title>Artboard 1</title>
|
||||
<g>
|
||||
<path class="st0" d="M163.5,38.1c-2.8,12.8-2.1,21.9,2.1,26.9c5.6,6.7,18.4,5.6,25.7,0.2c5.8-4.3,7.7-12.3,8.9-19.6
|
||||
c0.2-1.5,0.4-3.4,0.6-5.3c0.7-8.6,1.8-21.6,13.4-27c16.8-7.9,31.6,9.5,39.7,18.9c0.5,0.6,1.2,1.1,1.2,1.6v-8.9
|
||||
c0.1-13.6-10.8-24.7-24.3-24.8c-0.1,0-0.2,0-0.3,0h-43.7C174.1,12,166.5,24.4,163.5,38.1z"/>
|
||||
<path class="st0" d="M255,198.2v-38.5c-16,2.7-31.2-1.1-45.9-4.9c-7.3-2-14.7-3.6-22.1-4.8c-11.6-1.5-20.6,3.8-24.9,14.6
|
||||
c-6,15.2,7,25.6,25.9,38.7c5.6,3.9,10.5,7.2,14.1,10.7c7.1-7.6,15-12.5,23.8-14.5C235.8,197.3,246,197.6,255,198.2z"/>
|
||||
<path class="st0" d="M153.8,99.7c1.3,1,2.7,1.9,4.2,2.7c6,3.4,10.6,4.2,16.4,2.8c1.1-0.3,2.3-0.6,3.4-0.9c4.6-1.2,9.7-2.6,15.3-2.2
|
||||
c7.8,0.4,14.4,4,20.6,7.6l0.6,0.3c4.7,2.8,9.2,5.4,13.7,6c6.3,0.9,11.2-4.9,17.5-13.1l0.5-0.7c0.6-0.8,1.2-1.8,2-2.8
|
||||
c2.6-3.2,4.9-6.5,7-10.1V57.8c-1-2.2-3.4-4.5-5-6.7s-3.3-4.6-5.1-6.5c-0.7-0.8-1.4-1.7-2.2-2.6c-5.1-5.9-15.6-18.1-22.1-15.1
|
||||
c-3.5,1.6-4.2,7.1-4.8,14.7c-0.2,2.2-0.4,4.4-0.7,6.4c-1.5,9.6-4.6,21.9-14.7,29.4c-6.7,4.9-14.7,7.5-23,7.6l0,0
|
||||
c-9.6,0-17.8-3.8-23.2-10.3c-7.4-8.9-9.1-21.9-5.2-39.7c2.7-12.5,8.4-24,17.4-35h-33.5c-2.3,13-4.4,31.6-2.6,49.7
|
||||
C132.4,73.1,140.4,89.9,153.8,99.7z"/>
|
||||
<path class="st0" d="M81,130.4l3.4,0.4c1.9,0.2,4,0.6,6.2,1c8.1,1.4,19.2,3.4,22.5-1.6c2.7-4.1-0.8-12.9-5.7-18.2
|
||||
c-3.5-3.8-7.9-6.9-12.5-10.2c-2.7-1.9-5.5-3.9-8.2-6.1c-6.4-5.2-13.3-12.8-9.4-25.4c1.3-3.8,3-7.4,5-10.8c1.9-3.4,3.5-6.3,4.2-9.5
|
||||
c1.1-5.6-1.6-16.6-6.7-22c-2.7-2.8-4.7-2.8-6.1-2.6C62.8,27,58.7,38.5,54.1,54.6c-1.1,3.8-2.1,7.3-3.3,10.5l-0.1,0.4
|
||||
c-3.2,8.8-8,22.1-20.7,25.6C19.4,94,9,89,0,82.8v32c3,6,8,11.9,14.7,17.8c5.5,4.6,11.4,8.8,17.6,12.3c3.9-6.3,9.9-11.1,16.9-13.6
|
||||
C60,127.5,71.1,129,81,130.4z"/>
|
||||
<path class="st0" d="M229.2,214.2c-6.6,1.5-12.5,5.4-18.1,12.1c4.9,9,8.5,18.7,10.6,28.8h8.6c13.5,0,24.6-10.9,24.6-24.4
|
||||
c0-0.1,0-0.2,0-0.3v-17C246,212.7,237.5,212.3,229.2,214.2z"/>
|
||||
<path class="st0" d="M26,76.6c5.2-1.4,8.3-10,10.5-16.2l0.1-0.4c1-2.8,2-6.1,3-9.6c4.5-15.5,10.6-36.8,31.8-39.9
|
||||
c7-1,13.8,1.6,19.1,7.2c9,9.5,12.4,25.6,10.5,35.2c-1.1,5.4-3.6,9.9-5.8,13.8c-1.5,2.5-2.8,5.2-3.8,8c-0.9,3-0.8,5,4.6,9.3
|
||||
c2.3,1.9,4.8,3.7,7.5,5.6c5,3.6,10.2,7.3,14.7,12.2c7.4,7.9,15.4,24.3,7.3,36.7c-8.8,13.3-26.2,10.2-37.7,8.1
|
||||
c-2-0.4-3.9-0.7-5.5-0.9l-3.5-0.5c-8.6-1.2-17.5-2.4-24.9,0.1c-7.1,2.4-12.6,10.7-12.8,19.3c-0.1,3.8,0.8,10.5,8.3,13.5
|
||||
c9.2,3.7,19.4,3.3,30.2,2.8c11.6-0.5,23.6-1,35.5,3.5c16,6.1,30.6,20.4,38,37.7c4.8,11.1,6.3,22.8,4.4,32.8h48.8
|
||||
c-2-8-6.4-21.3-14.1-29.7c-2.5-2.8-7.5-6.1-12.8-9.8c-16.8-11.6-42.1-29.1-31.3-56.5c6.8-17.2,22.4-26.3,40.8-23.9
|
||||
c8.3,1.1,16.1,3.1,23.8,5.1c14.5,3.7,28.2,7.2,42.2,4.1v-29.9c-5,7.5-13.8,16.5-25.8,16.5c-1.1,0-2.3-0.1-3.4-0.2
|
||||
c-7.4-1-13.6-4.7-19.1-7.9l-0.6-0.3c-4.8-2.8-9.4-5.3-13.9-5.6c-3.2-0.2-6.8,0.8-10.6,1.8c-1.3,0.3-2.5,0.7-3.8,1
|
||||
c-9.5,2.3-17.9,0.9-27.3-4.3c-1.9-1.1-3.8-2.3-5.6-3.6c-17-12.4-27-32.7-29.7-60.6c-1.8-18.6,0-37.2,2.3-51.2H25
|
||||
C11.2,0,0.1,11.1,0,24.8v38.8C7,70,18.4,78.7,26,76.6z"/>
|
||||
<path class="st0" d="M62.8,231.9c-20.2-1.1-32.2-2.7-43.4-23.9c-1.9-3.7-0.5-8.2,3.1-10.1c3.7-1.9,8.2-0.5,10.1,3.1
|
||||
c7.5,14.2,12.6,14.9,31,15.9c14.4,0.8,26.2,14.1,35,38.1h43.7c2.1-8,1.2-17.6-2.8-26.9c-5.9-13.6-17.2-24.9-29.6-29.6
|
||||
c-9-3.4-19-3-29.5-2.5C68.5,196.4,56.2,197,44,192c-11.4-4.6-18-15-17.6-27.9c0-1.8,0.2-3.6,0.5-5.3C17.1,153.6,8.1,147,0,139.4
|
||||
v90.8C0.1,244,11.2,255.1,25,255c0,0,0,0,0,0h57.5C78.3,245,71.4,232.3,62.8,231.9z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -8,7 +8,7 @@ const {
|
||||
SUBSCRIBE_ALL_USERNAME_CHANGED,
|
||||
SUBSCRIBE_ALL_USERNAME_FLAGGED,
|
||||
SUBSCRIBE_ALL_USERNAME_REJECTED,
|
||||
SUBSCRIBE_COMMENT_ACCEPTED,
|
||||
SUBSCRIBE_ALL_COMMENT_ACCEPTED,
|
||||
SUBSCRIBE_COMMENT_FLAGGED,
|
||||
SUBSCRIBE_COMMENT_REJECTED,
|
||||
SUBSCRIBE_COMMENT_RESET,
|
||||
@@ -64,10 +64,14 @@ const setupFunctions = {
|
||||
return !args.asset_id || comment.asset_id === args.asset_id;
|
||||
},
|
||||
commentAccepted: (options, args, comment, context) => {
|
||||
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_ACCEPTED)) {
|
||||
return false;
|
||||
if (args.asset_id) {
|
||||
// Allow sending back the comment for the user that has filtered based
|
||||
// on a specific asset.
|
||||
return comment.asset_id === args.asset_id;
|
||||
} else {
|
||||
// Only privileged users can subscribe to all assets.
|
||||
return context.user && context.user.can(SUBSCRIBE_ALL_COMMENT_ACCEPTED);
|
||||
}
|
||||
return !args.asset_id || comment.asset_id === args.asset_id;
|
||||
},
|
||||
commentRejected: (options, args, comment, context) => {
|
||||
if (!context.user || !context.user.can(SUBSCRIBE_COMMENT_REJECTED)) {
|
||||
|
||||
@@ -312,7 +312,6 @@ ar:
|
||||
button: أرسل
|
||||
error: 'يمكن أن تحتوي أسماء المستخدمين على أحرف, أرقام و _ فقط'
|
||||
label: 'اسم مستخدم جديد'
|
||||
msg: 'تم تعليق حسابك حاليا نظرا لأن اسم المستخدم قد اعتبر غير لائق. لاستعادة حسابك، يرجى إدخال اسم مستخدم جديد. يرجى الاتصال بنا إذا كان لديك أي أسئلة.'
|
||||
my_comments: تعليقاتي
|
||||
my_profile: ملفي
|
||||
new_count: 'شاهد {0} أكثر {1}'
|
||||
@@ -559,4 +558,3 @@ ar:
|
||||
view_conversation: 'عرض المحادثة'
|
||||
your_account_has_been_banned: 'تم حظر حسابك.'
|
||||
your_account_has_been_suspended: 'تم تعليق حسابك مؤقتا.'
|
||||
your_username_has_been_rejected: 'تم تعليق حسابك لعدم صلاحية اسم المستخدم الخاصة بك. لاستعادة حسابك رجاء أدخل اسم مستخدم جديدة.'
|
||||
|
||||
@@ -266,7 +266,6 @@ da:
|
||||
button: Indsend
|
||||
error: 'Brugernavne kan kun indeholde bogstaver og _'
|
||||
label: 'Nyt brugernavn'
|
||||
msg: 'Din konto er midlertidigt suspenderet, fordi dit brugernavn er blevet anset for upassende. For at gendanne din konto skal du indtaste et nyt brugernavn. Kontakt os venligst, hvis du har spørgsmål.'
|
||||
my_comments: 'Mine kommentarer'
|
||||
my_profile: 'Min profil'
|
||||
new_count: 'Se {0} mere {1}'
|
||||
@@ -473,4 +472,3 @@ da:
|
||||
view_conversation: 'Vis samtale'
|
||||
your_account_has_been_banned: 'Din konto er blevet banned.'
|
||||
your_account_has_been_suspended: 'Din konto er midlertidigt suspenderet'
|
||||
your_username_has_been_rejected: 'Din konto er blevet suspenderet fordi dit brugernavn er blevet anset for upassende. For at gendanne din konto, venligst indtast et nyt brugernavn.'
|
||||
|
||||
@@ -337,7 +337,6 @@ de:
|
||||
button: Senden
|
||||
error: 'Nutzernamen dürfen nur Buchstaben, Zahlen und _ enthalten'
|
||||
label: 'Neuer Nutzername'
|
||||
msg: 'Ihr Konto ist vorübergehend gesperrt, da Ihr Nutzername als unangemessen eingestuft wurde. Um Ihr Konto wieder herzustellen, geben Sie bitte einen neuen Nutzernamen ein. Bei Fragen, kontaktieren Sie uns bitte.'
|
||||
my_comments: 'Meine Kommentare'
|
||||
my_profile: 'Mein Profil'
|
||||
new_count: '{0} {1} mehr anzeigen'
|
||||
@@ -593,4 +592,3 @@ de:
|
||||
view_conversation: 'Diskussion ansehen'
|
||||
your_account_has_been_banned: 'Ihr Zugang wurde gesperrt.'
|
||||
your_account_has_been_suspended: 'Ihr Zugang wurde vorübergehend gesperrt.'
|
||||
your_username_has_been_rejected: 'Ihr Zugang wurde vorübergehend gesperrt, da Ihr Nutzername als unangemessen eingestuft wurde. Um Ihren Zugang wieder herzustellen, geben Sie bitte einen neuen Nutzernamen ein.'
|
||||
|
||||
+2
-2
@@ -337,7 +337,7 @@ en:
|
||||
button: Submit
|
||||
error: 'Usernames can contain letters numbers and _ only'
|
||||
label: 'New Username'
|
||||
msg: 'Your account is currently suspended because your username has been deemed inappropriate. To restore your account please enter a new username. Please contact us if you have any questions.'
|
||||
rejected: 'Your choice of username has been rejected because it is not in line with our username policies. Please submit another name for moderator approval.'
|
||||
my_comments: 'My Comments'
|
||||
my_profile: 'My profile'
|
||||
new_count: 'View {0} more {1}'
|
||||
@@ -593,4 +593,4 @@ en:
|
||||
view_conversation: 'View Conversation'
|
||||
your_account_has_been_banned: 'Your account has been banned.'
|
||||
your_account_has_been_suspended: 'Your account has been temporarily suspended.'
|
||||
your_username_has_been_rejected: 'Your account has been suspended because your username has been deemed inappropriate. To restore your account please enter a new username.'
|
||||
your_username_has_been_rejected_not_in_line: 'Your choice of username has been rejected because it is not in line with our username policies. Please submit another name for moderator approval.'
|
||||
|
||||
@@ -309,7 +309,6 @@ es:
|
||||
button: Enviar
|
||||
error: 'Nombres de usuarios pueden solamente incluir letras, números y _'
|
||||
label: 'Nuevo Nombre'
|
||||
msg: 'Tu cuenta está suspendida porque tu nombre de usuario ha sido considerado no apropiado para el espacio. Para recuperar la cuenta, por favor ingresar un nuevo nombre de usuario. Contáctanos si tienes alguna pregunta.'
|
||||
my_comments: 'Mis Comentarios'
|
||||
my_profile: 'Mi perfil'
|
||||
new_count: 'Ver {0} más {1} '
|
||||
@@ -542,4 +541,3 @@ es:
|
||||
view_conversation: 'Ver Conversación'
|
||||
your_account_has_been_banned: 'Su cuenta ha sido prohibida.'
|
||||
your_account_has_been_suspended: 'Su cuenta ha sido suspendida.'
|
||||
your_username_has_been_rejected: 'Su cuenta ha sido suspendida porque tu nombre de usuario ha sido considerado no apropiado para el espacio. Para recuperar la cuenta, por favor ingresar un nuevo nombre de usuario.'
|
||||
|
||||
@@ -269,7 +269,6 @@ fi_FI:
|
||||
button: Lähetä
|
||||
error: 'Käyttäjänimissä sallittuja merkkejä ovat ainoastaan kirjaimet, numerot, sekä alaviiva'
|
||||
label: 'Uusi käyttäjänimi'
|
||||
msg: 'Tilisi on suljettu väliaikaisesti, koska käyttäjänimi on todettu sopimattomaksi. Vaihda käyttäjänimi, jos haluat jatkaa tilin käyttöä. Ole meihin yhteydessä, jos sinulla on aiheesta kysyttävää.'
|
||||
my_comments: Kommenttini
|
||||
my_profile: Profiilini
|
||||
new_count: 'Näytä {0} lisää {1}'
|
||||
@@ -466,4 +465,3 @@ fi_FI:
|
||||
view_conversation: 'Näytä keskustelu'
|
||||
your_account_has_been_banned: 'Tilillesi on asetettu kirjoituskielto.'
|
||||
your_account_has_been_suspended: 'Tilisi on väliaikasesti suljettu.'
|
||||
your_username_has_been_rejected: 'Tilisi on suljettu, koska käyttäjänimesi on epäsopiva. Vaihda käyttäjänimeä jatkaaksesi tilin käyttöä.'
|
||||
|
||||
@@ -264,7 +264,6 @@ fr:
|
||||
button: Soumettre
|
||||
error: 'Les noms d''utilisateur ne peuvent contenir que des chiffres, des lettres et "_"'
|
||||
label: 'Nouveau nom d''utilisateur'
|
||||
msg: 'Votre compte est actuellement suspendu car votre nom d''utilisateur a été jugé inapproprié. Pour restaurer votre compte, entrez un nouveau nom d''utilisateur. Contactez-nous si vous avez des questions.'
|
||||
my_comments: 'Mes commentaires'
|
||||
my_profile: 'Mon profil'
|
||||
new_count: 'Voir {0} plus {1}'
|
||||
@@ -462,4 +461,3 @@ fr:
|
||||
view_conversation: 'Afficher la conversation'
|
||||
your_account_has_been_banned: 'Votre compte a été banni.'
|
||||
your_account_has_been_suspended: 'Votre compte a été temporairement suspendu.'
|
||||
your_username_has_been_rejected: 'Votre compte a été suspendu en raison de votre nom d’utilisateur jugé inapproprié. Veuillez saisir un nouveau nom d’utilisateur pour restaurer votre compte.'
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
he:
|
||||
your_account_has_been_suspended: החשבון שלך הושעה באופן זמני.
|
||||
your_account_has_been_banned: החשבון שלך הורחק.
|
||||
your_username_has_been_rejected: החשבון שלך הושעה מפני ששם המשתמש שלך נחשב לא הולם. כדי לשחזר את החשבון שלך, הזן שם משתמש חדש.
|
||||
embed_comments_tab: תגובות
|
||||
bandialog:
|
||||
are_you_sure: "האם אתה בטוח שאתה רוצה לאסור {0}?"
|
||||
@@ -260,7 +259,6 @@ he:
|
||||
button: שלח
|
||||
error: "שמות משתמש יכולים להכיל מספרי אותיות ו- _ בלבד"
|
||||
label: "שם משתמש חדש"
|
||||
msg: "החשבון שלך מושעה כרגע מפני ששם המשתמש שלך נחשב לא הולם. כדי לשחזר את החשבון שלך, הזן שם משתמש חדש. אנא צור איתנו קשר אם יש לך שאלות."
|
||||
changed_name:
|
||||
msg: "שינוי שם המשתמש שלך נמצא בבדיקה על ידי צוות הניהול שלנו."
|
||||
my_comments: "התגובות שלי"
|
||||
|
||||
@@ -321,7 +321,6 @@ it:
|
||||
button: Invia
|
||||
error: 'L''username può contenere solo lettere numeri o _'
|
||||
label: 'Nuovo username'
|
||||
msg: 'Il tuo account è attualmente sospeso perchè il tuo username è considerato inappropriato. Per ripristinare il tuo account inserisci un nuovo username. Contattaci se hai qualche domanda.'
|
||||
my_comments: 'I miei commenti'
|
||||
my_profile: 'Il mio profilo'
|
||||
new_count: 'Visualizza {0} e {1}'
|
||||
@@ -571,4 +570,3 @@ it:
|
||||
view_conversation: 'Visualizza conversazione'
|
||||
your_account_has_been_banned: 'Il tuo account è stato bloccato.'
|
||||
your_account_has_been_suspended: 'Il tuo account è stato temporaneamente sospeso.'
|
||||
your_username_has_been_rejected: 'Il tuo account è stato sospeso perchè il tuo username è ritenuto inappropriato. Per ripristinare il tuo account inserisci un nuovo username.'
|
||||
|
||||
@@ -324,7 +324,6 @@ nl_NL:
|
||||
button: Versturen
|
||||
error: "Gebruikersnamen kunnen alleen cijfers, letters en _ bevatten."
|
||||
label: "Nieuwe gebruikersnaam"
|
||||
msg: "Je account is momenteel geschorst omdat je gebruikersnaam ongepast is bevonden. Om je account te herstellen, moet je je gebruikersnaam herstellen. Neem contact met ons op wanneer je vragen hebt."
|
||||
my_comments: "Mijn reacties"
|
||||
my_profile: "Mijn profiel"
|
||||
new_count: "Bekijk {0} meer {1}"
|
||||
@@ -574,4 +573,3 @@ nl_NL:
|
||||
view_conversation: "Bekijk conversatie"
|
||||
your_account_has_been_banned: "Je account is verbannen."
|
||||
your_account_has_been_suspended: "Je account is tijdelijk geschorst."
|
||||
your_username_has_been_rejected: "Je account is geschorst omdat we je gebruikersnaam ongepast vinden. Verander je gebruikersnaam om hem weer te activeren."
|
||||
|
||||
@@ -285,7 +285,6 @@ pt_BR:
|
||||
button: Enviar
|
||||
error: 'Nomes de usuários podem conter números de letras e _ somente'
|
||||
label: 'Novo usuário'
|
||||
msg: 'Sua conta está suspensa porque seu nome de usuário foi considerado inapropriado. Para restaurar sua conta, insira um novo nome de usuário. Entre em contato conosco se você tiver alguma dúvida.'
|
||||
my_comments: 'Meus comentários'
|
||||
my_profile: 'Meu perfil'
|
||||
new_count: 'Ver {0} {1}'
|
||||
@@ -522,4 +521,3 @@ pt_BR:
|
||||
view_conversation: 'Ver conversa'
|
||||
your_account_has_been_banned: 'Sua conta foi banida.'
|
||||
your_account_has_been_suspended: 'Sua conta foi temporariamente suspensa.'
|
||||
your_username_has_been_rejected: 'Sua conta foi rejeitada porque seu nome de usuário foi considerado inapropriado. Para restaurar sua conta, insira um novo nome de usuário.'
|
||||
|
||||
@@ -323,7 +323,6 @@ sr:
|
||||
button: 'Podnesi'
|
||||
error: 'Došlo je do greške'
|
||||
label: 'Novo korisničko ime'
|
||||
msg: 'Izmjena vašeg korisničkog imena prolazi provjeru našeg tima moderatora'
|
||||
my_comments: 'Moji komentari'
|
||||
my_profile: 'Moj profil'
|
||||
new_count: 'Vidi još {0} / {1}'
|
||||
@@ -573,4 +572,3 @@ sr:
|
||||
view_conversation: 'Vidi razgovor'
|
||||
your_account_has_been_banned: 'Vaš nalog je banovan'
|
||||
your_account_has_been_suspended: 'Vaš nalog je privremeno suspendovan'
|
||||
your_username_has_been_rejected: 'Vaš nalog je suspendovan jer je korisničko ime označeno kao neprikladno. Da povratite nalog, unesite novo korisničko ime'
|
||||
|
||||
@@ -232,7 +232,6 @@ zh_CN:
|
||||
button: 提交
|
||||
error: 用户名只能包含字母、数字跟下划线
|
||||
label: 新用户名
|
||||
msg: 由于您的用户名不当,您的帐号目前被暂停使用。如要恢复您的帐户,请输入一个新的用户名。如有任何疑问,请与我们联系。
|
||||
my_comments: 我的评论
|
||||
my_profile: 我的资料
|
||||
new_count: '查看 {0} 更多 {1}'
|
||||
@@ -411,4 +410,3 @@ zh_CN:
|
||||
view_conversation: 查看对话
|
||||
your_account_has_been_banned: 您的帐户已被禁用。
|
||||
your_account_has_been_suspended: 您的帐户已被暂时停用。
|
||||
your_username_has_been_rejected: 由于您使用了不恰当的用户名,您的帐户已被暂停使用。若需恢复帐户,请输入一个新的用户名
|
||||
|
||||
@@ -228,7 +228,6 @@ zh_TW:
|
||||
button: 提交
|
||||
error: 用戶名只能包含字母、數字和下劃線。
|
||||
label: 新用戶名
|
||||
msg: 由於您的用戶名不當,您的帳號目前已被暫停使用。如要恢復您的帳戶,請輸入一個新的用戶名。如有任何疑問,請與我們聯繫。
|
||||
my_comments: 我的評論
|
||||
my_profile: 我的概況
|
||||
new_count: '查看{0}更多{1}'
|
||||
@@ -407,4 +406,3 @@ zh_TW:
|
||||
view_conversation: 查看對話
|
||||
your_account_has_been_banned: 您的賬戶已被禁用。
|
||||
your_account_has_been_suspended: 您的賬戶已被暫停使用。
|
||||
your_username_has_been_rejected: 由於您使用了不恰當的用戶名,您的帳戶已被暫停使用。若需恢復帳戶,請輸入一個新的用戶名。
|
||||
|
||||
@@ -41,4 +41,7 @@ const Action = new Schema(
|
||||
}
|
||||
);
|
||||
|
||||
// Indexes for listing users actions.
|
||||
Action.index({ user_id: 1, item_type: 1 }, { background: true });
|
||||
|
||||
module.exports = Action;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[build]
|
||||
command = "yarn generate-introspection && cd docs && yarn build"
|
||||
publish = "docs/public"
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "talk",
|
||||
"version": "4.10.1",
|
||||
"description": "A better commenting experience from Mozilla, The New York Times, and the Washington Post. https://coralproject.net",
|
||||
"version": "4.11.4",
|
||||
"description": "A better commenting experience from Vox Media.",
|
||||
"main": "app.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -251,6 +251,6 @@
|
||||
"yaml-lint": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": "~8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
SUBSCRIBE_COMMENT_ACCEPTED: 'SUBSCRIBE_COMMENT_ACCEPTED',
|
||||
SUBSCRIBE_ALL_COMMENT_ACCEPTED: 'SUBSCRIBE_ALL_COMMENT_ACCEPTED',
|
||||
SUBSCRIBE_COMMENT_REJECTED: 'SUBSCRIBE_COMMENT_REJECTED',
|
||||
SUBSCRIBE_COMMENT_FLAGGED: 'SUBSCRIBE_COMMENT_FLAGGED',
|
||||
SUBSCRIBE_COMMENT_RESET: 'SUBSCRIBE_COMMENT_RESET',
|
||||
|
||||
@@ -4,7 +4,7 @@ const types = require('../constants');
|
||||
module.exports = (user, perm) => {
|
||||
switch (perm) {
|
||||
case types.SUBSCRIBE_COMMENT_FLAGGED:
|
||||
case types.SUBSCRIBE_COMMENT_ACCEPTED:
|
||||
case types.SUBSCRIBE_ALL_COMMENT_ACCEPTED:
|
||||
case types.SUBSCRIBE_COMMENT_REJECTED:
|
||||
case types.SUBSCRIBE_COMMENT_RESET:
|
||||
case types.SUBSCRIBE_ALL_COMMENT_EDITED:
|
||||
|
||||
@@ -21,17 +21,6 @@ function getReactionConfig(reaction) {
|
||||
background: true,
|
||||
}
|
||||
);
|
||||
|
||||
Comment.collection.ensureIndex(
|
||||
{
|
||||
asset_id: 1,
|
||||
[`action_counts.${sc(reaction)}`]: -1,
|
||||
created_at: -1,
|
||||
},
|
||||
{
|
||||
background: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const reactionPlural = pluralize(reaction);
|
||||
|
||||
@@ -36,17 +36,32 @@
|
||||
}
|
||||
|
||||
.button {
|
||||
color: #787D80;
|
||||
background-color: #3498db;
|
||||
border-radius: 2px;
|
||||
background-color: transparent;
|
||||
height: 30px;
|
||||
font-size: 0.9em;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
background-color: #3498DB;
|
||||
border: 0;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.cancel {
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 2px;
|
||||
border: 0;
|
||||
color: #4f5c67;
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
height: 30px;
|
||||
margin-top: 5px;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -14,10 +14,10 @@ import {
|
||||
} from 'coral-framework/lib/validation';
|
||||
import { Form, Field } from 'react-final-form';
|
||||
|
||||
const AddEmailContent = ({ onSubmit }) => (
|
||||
const AddEmailContent = ({ onSubmit, onCancel }) => (
|
||||
<div>
|
||||
<h4 className={styles.title}>
|
||||
{t('talk-plugin-local-auth.add_email.content.title')}
|
||||
{t('talk-plugin-local-auth.add_email.title')}
|
||||
</h4>
|
||||
<p className={styles.description}>
|
||||
{t('talk-plugin-local-auth.add_email.content.description')}
|
||||
@@ -113,6 +113,14 @@ const AddEmailContent = ({ onSubmit }) => (
|
||||
<button className={styles.button} disabled={submitting}>
|
||||
{t('talk-plugin-local-auth.add_email.add_email_address')}
|
||||
</button>
|
||||
<button
|
||||
onClick={onCancel}
|
||||
className={styles.cancel}
|
||||
disabled={submitting}
|
||||
type="button"
|
||||
>
|
||||
{t('talk-plugin-local-auth.add_email.cancel')}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
)}
|
||||
@@ -122,6 +130,7 @@ const AddEmailContent = ({ onSubmit }) => (
|
||||
|
||||
AddEmailContent.propTypes = {
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default AddEmailContent;
|
||||
|
||||
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
||||
import { compose, gql } from 'react-apollo';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { connect, withFragments, excludeIf } from 'plugin-api/beta/client/hocs';
|
||||
import { logout } from 'plugin-api/beta/client/actions/auth';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
import { withAttachLocalAuth } from '../hocs';
|
||||
import { startAttach, finishAttach } from '../actions';
|
||||
@@ -58,6 +59,10 @@ class AddEmailAddressDialog extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
handleOnCancel = async () => {
|
||||
this.props.logout();
|
||||
};
|
||||
|
||||
goToNextStep = () => {
|
||||
this.setState(({ step }) => ({
|
||||
step: step + 1,
|
||||
@@ -79,7 +84,12 @@ class AddEmailAddressDialog extends React.Component {
|
||||
id="talk-plugin-local-auth-email-dialog"
|
||||
className={styles.dialog}
|
||||
>
|
||||
{step === 0 && <AddEmailForm onSubmit={this.handleSubmit} />}
|
||||
{step === 0 && (
|
||||
<AddEmailForm
|
||||
onSubmit={this.handleSubmit}
|
||||
onCancel={this.handleOnCancel}
|
||||
/>
|
||||
)}
|
||||
{step === 1 &&
|
||||
!requireEmailConfirmation && (
|
||||
<EmailAddressAdded onDone={this.handleDone} />
|
||||
@@ -98,6 +108,7 @@ AddEmailAddressDialog.propTypes = {
|
||||
notify: PropTypes.func.isRequired,
|
||||
startAttach: PropTypes.func.isRequired,
|
||||
finishAttach: PropTypes.func.isRequired,
|
||||
logout: PropTypes.func.isRequired,
|
||||
root: PropTypes.object,
|
||||
};
|
||||
|
||||
@@ -106,7 +117,7 @@ const mapStateToProps = ({ talkPluginLocalAuth: state }) => ({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators({ notify, startAttach, finishAttach }, dispatch);
|
||||
bindActionCreators({ notify, startAttach, finishAttach, logout }, dispatch);
|
||||
|
||||
const withData = withFragments({
|
||||
root: gql`
|
||||
|
||||
@@ -32,4 +32,18 @@ class ErrIncorrectPassword extends TalkError {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { ErrLocalProfile, ErrNoLocalProfile, ErrIncorrectPassword };
|
||||
class ErrDuplicateLocalProfile extends TalkError {
|
||||
constructor() {
|
||||
super('Duplicate local profile attachment', {
|
||||
translation_key: 'DUPLICATE_LOCAL_PROFILE',
|
||||
status: 400,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
ErrDuplicateLocalProfile,
|
||||
ErrLocalProfile,
|
||||
ErrNoLocalProfile,
|
||||
ErrIncorrectPassword,
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ const {
|
||||
ErrNoLocalProfile,
|
||||
ErrLocalProfile,
|
||||
ErrIncorrectPassword,
|
||||
ErrDuplicateLocalProfile,
|
||||
} = require('./errors');
|
||||
const { get } = require('lodash');
|
||||
|
||||
@@ -115,6 +116,11 @@ async function attachUserLocalAuth(ctx, email, password) {
|
||||
// Validate the password.
|
||||
await Users.isValidPassword(password);
|
||||
|
||||
// See if this email address already has a local profile setup.
|
||||
if (await Users.findLocalUser(email)) {
|
||||
throw new ErrDuplicateLocalProfile();
|
||||
}
|
||||
|
||||
// Hash the new password.
|
||||
const hashedPassword = await Users.hashPassword(password);
|
||||
|
||||
@@ -160,7 +166,7 @@ async function attachUserLocalAuth(ctx, email, password) {
|
||||
await Users.sendEmailConfirmation(updatedUser, email, redirectUri);
|
||||
} catch (err) {
|
||||
if (err.code === 11000) {
|
||||
throw new ErrEmailTaken();
|
||||
throw new ErrDuplicateLocalProfile();
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,6 @@ ar:
|
||||
required_field: "هذه الخانة مطلوبه"
|
||||
done: "تم"
|
||||
content:
|
||||
title: "أضف عنوان بريد إلكتروني"
|
||||
description: "لمزيد من الأمان ، نطلب من المستخدمين إضافة عنوان بريد إلكتروني إلى حساباتهم. سيتم استخدام عنوان بريدك الإلكتروني في:"
|
||||
item_1: "تلقي التحديثات المتعلقة بأي تغييرات في حسابك (عنوان البريد الإلكتروني ، اسم المستخدم ، كلمة المرور ، إلخ.)"
|
||||
item_2: "السماح لك بتنزيل تعليقاتك."
|
||||
@@ -83,6 +82,7 @@ en:
|
||||
NO_LOCAL_PROFILE: No existing email address is associated with this account.
|
||||
LOCAL_PROFILE: An email address is already associated with this account.
|
||||
INCORRECT_PASSWORD: Provided password was incorrect.
|
||||
DUPLICATE_LOCAL_PROFILE: An account already exists with this email address. Please cancel and login with your email address and password.
|
||||
talk-plugin-local-auth:
|
||||
change_password:
|
||||
change_password: "Change Password"
|
||||
@@ -125,7 +125,9 @@ en:
|
||||
cancel: "Cancel"
|
||||
change_email_msg: "Email Address Changed. This email address will now be used for signing in and email notifications."
|
||||
add_email:
|
||||
title: "Create New Account"
|
||||
add_email_address: "Add Email Address"
|
||||
cancel: "Cancel"
|
||||
enter_email_address: "Enter Email Address:"
|
||||
invalid_email_address: "Invalid Email address"
|
||||
confirm_email_address: "Confirm Email Address:"
|
||||
@@ -135,7 +137,6 @@ en:
|
||||
required_field: "This field is required"
|
||||
done: "Done"
|
||||
content:
|
||||
title: "Add an Email Address"
|
||||
description: "For your added security, we require users to add an email address to their accounts. Your email address will be used to:"
|
||||
item_1: "Receive updates regarding any changes to your account (email address, username, password, etc.)"
|
||||
item_2: "Allow you to download your comments."
|
||||
@@ -211,7 +212,6 @@ sr:
|
||||
required_field: "Ovo polje je obavezno"
|
||||
done: "Gotovo"
|
||||
content:
|
||||
title: "Dodaj e-mail adresu"
|
||||
description: "For your added security, we require users to add an email address to their accounts. Your email address will be used to:"
|
||||
item_1: "Receive updates regarding any changes to your account (email address, username, password, etc.)"
|
||||
item_2: "Omogućuje vam da preuzmete (download) svoje komentare."
|
||||
@@ -225,7 +225,7 @@ sr:
|
||||
subtitle: "Želite da promenite e-mail adresu?"
|
||||
description_2: "Možete urediti svoj nalog ovde:"
|
||||
path: "Moj profil > Podešavanja"
|
||||
alert: "E-mail dodat"
|
||||
alert: "E-mail dodat"
|
||||
pt_BR:
|
||||
email:
|
||||
email_change_original:
|
||||
@@ -287,7 +287,6 @@ pt_BR:
|
||||
required_field: "Esse campo é obrigatório"
|
||||
done: "Feito"
|
||||
content:
|
||||
title: "Adicione um endereço de email"
|
||||
description: "Para a sua segurança, exigimos que os usuários adicionem um endereço de email para suas contas. Seu email será usado para:"
|
||||
item_1: "Receba avisos de alterações na sua conta(endereço de email, usuário, senha, etc.)"
|
||||
item_2: "Permitir que você baixe seus comentários."
|
||||
@@ -362,7 +361,6 @@ de:
|
||||
required_field: "Dieses Feld ist erforderlich"
|
||||
done: "Fertig"
|
||||
content:
|
||||
title: "E-Mail-Adresse hinzufügen"
|
||||
description: "Aus Sicherheitsgründen benötigen wir eine E-Mail-Adresse zu jedem Benutzerkonto. Ihre E-Mail-Adresse wird für folgendes verwendet:"
|
||||
item_1: "Benachrichtigungen über Änderungen am Benutzerkonto (Nutzername, E-Mail-Adresse, Passwort)"
|
||||
item_2: "Ermöglicht den Download des eigenen Kommentar-Archivs"
|
||||
@@ -437,7 +435,6 @@ es:
|
||||
required_field: "Este campo es requerido"
|
||||
done: "Hecho"
|
||||
content:
|
||||
title: "Agregar una dirección de correo electrónico"
|
||||
description: "Para su seguridad adicional, solicitamos a los usuarios que agreguen una dirección de correo electrónico a sus cuentas. Su dirección de correo electrónico se usará para:"
|
||||
item_1: "Recibe actualizaciones sobre cualquier cambio en tu cuenta (dirección de correo electrónico, nombre de usuario, contraseña, etc.)"
|
||||
item_2: "Permitir que descargues tus comentarios."
|
||||
@@ -513,7 +510,6 @@ it:
|
||||
required_field: "Questo campo è obbligatorio"
|
||||
done: "Finito"
|
||||
content:
|
||||
title: "Aggiungi indirizzo email"
|
||||
description: "Per questioni di sicurezza, richiediamo agli utenti di aggiungere un indirizzo email associato ai loro account. Il tuo indirizzo email sarà usato per:"
|
||||
item_1: "Ricevere aggiornamenti riguardo modifiche relative al tuo account (indirizzo email, username, password, etc.)"
|
||||
item_2: "Permetterti di scaricare i tuoi commenti."
|
||||
@@ -589,7 +585,6 @@ nl_NL:
|
||||
required_field: "Dit veld is verplicht"
|
||||
done: "Klaar"
|
||||
content:
|
||||
title: "Voeg een e-mailadres toe"
|
||||
description: "Voor je veiligheid vragen we gebruikers om een e-mailadres toe te voegen aan hun account. Je e-mailadres zal worden gebruikt om:"
|
||||
item_1: "Updates te ontvangen omtrent wijzigingen in je account (e-mailadres, gebruikersnaam, wachtwoord, etc.)"
|
||||
item_2: "Je reacties te kunnen downloaden."
|
||||
|
||||
+1
-24
@@ -30,7 +30,7 @@ deploy_tag() {
|
||||
done
|
||||
|
||||
# Push each of the tags to dockerhub, including latest
|
||||
for version in $tag_list latest
|
||||
for version in $tag_list
|
||||
do
|
||||
echo "==> pushing $version"
|
||||
docker push coralproject/talk:$version
|
||||
@@ -38,22 +38,6 @@ deploy_tag() {
|
||||
done
|
||||
}
|
||||
|
||||
deploy_latest() {
|
||||
echo "==> pushing latest"
|
||||
docker push coralproject/talk:latest
|
||||
docker push coralproject/talk:latest-onbuild
|
||||
}
|
||||
|
||||
deploy_branch() {
|
||||
echo "==> tagging branch $CIRCLE_BRANCH"
|
||||
docker tag coralproject/talk:latest coralproject/talk:$CIRCLE_BRANCH
|
||||
docker tag coralproject/talk:latest-onbuild coralproject/talk:$CIRCLE_BRANCH-onbuild
|
||||
|
||||
echo "==> pushing branch $CIRCLE_BRANCH"
|
||||
docker push coralproject/talk:$CIRCLE_BRANCH
|
||||
docker push coralproject/talk:$CIRCLE_BRANCH-onbuild
|
||||
}
|
||||
|
||||
ARGS=""
|
||||
|
||||
if [[ -n "$CIRCLE_SHA1" ]]
|
||||
@@ -79,12 +63,5 @@ then
|
||||
if [ -n "$CIRCLE_TAG" ]
|
||||
then
|
||||
deploy_tag
|
||||
else
|
||||
if [ "$CIRCLE_BRANCH" = "master" ]
|
||||
then
|
||||
deploy_latest
|
||||
else
|
||||
deploy_branch
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const linkify = require('linkify-it')().tlds(require('tlds'));
|
||||
const linkify = require('linkifyjs');
|
||||
|
||||
// This phase checks the comment if it has any links in it if the check is
|
||||
// enabled.
|
||||
@@ -11,7 +11,12 @@ module.exports = (
|
||||
},
|
||||
}
|
||||
) => {
|
||||
if (premodLinksEnable && linkify.test(comment.body.replace(/\xAD/g, ''))) {
|
||||
if (premodLinksEnable) {
|
||||
const links = linkify.find(comment.body.replace(/\xAD/g, ''));
|
||||
if (!links || links.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the flag related to Trust to the comment.
|
||||
return {
|
||||
status: 'SYSTEM_WITHHELD',
|
||||
|
||||
@@ -14,8 +14,6 @@ const {
|
||||
} = require('../errors');
|
||||
const uuid = require('uuid');
|
||||
const debug = require('debug')('talk:services:passport');
|
||||
const bowser = require('bowser');
|
||||
const ms = require('ms');
|
||||
const _ = require('lodash');
|
||||
const { attachStaticLocals } = require('../middleware/staticTemplate');
|
||||
const { encodeJSONForHTML } = require('./response');
|
||||
@@ -57,21 +55,6 @@ const GenerateToken = user => {
|
||||
});
|
||||
};
|
||||
|
||||
// SetTokenForSafari sends the token in a cookie for Safari clients.
|
||||
const SetTokenForSafari = (req, res, token) => {
|
||||
const browser = bowser._detect(req.headers['user-agent']);
|
||||
if (browser.ios || browser.safari) {
|
||||
debug('browser was safari/ios, setting a cookie');
|
||||
res.cookie(JWT_SIGNING_COOKIE_NAME, token, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
expires: new Date(Date.now() + ms(JWT_EXPIRY)),
|
||||
});
|
||||
} else {
|
||||
debug("browser wasn't safari/ios, didn't set a cookie");
|
||||
}
|
||||
};
|
||||
|
||||
// HandleGenerateCredentials validates that an authentication scheme did indeed
|
||||
// return a user, if it did, then sign and return the user and token to be used
|
||||
// by the frontend to display and update the UI.
|
||||
@@ -87,8 +70,6 @@ const HandleGenerateCredentials = (req, res, next) => (err, user) => {
|
||||
// Generate the token to re-issue to the frontend.
|
||||
const token = GenerateToken(user);
|
||||
|
||||
SetTokenForSafari(req, res, token);
|
||||
|
||||
// Set the cache control headers.
|
||||
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
||||
res.header('Expires', '-1');
|
||||
@@ -139,8 +120,6 @@ const HandleAuthPopupCallback = (req, res, next) => (err, user) => {
|
||||
// Generate the token to re-issue to the frontend.
|
||||
const token = GenerateToken(user);
|
||||
|
||||
SetTokenForSafari(req, res, token);
|
||||
|
||||
// We logged in the user! Let's send back the user data.
|
||||
res.render('auth-callback.njk', {
|
||||
auth: { err: null, data: { user, token } },
|
||||
|
||||
@@ -75,6 +75,12 @@ const scraper = {
|
||||
});
|
||||
const html = await res.text();
|
||||
|
||||
if (!res.ok) {
|
||||
let err = new Error(res.statusText);
|
||||
err.response = res;
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Get the metadata from the scraped html.
|
||||
const meta = await metascraper({
|
||||
html,
|
||||
|
||||
Reference in New Issue
Block a user