Skip to content

Commit

Permalink
Articles: fix some bugs (RocketChat#69)
Browse files Browse the repository at this point in the history
* fix some bugs and improve code structure

* fix undefined issue in ghostAPI

* fix importPackage.js
  • Loading branch information
shubhsherl authored and Kailash0311 committed Jul 26, 2019
1 parent 803e79b commit 363428d
Show file tree
Hide file tree
Showing 20 changed files with 239 additions and 261 deletions.
Empty file removed app/articles/client/index.js
Empty file.
Empty file removed app/articles/index.js
Empty file.
7 changes: 3 additions & 4 deletions app/articles/server/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ const Api = new Restivus({
}

this.announceToken = settings.get('Announcement_Token');
const { blogId } = this.request.params;
const token = decodeURIComponent(this.request.params.token);

if (this.announceToken !== `${ blogId }/${ token }`) {
if (this.announceToken !== token) {
return {
error: {
statusCode: 404,
Expand Down Expand Up @@ -90,15 +89,15 @@ function executefetchUserRest() {
}
}

Api.addRoute(':blogId/:token', { authRequired: true }, {
Api.addRoute(':token', { authRequired: true }, {
post: executeAnnouncementRest,
get: executeAnnouncementRest,
});

// If a user is editor/admin in Ghost but is not an admin in RC,
// then the e-mail will not be provided to that user
// This method will allow user to fetch user with email.
Api.addRoute(':blogId/:token/getUser', { authRequired: true }, {
Api.addRoute(':token/getUser', { authRequired: true }, {
post: executefetchUserRest,
get: executefetchUserRest,
});
70 changes: 5 additions & 65 deletions app/articles/server/lib/triggerHandler.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';

import { settings } from '../../../settings';
import { API } from '../utils/url';

const api = new API();
import { ghostAPI } from '../utils/ghostAPI';

export const triggerHandler = new class ArticlesSettingsHandler {
constructor() {
this.trigger = {};
}

eventNameArgumentsToObject(...args) {
const argObject = {
event: args[0],
};
switch (argObject.event) {
case 'userEmail':
case 'userRealname':
case 'userAvatar':
case 'userName':
case 'deleteUser':
if (args.length >= 2) {
argObject.user = args[1];
}
Expand All @@ -45,14 +35,10 @@ export const triggerHandler = new class ArticlesSettingsHandler {
switch (event) {
case 'userEmail':
case 'userRealname':
case 'userAvatar':
case 'userName':
case 'deleteUser':
data.user_id = user._id;

if (user.avatar) {
data.avatar = user.avatar;
}

if (user.name) {
data.name = user.name;
}
Expand Down Expand Up @@ -95,56 +81,10 @@ export const triggerHandler = new class ArticlesSettingsHandler {
return;
}

if (settings.get('Articles_enabled')) {
const token = settings.get('Settings_Token');
this.trigger.api = api.rhooks(token);
this.trigger.retryCount = 5;
}

this.executeTriggerUrl(argObject, 0);
}

executeTriggerUrl({ event, room, user, article }, tries = 0) {
if (!this.trigger.api) {
return;
}
const url = this.trigger.api;

const data = {};

this.mapEventArgsToData(data, { event, room, user, article });

const opts = {
params: {},
method: 'POST',
url,
data,
auth: undefined,
npmRequestOptions: {
rejectUnauthorized: !settings.get('Allow_Invalid_SelfSigned_Certs'),
strictSSL: !settings.get('Allow_Invalid_SelfSigned_Certs'),
},
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36',
},
};

if (!opts.url || !opts.method) {
return;
}
this.mapEventArgsToData(data, argObject);

HTTP.call(opts.method, opts.url, opts, (error, result) => {
// if the result contained nothing or wasn't a successful statusCode
if (!result) {
if (tries < this.trigger.retryCount) {
// 2 seconds, 4 seconds, 8 seconds
const waitTime = Math.pow(2, tries + 1) * 1000;

Meteor.setTimeout(() => {
this.executeTriggerUrl({ event, room, user }, tries + 1);
}, waitTime);
}
}
});
ghostAPI.executeTriggerUrl(data, 0);
}
}();
12 changes: 3 additions & 9 deletions app/articles/server/logoutCleanUp.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';

import { settings } from '../../settings';
import { API } from './utils/url';

const api = new API();
import { ghostAPI } from './utils/ghostAPI';

export function ghostCleanUp(cookie) {
const rcUrl = Meteor.absoluteUrl().replace(/\/$/, '');
try {
if (settings.get('Articles_enabled')) {
HTTP.call('DELETE', api.session(), { headers: { cookie, referer: rcUrl } });
if (settings.get('Articles_Enabled')) {
ghostAPI.deleteSesseion(cookie);
}
} catch (e) {
// Do nothing if failed to logout from Ghost.
Expand Down
65 changes: 24 additions & 41 deletions app/articles/server/methods/admin.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,46 @@
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
import { Random } from 'meteor/random';

import { API } from '../utils/url';
import { hasPermission } from '../../../authorization';
import { ghostAPI } from '../utils/ghostAPI';
import { settings } from '../../../settings';

const api = new API();

function setupGhost(user, token) {
const rcUrl = Meteor.absoluteUrl().replace(/\/$/, '');
const blogTitle = settings.get('Article_Site_title');
const blogToken = Random.id(17);
const announceToken = `${ blogToken }/${ Random.id(24) }`;
const settingsToken = `${ blogToken }/${ Random.id(24) }`;
settings.updateById('Announcement_Token', announceToken);
settings.updateById('Settings_Token', settingsToken);
const data = {
setup: [{
rc_url: rcUrl,
rc_id: user._id,
rc_token: token,
announce_token: announceToken,
settings_token: settingsToken,
blogTitle,
}],
};
return HTTP.call('POST', api.setup(), { data, headers: { 'Content-Type': 'application/json' } });
}

function redirectGhost() {
return {
link: api.siteUrl(),
message: 'Ghost is Set up. Redirecting.',
};
}

Meteor.methods({
Articles_admin_panel(token) {
const enabled = settings.get('Articles_enabled');
articlesAdminPanel(loginToken) {
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'articlesAdminPanel',
});
}

const enabled = settings.get('Articles_Enabled');

if (!enabled) {
throw new Meteor.Error('Articles are disabled');
throw new Meteor.Error('error-articles-disabled', 'Articles are disabled', {
method: 'articlesAdminPanel',
});
}
const user = Meteor.users.findOne(Meteor.userId());
let errMsg = 'Unable to connect to Ghost. Make sure Ghost is running';

try {
let response = HTTP.call('GET', api.setup());
let response = ghostAPI.isSetup();

if (response.data.setup[0].status) { // Ghost site is already setup
return redirectGhost();
return ghostAPI.redirectToGhostLink();
}

if (!hasPermission(Meteor.userId(), 'setup-ghost')) {
throw new Meteor.Error('error-action-not-allowed', 'Setting up Ghost is not allowed', {
method: 'articlesAdminPanel',
});
}

// Setup Ghost Site and set title
response = setupGhost(user, token);
response = ghostAPI.setupGhost(loginToken);

errMsg = 'Unable to setup. Make sure Ghost is running';

if (response.statusCode === 201 && response.content) {
return redirectGhost();
return ghostAPI.redirectToGhostLink();
}

throw new Meteor.Error(errMsg);
Expand Down
96 changes: 29 additions & 67 deletions app/articles/server/methods/user.js
Original file line number Diff line number Diff line change
@@ -1,87 +1,47 @@
import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';

import { API } from '../utils/url';
import { ghostAPI } from '../utils/ghostAPI';
import { settings } from '../../../settings';

const api = new API();

function addUser(user, accessToken) {
const data = {
user: [{
rc_username: user.username,
role: 'Author', // User can add itself only as Author, even if he/she is admin in RC
rc_uid: user._id,
rc_token: accessToken,
}],
};
return HTTP.call('POST', api.createAccount(), { data, headers: { 'Content-Type': 'application/json' } });
}

function userExist(id) {
const data = {
user: [{
rc_uid: id,
}],
};
const response = HTTP.call('GET', api.userExist(), { data, headers: { 'Content-Type': 'application/json' } });
return response.data;
}

function inviteSetting() {
const response = HTTP.call('GET', api.invite());
const { settings } = response.data;

if (settings && settings[0] && settings[0].key === 'invite_only') {
return settings[0].value;
}
// default value in Ghost
return false;
}

function redirectGhost() {
return {
link: api.siteUrl(),
message: 'Ghost is Set up. Redirecting.',
};
}

function redirectUser(slug) {
return {
link: api.authorUrl(slug),
message: 'Redirecting.',
};
}

Meteor.methods({
redirectUserToArticles(accessToken) {
const enabled = settings.get('Articles_enabled');
redirectUserToArticles(loginToken) {
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'redirectUserToArticles',
});
}

const enabled = settings.get('Articles_Enabled');

if (!enabled) {
throw new Meteor.Error('Articles are disabled');
throw new Meteor.Error('error-articles-disabled', 'Articles are disabled', {
method: 'redirectUserToArticles',
});
}
const user = Meteor.users.findOne(Meteor.userId());

let errMsg = 'Ghost is not set up. Setup can be done from Admin Panel';

try {
const response = HTTP.call('GET', api.setup());
const response = ghostAPI.isSetup();

if (response.data.setup[0].status) { // Ghost site is already setup
const u = userExist(user._id).users[0];
const u = ghostAPI.userExistInGhost(Meteor.userId()).users[0];

if (u.exist && u.status === 'active') {
return redirectGhost();
return ghostAPI.redirectToGhostLink();
}

if (u.exist) { // user exist but suspended
throw new Meteor.Error('You are suspended from Ghost');
throw new Meteor.Error('error-articles-user-suspended', 'You are suspended from Ghost', {
method: 'redirectUserToArticles',
});
}

const inviteOnly = inviteSetting();
const inviteOnly = ghostAPI.inviteSettingInGhost();

// create user account in ghost
if (!inviteOnly && addUser(user, accessToken).statusCode === 200) {
return redirectGhost();
if (!inviteOnly && ghostAPI.createUserAccount(loginToken).statusCode === 200) {
return ghostAPI.redirectToGhostLink();
}

errMsg = inviteOnly ? 'You are not a member of Ghost. Ask admin to add' : 'Unable to setup your account';
Expand All @@ -95,18 +55,20 @@ Meteor.methods({
},

redirectToUsersArticles(_id) {
const enabled = settings.get('Articles_enabled');
const enabled = settings.get('Articles_Enabled');

if (!enabled) {
throw new Meteor.Error('Articles are disabled');
throw new Meteor.Error('error-articles-disabled', 'Articles are disabled', {
method: 'redirectToUsersArticles',
});
}
const errMsg = 'User is not a member of Ghost';

try {
const u = userExist(_id).users[0];
const response = ghostAPI.userExistInGhost(_id).users[0];

if (u.exist) {
return redirectUser(u.slug);
if (response.exist) {
return ghostAPI.redirectToPublicLink(response.slug);
}

throw new Meteor.Error(errMsg);
Expand Down
Loading

0 comments on commit 363428d

Please sign in to comment.