Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] Improve cloud section #13820

Merged
merged 10 commits into from
Apr 2, 2019
40 changes: 28 additions & 12 deletions app/cloud/client/admin/cloud.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,41 @@
</div>
</div>
<div class="section">
{{#if info.registeredWithWizard}}
{{#if info.workspaceConnected}}
{{#if info.connectToCloud}}
{{#if info.workspaceRegistered}}
<div class="section-content border-component-color">
{{#if info.userAssociated}}
<p>{{_ "Cloud_workspace_connected_plus_account"}}</p>
{{else}}
<p>{{_ "Cloud_workspace_connected_without_account"}}</p>
<p>{{_ "Cloud_workspace_connected"}}</p>
<div class="input-line double-col">
<label class="setting-label" title=""></label>
<div class="setting-field">
<a href="https://cloud.rocket.chat" class="rc-button rc-button--primary" target="_blank">{{_ "Cloud_login_to_cloud"}}</a>
</div>
</div>
</div>

<div class="section-content border-component-color">
<p>{{_ "Cloud_workspace_support"}}</p>
<div class="input-line double-col">
<label class="setting-label" title=""></label>
<div class="setting-field">
<button type="button" class="rc-button rc-button--primary action login-btn">{{_ "Cloud_login_to_cloud"}}</button>
<button type="button" class="rc-button rc-button--danger action sync-btn">{{_ "Sync"}}</button>
</div>
</div>
{{/if}}
</div>

<div class="section-content border-component-color">
<p>{{_ "Cloud_workspace_disconnect"}}</p>
<div class="input-line double-col">
<label class="setting-label" title=""></label>
<div class="setting-field">
<button type="button" class="rc-button rc-button--danger action disconnect-btn">{{_ "Disconnect"}}</button>
</div>
</div>
</div>
{{else}}
<div class="section-content border-component-color">
<div class="input-line double-col">
<label class="setting-label" title="cloudEmail">Email</label>
<label class="setting-label" title="cloudEmail">{{_ "Email"}}</label>
<div class="setting-field">
<input class="input-monitor rc-input__element" type="text" name="cloudEmail" value="{{ info.email }}">
<div class="settings-description secondary-font-color">{{_ "Cloud_address_to_send_registration_to"}}</div>
Expand All @@ -47,8 +63,6 @@
</div>
</div>

<pre>{{ registeredWithWizard }}</pre>

<div class="input-line double-col">
<label class="setting-label" title="cloudToken">{{_ "Token"}}</label>
<div class="setting-field">
Expand All @@ -62,6 +76,8 @@
<button type="button" class="rc-button rc-button--primary action connect-btn">{{_ "Connect"}}</button>
</div>
</div>

<p>If you still haven't received a registration email please make sure your email is updated above. If you still have issues you can contact support at: <a href="mailto:support@rocket.chat?subject=[Self Hosted Registration]&body=WorkspaceId: {{ info.workspaceId }}%0D%0ADeployment Id: {{ info.uniqueId }}%0D%0AIssue: <please describe your issue here>">support@rocket.chat</a></p>
</div>
{{/if}}
{{else}}
Expand All @@ -72,7 +88,7 @@
</div>
<div class="section-content border-component-color">
<p>{{_ "Cloud_registration_required_description"}}</p>
<p><a href="./admin/Setup_Wizard">{{_ "Cloud_registration_requried_link_text"}}</a></p>
<button type="button" class="rc-button rc-button--primary action register-btn">{{_ "Cloud_registration_requried_link_text"}}</button>
</div>
{{/if}}
</div>
Expand Down
85 changes: 73 additions & 12 deletions app/cloud/client/admin/cloud.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,67 @@ Template.cloud.onCreated(function() {
}

if (!success) {
toastr.error('Invalid token');
toastr.error('An error occured connecting');
instance.loadRegStatus();
return;
}

toastr.success(t('Connected'));

instance.loadRegStatus();
});
};

instance.disconnectWorkspace = function _disconnectWorkspace() {
Meteor.call('cloud:disconnectWorkspace', (error, success) => {
if (error) {
toastr.error(error);
instance.loadRegStatus();
return;
}

if (!success) {
toastr.error('An error occured disconnecting');
instance.loadRegStatus();
return;
}

toastr.success(t('Disconnected'));

instance.loadRegStatus();
});
};

instance.syncWorkspace = function _syncWorkspace() {
Meteor.call('cloud:syncWorkspace', (error, success) => {
if (error) {
toastr.error(error);
instance.loadRegStatus();
return;
}

if (!success) {
toastr.error('An error occured syncing');
instance.loadRegStatus();
return;
}

toastr.success(t('Sync Complete'));

instance.loadRegStatus();
});
};

instance.registerWorkspace = function _registerWorkspace() {
Meteor.call('cloud:registerWorkspace', (error, success) => {
if (error) {
toastr.error(error);
instance.loadRegStatus();
return;
}

if (!success) {
toastr.error('An error occured');
instance.loadRegStatus();
return;
}
Expand Down Expand Up @@ -74,20 +134,21 @@ Template.cloud.events({
});
},

'click .login-btn'() {
Meteor.call('cloud:getOAuthAuthorizationUrl', (error, url) => {
if (error) {
console.warn(error);
return;
}

window.location.href = url;
});
},

'click .connect-btn'(e, i) {
const token = $('input[name=cloudToken]').val();

i.connectWorkspace(token);
},

'click .register-btn'(e, i) {
i.registerWorkspace();
},

'click .disconnect-btn'(e, i) {
i.disconnectWorkspace();
},

'click .sync-btn'(e, i) {
i.syncWorkspace();
},
});
33 changes: 10 additions & 23 deletions app/cloud/server/functions/connectWorkspace.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import querystring from 'querystring';

import { HTTP } from 'meteor/http';
import { settings } from '../../../settings';
import { Settings } from '../../../models';

import { getRedirectUri } from './getRedirectUri';
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus';
import { getWorkspaceAccessToken } from './getWorkspaceAccessToken';

export function connectWorkspace(token) {
const { registeredWithWizard } = retrieveRegistrationStatus();
if (!registeredWithWizard) {
return false;
const { connectToCloud } = retrieveRegistrationStatus();
if (!connectToCloud) {
Settings.updateValueById('Register_Server', true);
}

const redirectUri = getRedirectUri();
Expand All @@ -31,6 +30,10 @@ export function connectWorkspace(token) {
data: regInfo,
});
} catch (e) {
if (e.response && e.response.data && e.response.data.error) {
console.error(`Failed to register with Rocket.Chat Cloud. Error: ${ e.response.data.error }`);
}

return false;
}

Expand All @@ -48,26 +51,10 @@ export function connectWorkspace(token) {
Settings.updateValueById('Cloud_Workspace_Registration_Client_Uri', data.registration_client_uri);

// Now that we have the client id and secret, let's get the access token
let authTokenResult;
try {
authTokenResult = HTTP.post(`${ cloudUrl }/api/oauth/token`, {
data: {},
query: querystring.stringify({
client_id: data.client_id,
client_secret: data.client_secret,
grant_type: 'client_credentials',
redirect_uri: redirectUri,
}),
});
} catch (e) {
const accessToken = getWorkspaceAccessToken(true);
if (!accessToken) {
return false;
}

const expiresAt = new Date();
expiresAt.setSeconds(expiresAt.getSeconds() + authTokenResult.data.expires_in);

Settings.updateValueById('Cloud_Workspace_Access_Token', authTokenResult.data.access_token);
Settings.updateValueById('Cloud_Workspace_Access_Token_Expires_At', expiresAt);

return true;
}
13 changes: 13 additions & 0 deletions app/cloud/server/functions/disconnectWorkspace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus';
import { Settings } from '../../../models';

export function disconnectWorkspace() {
const { connectToCloud } = retrieveRegistrationStatus();
if (!connectToCloud) {
return true;
}

Settings.updateValueById('Register_Server', false);

return true;
}
16 changes: 11 additions & 5 deletions app/cloud/server/functions/finishOAuthAuthorization.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import querystring from 'querystring';

import { Meteor } from 'meteor/meteor';
import { HTTP } from 'meteor/http';
import { settings } from '../../../settings';
import { Settings, Users } from '../../../models';

import { getRedirectUri } from './getRedirectUri';
import { userScopes } from '../oauthScopes';

export function finishOAuthAuthorization(code, state) {
if (settings.get('Cloud_Workspace_Registration_State') !== state) {
Expand All @@ -16,19 +15,26 @@ export function finishOAuthAuthorization(code, state) {
const clientId = settings.get('Cloud_Workspace_Client_Id');
const clientSecret = settings.get('Cloud_Workspace_Client_Secret');

const scope = userScopes.join(' ');

let result;
try {
result = HTTP.post(`${ cloudUrl }/api/oauth/token`, {
data: {},
query: querystring.stringify({
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
params: {
client_id: clientId,
client_secret: clientSecret,
grant_type: 'authorization_code',
scope,
code,
redirect_uri: getRedirectUri(),
}),
},
});
} catch (e) {
if (e.response && e.response.data && e.response.data.error) {
console.error(`Failed to get AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`);
}

return false;
}

Expand Down
5 changes: 4 additions & 1 deletion app/cloud/server/functions/getOAuthAuthorizationUrl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Settings } from '../../../models';
import { settings } from '../../../settings';

import { getRedirectUri } from './getRedirectUri';
import { userScopes } from '../oauthScopes';

export function getOAuthAuthorizationUrl() {
const state = Random.id();
Expand All @@ -13,5 +14,7 @@ export function getOAuthAuthorizationUrl() {
const client_id = settings.get('Cloud_Workspace_Client_Id');
const redirectUri = getRedirectUri();

return `${ cloudUrl }/authorize?response_type=code&client_id=${ client_id }&redirect_uri=${ redirectUri }&scope=offline_access&state=${ state }`;
const scope = userScopes.join(' ');

return `${ cloudUrl }/authorize?response_type=code&client_id=${ client_id }&redirect_uri=${ redirectUri }&scope=${ scope }&state=${ state }`;
}
28 changes: 22 additions & 6 deletions app/cloud/server/functions/getWorkspaceAccessToken.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import querystring from 'querystring';

import { HTTP } from 'meteor/http';
import { settings } from '../../../settings';
import { Settings } from '../../../models';

import { getRedirectUri } from './getRedirectUri';
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus';
import { unregisterWorkspace } from './unregisterWorkspace';
import { workspaceScopes } from '../oauthScopes';

export function getWorkspaceAccessToken(forceNew = false, scope = '', save = true) {
if (!settings.get('Register_Server')) {
const { connectToCloud, workspaceRegistered } = retrieveRegistrationStatus();

if (!connectToCloud || !workspaceRegistered) {
return '';
}

Expand All @@ -27,19 +30,32 @@ export function getWorkspaceAccessToken(forceNew = false, scope = '', save = tru
const client_secret = settings.get('Cloud_Workspace_Client_Secret');
const redirectUri = getRedirectUri();

if (scope === '') {
scope = workspaceScopes.join(' ');
}

let authTokenResult;
try {
authTokenResult = HTTP.post(`${ cloudUrl }/api/oauth/token`, {
data: {},
query: querystring.stringify({
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
params: {
client_id,
client_secret,
scope,
grant_type: 'client_credentials',
redirect_uri: redirectUri,
}),
},
});
} catch (e) {
if (e.response && e.response.data && e.response.data.error) {
console.error(`Failed to get AccessToken from Rocket.Chat Cloud. Error: ${ e.response.data.error }`);

if (e.response.data.error === 'oauth_invalid_client_credentials') {
console.error('Server has been unregistered from cloud');
unregisterWorkspace();
}
}

return '';
}

Expand Down
6 changes: 4 additions & 2 deletions app/cloud/server/functions/retrieveRegistrationStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { Users } from '../../../models';

export function retrieveRegistrationStatus() {
const info = {
registeredWithWizard: settings.get('Register_Server'),
workspaceConnected: (settings.get('Cloud_Workspace_Client_Id')) ? true : false,
connectToCloud: settings.get('Register_Server'),
workspaceRegistered: (settings.get('Cloud_Workspace_Client_Id')) ? true : false,
userAssociated: (settings.get('Cloud_Workspace_Account_Associated')) ? true : false,
workspaceId: settings.get('Cloud_Workspace_Id'),
uniqueId: settings.get('uniqueID'),
token: '',
email: '',
};
Expand Down
Loading