Merge branch 'new-queue' of github.com:coralproject/talk into new-queue

This commit is contained in:
Belen Curcio
2017-07-28 09:54:55 -03:00
23 changed files with 142 additions and 73 deletions
+7
View File
@@ -15,6 +15,7 @@ const apollo = require('graphql-server-express');
const accepts = require('accepts');
const compression = require('compression');
const cookieParser = require('cookie-parser');
const {ROOT_URL} = require('./config');
const app = express();
@@ -74,6 +75,12 @@ app.use('/public', express.static(path.join(__dirname, 'public')));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// Set the BASE_URL as the ROOT_URL.
app.locals.BASE_URL = ROOT_URL;
if (app.locals.BASE_URL[app.locals.BASE_URL.length - 1] !== '/') {
app.locals.BASE_URL += '/';
}
//==============================================================================
// PASSPORT MIDDLEWARE
//==============================================================================
+4 -1
View File
@@ -1,5 +1,6 @@
import React from 'react';
import {Router, Route, IndexRedirect, browserHistory, Redirect} from 'react-router';
import {useBasename} from 'history';
import Configure from 'routes/Configure';
import Dashboard from 'routes/Dashboard';
@@ -59,6 +60,8 @@ const routes = (
</div>
);
const AppRouter = () => <Router history={browserHistory} routes={routes} />;
const AppRouter = () => <Router history={useBasename(() => browserHistory)({
basename: '/talk/'
})} routes={routes}/>;
export default AppRouter;
@@ -2,6 +2,7 @@ import React, {Component} from 'react';
import t from 'coral-framework/services/i18n';
import styles from './Configure.css';
import {Button, Card} from 'coral-ui';
import {BASE_URL} from 'coral-framework/constants/url';
class EmbedLink extends Component {
@@ -24,21 +25,14 @@ class EmbedLink extends Component {
}
render () {
const location = window.location;
const talkBaseUrl = [
location.protocol,
'//',
location.hostname,
location.port ? (`:${window.location.port}`) : ''
].join('');
const coralJsUrl = [talkBaseUrl, '/embed.js'].join('');
const coralJsUrl = [BASE_URL, '/embed.js'].join('');
const nonce = String(Math.random()).slice(2);
const streamElementId = `coral_talk_${nonce}`;
const embedText = `
<div id="${streamElementId}"></div>
<script src="${coralJsUrl}" async onload="
Coral.Talk.render(document.getElementById('${streamElementId}'), {
talk: '${talkBaseUrl}'
talk: '${BASE_URL}'
});
"></script>
`.trim();
+7
View File
@@ -0,0 +1,7 @@
import url from 'url';
const base = document.querySelector('base');
const baseUrl = base && url.parse(base.href) || {};
export const BASE_URL = base.href;
export const BASE_PATH = baseUrl.pathname;
+2 -1
View File
@@ -2,6 +2,7 @@ import bowser from 'bowser';
import * as Storage from './storage';
import merge from 'lodash/merge';
import {getStore} from 'coral-framework/services/store';
import {BASE_PATH} from 'coral-framework/constants/url';
/**
* getAuthToken returns the active auth token or null
@@ -75,7 +76,7 @@ const handleResp = (res) => {
}
};
export const base = '/api/v1';
export const base = `${BASE_PATH}api/v1`;
export default (url, options) => {
return fetch(`${base}${url}`, buildOptions(options)).then(handleResp);
+2 -1
View File
@@ -4,6 +4,7 @@ import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transpo
import MessageTypes from 'subscriptions-transport-ws/dist/message-types';
import {getAuthToken} from '../helpers/request';
import introspectionQueryResultData from '../graphql/introspection.json';
import {BASE_PATH} from 'coral-framework/constants/url';
let client, wsClient = null, wsClientToken = null;
@@ -33,7 +34,7 @@ export function getClient(options = {}) {
}
const protocol = location.protocol === 'https:' ? 'wss' : 'ws';
wsClient = new SubscriptionClient(`${protocol}://${location.host}/api/v1/live`, {
wsClient = new SubscriptionClient(`${protocol}://${location.host}${BASE_PATH}api/v1/live`, {
reconnect: true,
lazy: true,
connectionParams: {
+2 -1
View File
@@ -1,12 +1,13 @@
import {createNetworkInterface} from 'apollo-client';
import {getAuthToken} from '../helpers/request';
import {BASE_PATH} from 'coral-framework/constants/url';
//==============================================================================
// NETWORK INTERFACE
//==============================================================================
const networkInterface = createNetworkInterface({
uri: '/api/v1/graph/ql',
uri: `${BASE_PATH}api/v1/graph/ql`,
opts: {
credentials: 'same-origin'
}
+11 -2
View File
@@ -72,7 +72,7 @@ const CONFIG = {
PORT: process.env.TALK_PORT || '3000',
// The URL for this Talk Instance as viewable from the outside.
ROOT_URL: process.env.TALK_ROOT_URL,
ROOT_URL: process.env.TALK_ROOT_URL || null,
// The keepalive timeout (in ms) that should be used to send keep alive
// messages through the websocket to keep the socket alive.
@@ -102,13 +102,22 @@ const CONFIG = {
// DISABLE_AUTOFLAG_SUSPECT_WORDS is true when the suspect words that are
// matched should not be flagged.
DISABLE_AUTOFLAG_SUSPECT_WORDS: process.env.TALK_DISABLE_AUTOFLAG_SUSPECT_WORDS === 'TRUE'
DISABLE_AUTOFLAG_SUSPECT_WORDS: process.env.TALK_DISABLE_AUTOFLAG_SUSPECT_WORDS === 'TRUE',
// TRUST_THRESHOLDS defines the thresholds used for automoderation.
TRUST_THRESHOLDS: process.env.TRUST_THRESHOLDS || 'comment:-1,-1;flag:-1,-1'
};
//==============================================================================
// CONFIG VALIDATION
//==============================================================================
if (process.env.NODE_ENV === 'test' && !CONFIG.ROOT_URL) {
CONFIG.ROOT_URL = 'http://localhost:3000';
} else if (!CONFIG.ROOT_URL) {
throw new Error('TALK_ROOT_URL must be provided');
}
//------------------------------------------------------------------------------
// JWT based configuration
//------------------------------------------------------------------------------
+32
View File
@@ -37,6 +37,15 @@ environment variables. Refer to the
[config.js](https://github.com/coralproject/talk/blob/master/config.js) file to
see how the configuration is parsed.
### Webpack
These are only used during the webpack build.
- `TALK_THREADING_LEVEL` (_optional_) - specify the maximum depth of the comment
thread. (Default `3`)
- `TALK_DEFAULT_STREAM_TAB` (_optional_) - specify the default stream tab in the
admin. (Default `all`)
### Database
- `TALK_MONGO_URL` (*required*) - the database connection string for the MongoDB database.
@@ -91,6 +100,29 @@ on the contents of those variables.**
- `TALK_RECAPTCHA_SECRET` (*required for reCAPTCHA support*) - server secret used for enabling reCAPTCHA powered logins. If not provided it will instead default to providing only a time based lockout.
- `TALK_RECAPTCHA_PUBLIC` (*required for reCAPTCHA support*) - client secret used for enabling reCAPTCHA powered logins. If not provided it will instead default to providing only a time based lockout.
### Trust
Trust can automoderate comments based on user history. By specifying this
option, the beheviour can be changed to offer different results.
- `TRUST_THRESHOLDS` (_optional_) - configure the reliability thresholds for
flagging and commenting. (Default `comment:-1,-1;flag:-1,-1`)
The form of the environment variable:
```
<name>:<RELIABLE>,<UNRELIABLE>;<name>:<RELIABLE>,<UNRELIABLE>;...
```
The default could be read as:
- When a commenter has one comment rejected, their next comment must be
premoderated once in order to post freely again. If they instead get rejected
again, then they must have two of their comments approved in order to get
added back to the queue.
- At the moment of writing, beheviour is not attached to the flagging
reliability, but it is recorded.
### Plugins
- `TALK_PLUGINS_JSON` (_optional_) - used to specify the plugin config via the
+4 -4
View File
@@ -5,10 +5,10 @@
.masthead {
position: relative;
border-bottom: 1px solid $border-color;
-webkit-animation: intro 0.3s both;
animation: intro 0.3s both;
-webkit-animation-delay: 0.15s;
animation-delay: 0.15s;
// -webkit-animation: intro 0.3s both;
// animation: intro 0.3s both;
// -webkit-animation-delay: 0.15s;
// animation-delay: 0.15s;
z-index: 20;
&__inner-wrap {
+4 -4
View File
@@ -14,10 +14,10 @@
padding-left: 2em;
padding-right: 2em;
font-family: $sans-serif;
-webkit-animation: intro 0.3s both;
animation: intro 0.3s both;
-webkit-animation-delay: 0.30s;
animation-delay: 0.30s;
// -webkit-animation: intro 0.3s both;
// animation: intro 0.3s both;
// -webkit-animation-delay: 0.30s;
// animation-delay: 0.30s;
@include breakpoint($large) {
padding-left: 1em;
+12 -12
View File
@@ -8,10 +8,10 @@
margin-top: 2em;
padding-left: 1em;
padding-right: 1em;
-webkit-animation: intro 0.3s both;
animation: intro 0.3s both;
-webkit-animation-delay: 0.35s;
animation-delay: 0.35s;
// -webkit-animation: intro 0.3s both;
// animation: intro 0.3s both;
// -webkit-animation-delay: 0.35s;
// animation-delay: 0.35s;
@include breakpoint($x-large) {
max-width: $x-large;
@@ -113,10 +113,10 @@
position: relative;
margin-bottom: 2em;
@include clearfix;
-webkit-animation: intro 0.3s both;
animation: intro 0.3s both;
-webkit-animation-delay: 0.25s;
animation-delay: 0.25s;
// -webkit-animation: intro 0.3s both;
// animation: intro 0.3s both;
// -webkit-animation-delay: 0.25s;
// animation-delay: 0.25s;
&--overlay {
position: relative;
@@ -126,10 +126,10 @@
background-size: cover;
background-repeat: no-repeat;
background-position: center;
-webkit-animation: intro 0.3s both;
animation: intro 0.3s both;
-webkit-animation-delay: 0.25s;
animation-delay: 0.25s;
// -webkit-animation: intro 0.3s both;
// animation: intro 0.3s both;
// -webkit-animation-delay: 0.25s;
// animation-delay: 0.25s;
a {
color: #fff;
+2 -2
View File
@@ -16,8 +16,8 @@
@include breakpoint($large) {
@include span(2 of 12);
opacity: 0.75;
-webkit-transition: opacity 0.2s ease-in-out;
transition: opacity 0.2s ease-in-out;
// -webkit-transition: opacity 0.2s ease-in-out;
// transition: opacity 0.2s ease-in-out;
&:hover {
opacity: 1;
+2 -2
View File
@@ -91,7 +91,7 @@ $xing-color : #006567 !default;
/* links */
$link-color : $info-color !default;
$link-color : #f67150 !default;
$link-color-hover : mix(#000, $link-color, 25%) !default;
$link-color-visited : mix(#fff, $link-color, 25%) !default;
$masthead-link-color : $primary-color !default;
@@ -126,4 +126,4 @@ $border-radius : 4px !default;
$box-shadow : 0 1px 1px rgba(0, 0, 0, 0.125) !default;
$navicon-width : 1.5rem !default;
$navicon-height : 0.25rem !default;
$global-transition : all 0.2s ease-in-out !default;
$global-transition : none !default;
+1
View File
@@ -178,6 +178,7 @@
"graphql-docs": "^0.2.0",
"graphql-tag": "^1.2.3",
"hammerjs": "^2.0.8",
"history": "^3.0.0",
"ignore-styles": "^5.0.1",
"immutable": "^3.8.1",
"imports-loader": "^0.7.1",
@@ -1,13 +1,20 @@
const FacebookStrategy = require('passport-facebook').Strategy;
const UsersService = require('services/users');
const {ValidateUserLogin} = require('services/passport');
let {
ROOT_URL
} = require('config');
if (ROOT_URL[ROOT_URL.length - 1] !== '/') {
ROOT_URL += '/';
}
module.exports = (passport) => {
if (process.env.TALK_FACEBOOK_APP_ID && process.env.TALK_FACEBOOK_APP_SECRET && process.env.TALK_ROOT_URL) {
passport.use(new FacebookStrategy({
clientID: process.env.TALK_FACEBOOK_APP_ID,
clientSecret: process.env.TALK_FACEBOOK_APP_SECRET,
callbackURL: `${process.env.TALK_ROOT_URL}/api/v1/auth/facebook/callback`,
callbackURL: `${ROOT_URL}api/v1/auth/facebook/callback`,
passReqToCallback: true,
profileFields: ['id', 'displayName', 'picture.type(large)']
}, async (req, accessToken, refreshToken, profile, done) => {
+1 -1
View File
@@ -23,7 +23,7 @@ router.get('*', (req, res) => {
TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC
};
res.render('admin', {basePath: '/client/coral-admin', data});
res.render('admin', {data});
});
module.exports = router;
+14 -11
View File
@@ -1,22 +1,25 @@
const debug = require('debug')('talk:services:karma');
const UserModel = require('../models/user');
const {
TRUST_THRESHOLDS
} = require('../config');
/**
* This will create an object with the property name of the action type as the
* key and an object as it's value. This will contain a RELIABLE, and UNRELIABLE
* property with the number of karma points associated with their particular
* state.
*
*
* If only the RELIABLE variable is provided, then it will also be used as the
* UNRELIABLE variable.
*
*
* The form of the environment variable is:
*
*
* <name>:<RELIABLE>,<UNRELIABLE>;<name>:<RELIABLE>,<UNRELIABLE>;...
*
*
* The default used is:
*
* comment:1,1;flag:-1,-1
*
* comment:-1,-1;flag:-1,-1
*/
const parseThresholds = (thresholds) => thresholds
.split(';')
@@ -50,16 +53,16 @@ const parseThresholds = (thresholds) => thresholds
return acc;
}, {
comment: {
RELIABLE: -1,
UNRELIABLE: -1
RELIABLE: 0,
UNRELIABLE: 0
},
flag: {
RELIABLE: -1,
UNRELIABLE: -1
RELIABLE: 0,
UNRELIABLE: 0
}
});
const THRESHOLDS = parseThresholds(process.env.TRUST_THRESHOLDS || '');
const THRESHOLDS = parseThresholds(TRUST_THRESHOLDS);
debug('using thresholds: ', THRESHOLDS);
+15 -14
View File
@@ -4,19 +4,19 @@
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<title>Talk - Coral Admin</title>
<link rel="apple-touch-icon" sizes="57x57" href="/public/img/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/public/img/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/public/img/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/public/img/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/public/img/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/public/img/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/public/img/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/public/img/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/public/img/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="32x32" href="/public/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/public/img/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/public/img/favicon-16x16.png">
<link rel="manifest" href="/public/manifest.json">
<link rel="apple-touch-icon" sizes="57x57" href="public/img/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="public/img/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="public/img/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="public/img/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="public/img/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="public/img/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="public/img/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="public/img/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="public/img/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="32x32" href="public/img/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="public/img/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="public/img/favicon-16x16.png">
<link rel="manifest" href="public/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
@@ -37,10 +37,11 @@
<% if (data != null) { %>
<script id="data" type="application/json"><%- JSON.stringify(data) %></script>
<% } %>
<base href="<%= BASE_URL %>"/>
</head>
<body>
<div id="root"></div>
<script src='https://www.google.com/recaptcha/api.js?render=explicit' async defer></script>
<script src="<%= basePath %>/bundle.js" charset="utf-8"></script>
<script src="client/coral-admin/bundle.js" charset="utf-8"></script>
</body>
</html>
+4 -3
View File
@@ -17,16 +17,17 @@
}
</style>
<title><%= title %></title>
<base href="<%= BASE_URL %>"/>
</head>
<body>
<main>
<h1><%= title %></h1>
<p><%= body %></p>
<p><a href="/admin">Admin</a> - <a href="/assets">All Assets</a></p>
<p><a href="admin">Admin</a> - <a href="assets">All Assets</a></p>
<div id='coralStreamEmbed'></div>
<script src="/embed.js" async onload="
<script src="embed.js" async onload="
Coral.Talk.render(document.getElementById('coralStreamEmbed'), {
talk: '/',
talk: '<%= BASE_URL %>',
asset_url: '<%= asset_url ? asset_url : '' %>',
asset_id: '<%= asset_id ? asset_id : '' %>',
auth_token: '',
+1 -1
View File
@@ -4,7 +4,7 @@
Asset list
</h1>
<% assets.forEach(function (asset) { %>
<a href="/assets/id/<%= asset.id %>"><%= asset.url %></a><br />
<a href="<%= BASE_URL %>assets/id/<%= asset.id %>"><%= asset.url %></a><br />
<% }) %>
<p>
(For dev use only. FYI, you can: ?skip=100&limit=25)
+3 -2
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no">
<link rel="stylesheet" type="text/css" href="/client/embed/stream/default.css">
<link rel="stylesheet" type="text/css" href="<%= BASE_URL %>client/embed/stream/default.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<% if (locals.customCssUrl) { %>
@@ -12,10 +12,11 @@
<% if (data != null) { %>
<script id="data" type="application/json"><%- JSON.stringify(data) %></script>
<% } %>
<base href="<%= BASE_URL %>"/>
</head>
<body>
<div id="talk-embed-stream-container"></div>
<script src="/client/embed/stream/bundle.js"></script>
<script src="<%= BASE_URL %>client/embed/stream/bundle.js"></script>
</body>
</html>
+1 -1
View File
@@ -111,7 +111,7 @@ const config = {
new webpack.EnvironmentPlugin({
'TALK_PLUGINS_JSON': '{}',
'TALK_THREADING_LEVEL': '3',
'TALK_DEFAULT_STREAM_TAB': 'all',
'TALK_DEFAULT_STREAM_TAB': 'all'
})
],
resolveLoader: {