[NEW] Cloud Integration (#13013)
* Cloud package inside of rocket.chat, enforcing a few items now * Implementing more of the requirements to get cloud up * Fix the linter error. Really should have the linter run on commit, not push. * Switch callback to webview and rename some of the variables * fix additional lint * clean up * remove console log * use check for register server on statistics * Implement calling the server-to-cloud and store the tokens * Add the workspace token to various services Rocket.Chat, the company, provides * Clean up the html spacing in the cloud.html * Remove the check on stats for sending the organization email * Cloud workspace and user connected * Update to include refresh token now that cloud does * Add a license api and try/catches * Add support for the token in the url of the admin/cloud page * Change redirectUrl var to redirectUri. dont save scope, and remove workspace scope * fix messy looking if * try increasing wait time on test * add missing import after merge with develop * Check users email * Don't save the org email from the wizard * Fix the review issues, adding i18n * Remove console.log Co-Authored-By: geekgonecrazy <geekgonecrazy@users.noreply.github.com>pull/12951/head
parent
a326aabb28
commit
423c46aa72
@ -0,0 +1,16 @@ |
||||
<template name="cloudCallback"> |
||||
<div class="main-content-flex"> |
||||
<section class="page-container page-home page-static page-settings"> |
||||
{{> header sectionName="Cloud_connect"}} |
||||
<div class="content"> |
||||
{{#requiresPermission 'manage-cloud'}} |
||||
{{#if callbackError.error}} |
||||
<p>{{_ "Cloud_error_in_authenticating"}}</p> |
||||
|
||||
<p>{{_ "Cloud_error_code"}} {{ callbackError.errorCode }}</p> |
||||
{{/if}} |
||||
{{/requiresPermission}} |
||||
</div> |
||||
</section> |
||||
</div> |
||||
</template> |
||||
@ -0,0 +1,37 @@ |
||||
import './callback.html'; |
||||
|
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
|
||||
import queryString from 'query-string'; |
||||
|
||||
Template.cloudCallback.onCreated(function() { |
||||
const instance = this; |
||||
|
||||
instance.loading = new ReactiveVar(true); |
||||
instance.callbackError = new ReactiveVar({ error: false }); |
||||
|
||||
const params = queryString.parse(location.search); |
||||
|
||||
if (params.error_code) { |
||||
instance.callbackError.set({ error: true, errorCode: params.error_code }); |
||||
} else { |
||||
Meteor.call('cloud:finishOAuthAuthorization', params.code, params.state, (error) => { |
||||
if (error) { |
||||
console.warn('cloud:finishOAuthAuthorization', error); |
||||
return; |
||||
} |
||||
|
||||
FlowRouter.go('/admin/cloud'); |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
Template.cloudCallback.helpers({ |
||||
callbackError() { |
||||
return Template.instance().callbackError.get(); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,83 @@ |
||||
<template name="cloud"> |
||||
<div class="main-content-flex"> |
||||
<section class="page-container page-home page-static page-settings"> |
||||
{{> header sectionName="Cloud_connect"}} |
||||
<div class="content"> |
||||
{{#requiresPermission 'manage-cloud'}} |
||||
<div class="section"> |
||||
<div class="section-title"> |
||||
<div class="section-title-text"> |
||||
{{_ "Cloud_what_is_it"}} |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="section-content"> |
||||
<p>{{_ "Cloud_what_is_it_description"}}</p> |
||||
</div> |
||||
</div> |
||||
<div class="section"> |
||||
{{#if info.registeredWithWizard}} |
||||
{{#if info.workspaceConnected}} |
||||
<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> |
||||
<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> |
||||
</div> |
||||
</div> |
||||
{{/if}} |
||||
</div> |
||||
{{else}} |
||||
<div class="section-content border-component-color"> |
||||
<div class="input-line double-col"> |
||||
<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> |
||||
</div> |
||||
</div> |
||||
<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 update-email-btn">{{_ "Cloud_update_email"}}</button> |
||||
</div> |
||||
</div> |
||||
|
||||
<pre>{{ registeredWithWizard }}</pre> |
||||
|
||||
<div class="input-line double-col"> |
||||
<label class="setting-label" title="cloudToken">{{_ "Token"}}</label> |
||||
<div class="setting-field"> |
||||
<input class="input-monitor rc-input__element" type="text" name="cloudToken" value="{{ info.token }}"> |
||||
<div class="settings-description secondary-font-color">{{_ "Cloud_manually_input_token"}}</div> |
||||
</div> |
||||
</div> |
||||
<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 connect-btn">{{_ "Connect"}}</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{{/if}} |
||||
{{else}} |
||||
<div class="section-title"> |
||||
<div class="section-title-text"> |
||||
{{_ "Cloud_registration_required"}} |
||||
</div> |
||||
</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> |
||||
</div> |
||||
{{/if}} |
||||
</div> |
||||
{{/requiresPermission}} |
||||
</div> |
||||
</section> |
||||
</div> |
||||
</template> |
||||
@ -0,0 +1,93 @@ |
||||
import './cloud.html'; |
||||
|
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
import { Template } from 'meteor/templating'; |
||||
import { t } from 'meteor/rocketchat:utils'; |
||||
|
||||
import queryString from 'query-string'; |
||||
import toastr from 'toastr'; |
||||
|
||||
Template.cloud.onCreated(function() { |
||||
const instance = this; |
||||
instance.info = new ReactiveVar(); |
||||
instance.loading = new ReactiveVar(true); |
||||
|
||||
instance.loadRegStatus = function _loadRegStatus() { |
||||
Meteor.call('cloud:checkRegisterStatus', (error, info) => { |
||||
if (error) { |
||||
console.warn('cloud:checkRegisterStatus', error); |
||||
return; |
||||
} |
||||
|
||||
instance.info.set(info); |
||||
instance.loading.set(false); |
||||
}); |
||||
}; |
||||
|
||||
instance.connectWorkspace = function _connectWorkspace(token) { |
||||
Meteor.call('cloud:connectWorkspace', token, (error, success) => { |
||||
if (error) { |
||||
toastr.error(error); |
||||
instance.loadRegStatus(); |
||||
return; |
||||
} |
||||
|
||||
if (!success) { |
||||
toastr.error('Invalid token'); |
||||
instance.loadRegStatus(); |
||||
return; |
||||
} |
||||
|
||||
toastr.success(t('Connected')); |
||||
|
||||
instance.loadRegStatus(); |
||||
}); |
||||
}; |
||||
|
||||
const params = queryString.parse(location.search); |
||||
|
||||
if (params.token) { |
||||
instance.connectWorkspace(); |
||||
} else { |
||||
instance.loadRegStatus(); |
||||
} |
||||
}); |
||||
|
||||
Template.cloud.helpers({ |
||||
info() { |
||||
return Template.instance().info.get(); |
||||
}, |
||||
}); |
||||
|
||||
Template.cloud.events({ |
||||
'click .update-email-btn'() { |
||||
const val = $('input[name=cloudEmail]').val(); |
||||
|
||||
Meteor.call('cloud:updateEmail', val, (error) => { |
||||
if (error) { |
||||
console.warn(error); |
||||
return; |
||||
} |
||||
|
||||
toastr.success(t('Saved')); |
||||
}); |
||||
}, |
||||
|
||||
'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); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,28 @@ |
||||
import './admin/callback'; |
||||
import './admin/cloud'; |
||||
|
||||
import { BlazeLayout } from 'meteor/kadira:blaze-layout'; |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
|
||||
FlowRouter.route('/admin/cloud', { |
||||
name: 'cloud-config', |
||||
action() { |
||||
BlazeLayout.render('main', { center: 'cloud', old: true }); |
||||
}, |
||||
}); |
||||
|
||||
FlowRouter.route('/admin/cloud/oauth-callback', { |
||||
name: 'cloud-oauth-callback', |
||||
action() { |
||||
BlazeLayout.render('main', { center: 'cloudCallback', old: true }); |
||||
}, |
||||
}); |
||||
|
||||
RocketChat.AdminBox.addOption({ |
||||
icon: 'cloud-plus', |
||||
href: 'admin/cloud', |
||||
i18nLabel: 'Cloud', |
||||
permissionGranted() { |
||||
return RocketChat.authz.hasAtLeastOnePermission(['manage-cloud']); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,17 @@ |
||||
Package.describe({ |
||||
name: 'rocketchat:cloud', |
||||
version: '0.0.1', |
||||
summary: 'Package which interacts with the Rocket.Chat Cloud offerings.', |
||||
git: '', |
||||
}); |
||||
|
||||
Package.onUse(function(api) { |
||||
api.use([ |
||||
'ecmascript', |
||||
'rocketchat:lib', |
||||
'templating', |
||||
]); |
||||
|
||||
api.mainModule('client/index.js', 'client'); |
||||
api.mainModule('server/index.js', 'server'); |
||||
}); |
||||
@ -0,0 +1,70 @@ |
||||
import querystring from 'querystring'; |
||||
import { HTTP } from 'meteor/http'; |
||||
|
||||
import { getRedirectUri } from './getRedirectUri'; |
||||
import { retrieveRegistrationStatus } from './retrieveRegistrationStatus'; |
||||
|
||||
export function connectWorkspace(token) { |
||||
const { registeredWithWizard } = retrieveRegistrationStatus(); |
||||
if (!registeredWithWizard) { |
||||
return false; |
||||
} |
||||
|
||||
const redirectUri = getRedirectUri(); |
||||
|
||||
const regInfo = { |
||||
email: RocketChat.settings.get('Organization_Email'), |
||||
client_name: RocketChat.settings.get('Site_Name'), |
||||
redirect_uris: [redirectUri], |
||||
}; |
||||
|
||||
const cloudUrl = RocketChat.settings.get('Cloud_Url'); |
||||
let result; |
||||
try { |
||||
result = HTTP.post(`${ cloudUrl }/api/oauth/clients`, { |
||||
headers: { |
||||
Authorization: `Bearer ${ token }`, |
||||
}, |
||||
data: regInfo, |
||||
}); |
||||
} catch (e) { |
||||
return false; |
||||
} |
||||
|
||||
const { data } = result; |
||||
|
||||
if (!data) { |
||||
return false; |
||||
} |
||||
|
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Id', data.workspaceId); |
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Name', data.client_name); |
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Client_Id', data.client_id); |
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Client_Secret', data.client_secret); |
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Client_Secret_Expires_At', data.client_secret_expires_at); |
||||
RocketChat.models.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) { |
||||
return false; |
||||
} |
||||
|
||||
const expiresAt = new Date(); |
||||
expiresAt.setSeconds(expiresAt.getSeconds() + authTokenResult.data.expires_in); |
||||
|
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Access_Token', authTokenResult.data.access_token); |
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Access_Token_Expires_At', expiresAt); |
||||
|
||||
return true; |
||||
} |
||||
@ -0,0 +1,50 @@ |
||||
import querystring from 'querystring'; |
||||
|
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { HTTP } from 'meteor/http'; |
||||
|
||||
import { getRedirectUri } from './getRedirectUri'; |
||||
|
||||
export function finishOAuthAuthorization(code, state) { |
||||
if (RocketChat.settings.get('Cloud_Workspace_Registration_State') !== state) { |
||||
throw new Meteor.Error('error-invalid-state', 'Invalid state provided', { method: 'cloud:finishOAuthAuthorization' }); |
||||
} |
||||
|
||||
const cloudUrl = RocketChat.settings.get('Cloud_Url'); |
||||
const clientId = RocketChat.settings.get('Cloud_Workspace_Client_Id'); |
||||
const clientSecret = RocketChat.settings.get('Cloud_Workspace_Client_Secret'); |
||||
|
||||
let result; |
||||
try { |
||||
result = HTTP.post(`${ cloudUrl }/api/oauth/token`, { |
||||
data: {}, |
||||
query: querystring.stringify({ |
||||
client_id: clientId, |
||||
client_secret: clientSecret, |
||||
grant_type: 'authorization_code', |
||||
code, |
||||
redirect_uri: getRedirectUri(), |
||||
}), |
||||
}); |
||||
} catch (e) { |
||||
return false; |
||||
} |
||||
|
||||
const expiresAt = new Date(); |
||||
expiresAt.setSeconds(expiresAt.getSeconds() + result.data.expires_in); |
||||
|
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Account_Associated', true); |
||||
RocketChat.models.Users.update({ _id: Meteor.userId() }, { |
||||
$set: { |
||||
'services.cloud': { |
||||
accessToken: result.data.access_token, |
||||
expiresAt, |
||||
scope: result.data.scope, |
||||
tokenType: result.data.token_type, |
||||
refreshToken: result.data.refresh_token, |
||||
}, |
||||
}, |
||||
}); |
||||
|
||||
return true; |
||||
} |
||||
@ -0,0 +1,15 @@ |
||||
import { Random } from 'meteor/random'; |
||||
|
||||
import { getRedirectUri } from './getRedirectUri'; |
||||
|
||||
export function getOAuthAuthorizationUrl() { |
||||
const state = Random.id(); |
||||
|
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Registration_State', state); |
||||
|
||||
const cloudUrl = RocketChat.settings.get('Cloud_Url'); |
||||
const client_id = RocketChat.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 }`; |
||||
} |
||||
@ -0,0 +1,3 @@ |
||||
export function getRedirectUri() { |
||||
return `${ RocketChat.settings.get('Site_Url') }/admin/cloud/oauth-callback`.replace(/\/\/admin+/g, '/admin'); |
||||
} |
||||
@ -0,0 +1,50 @@ |
||||
import querystring from 'querystring'; |
||||
import { HTTP } from 'meteor/http'; |
||||
|
||||
import { getRedirectUri } from './getRedirectUri'; |
||||
|
||||
export function getWorkspaceAccessToken() { |
||||
if (!RocketChat.settings.get('Register_Server')) { |
||||
return ''; |
||||
} |
||||
|
||||
const client_id = RocketChat.settings.get('Cloud_Workspace_Client_Id'); |
||||
if (!client_id) { |
||||
return ''; |
||||
} |
||||
|
||||
const expires = RocketChat.models.Settings.findOneById('Cloud_Workspace_Access_Token_Expires_At'); |
||||
const now = new Date(); |
||||
|
||||
if (now < expires.value) { |
||||
return RocketChat.settings.get('Cloud_Workspace_Access_Token'); |
||||
} |
||||
|
||||
const cloudUrl = RocketChat.settings.get('Cloud_Url'); |
||||
const client_secret = RocketChat.settings.get('Cloud_Workspace_Client_Secret'); |
||||
const redirectUri = getRedirectUri(); |
||||
|
||||
let authTokenResult; |
||||
try { |
||||
authTokenResult = HTTP.post(`${ cloudUrl }/api/oauth/token`, { |
||||
data: {}, |
||||
query: querystring.stringify({ |
||||
client_id, |
||||
client_secret, |
||||
grant_type: 'client_credentials', |
||||
redirect_uri: redirectUri, |
||||
}), |
||||
}); |
||||
} catch (e) { |
||||
return ''; |
||||
} |
||||
|
||||
const expiresAt = new Date(); |
||||
expiresAt.setSeconds(expiresAt.getSeconds() + authTokenResult.data.expires_in); |
||||
|
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Access_Token', authTokenResult.data.access_token); |
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_Access_Token_Expires_At', expiresAt); |
||||
|
||||
|
||||
return authTokenResult.data.access_token; |
||||
} |
||||
@ -0,0 +1,34 @@ |
||||
import { HTTP } from 'meteor/http'; |
||||
|
||||
import { getWorkspaceAccessToken } from './getWorkspaceAccessToken'; |
||||
|
||||
export function getWorkspaceLicense() { |
||||
const token = getWorkspaceAccessToken(); |
||||
|
||||
if (!token) { |
||||
return { updated: false, license: '' }; |
||||
} |
||||
|
||||
|
||||
let licenseResult; |
||||
try { |
||||
licenseResult = HTTP.get(`${ RocketChat.settings.get('Cloud_Workspace_Registration_Client_Uri') }/license`, { |
||||
headers: { |
||||
Authorization: `Bearer ${ token }`, |
||||
}, |
||||
}); |
||||
} catch (e) { |
||||
return { updated: false, license: '' }; |
||||
} |
||||
|
||||
const remoteLicense = licenseResult.data; |
||||
const currentLicense = RocketChat.settings.get('Cloud_Workspace_License'); |
||||
|
||||
if (remoteLicense.updatedAt <= currentLicense._updatedAt) { |
||||
return { updated: false, license: '' }; |
||||
} |
||||
|
||||
RocketChat.models.Settings.updateValueById('Cloud_Workspace_License', remoteLicense.license); |
||||
|
||||
return { updated: true, license: remoteLicense.license }; |
||||
} |
||||
@ -0,0 +1,18 @@ |
||||
export function retrieveRegistrationStatus() { |
||||
const info = { |
||||
registeredWithWizard: RocketChat.settings.get('Register_Server'), |
||||
workspaceConnected: (RocketChat.settings.get('Cloud_Workspace_Client_Id')) ? true : false, |
||||
userAssociated: (RocketChat.settings.get('Cloud_Workspace_Account_Associated')) ? true : false, |
||||
token: '', |
||||
email: '', |
||||
}; |
||||
|
||||
const firstUser = RocketChat.models.Users.getOldest({ emails: 1 }); |
||||
info.email = firstUser && firstUser.emails[0].address; |
||||
|
||||
if (RocketChat.settings.get('Organization_Email')) { |
||||
info.email = RocketChat.settings.get('Organization_Email'); |
||||
} |
||||
|
||||
return info; |
||||
} |
||||
@ -0,0 +1,11 @@ |
||||
import './methods'; |
||||
import { getWorkspaceAccessToken } from './functions/getWorkspaceAccessTokens'; |
||||
|
||||
if (RocketChat.models && RocketChat.models.Permissions) { |
||||
RocketChat.models.Permissions.createOrUpdate('manage-cloud', ['admin']); |
||||
} |
||||
|
||||
// Ensure the client/workspace access token is valid
|
||||
getWorkspaceAccessToken(); |
||||
|
||||
export { getWorkspaceAccessToken }; |
||||
@ -0,0 +1,72 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { check } from 'meteor/check'; |
||||
|
||||
import { retrieveRegistrationStatus } from './functions/retrieveRegistrationStatus'; |
||||
import { connectWorkspace } from './functions/connectWorkspace'; |
||||
import { getOAuthAuthorizationUrl } from './functions/getOAuthAuthorizationUrl'; |
||||
import { finishOAuthAuthorization } from './functions/finishOAuthAuthorization'; |
||||
|
||||
Meteor.methods({ |
||||
'cloud:checkRegisterStatus'() { |
||||
if (!Meteor.userId()) { |
||||
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'cloud:checkRegisterStatus' }); |
||||
} |
||||
|
||||
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'manage-cloud')) { |
||||
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'cloud:checkRegisterStatus' }); |
||||
} |
||||
|
||||
return retrieveRegistrationStatus(); |
||||
}, |
||||
'cloud:updateEmail'(email) { |
||||
check(email, String); |
||||
|
||||
if (!Meteor.userId()) { |
||||
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'cloud:updateEmail' }); |
||||
} |
||||
|
||||
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'manage-cloud')) { |
||||
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'cloud:updateEmail' }); |
||||
} |
||||
|
||||
RocketChat.models.Settings.updateValueById('Organization_Email', email); |
||||
}, |
||||
'cloud:connectWorkspace'(token) { |
||||
check(token, String); |
||||
|
||||
if (!Meteor.userId()) { |
||||
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'cloud:connectServer' }); |
||||
} |
||||
|
||||
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'manage-cloud')) { |
||||
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'cloud:connectServer' }); |
||||
} |
||||
|
||||
return connectWorkspace(token); |
||||
}, |
||||
'cloud:getOAuthAuthorizationUrl'() { |
||||
if (!Meteor.userId()) { |
||||
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'cloud:connectServer' }); |
||||
} |
||||
|
||||
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'manage-cloud')) { |
||||
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'cloud:connectServer' }); |
||||
} |
||||
|
||||
return getOAuthAuthorizationUrl(); |
||||
}, |
||||
'cloud:finishOAuthAuthorization'(code, state) { |
||||
check(code, String); |
||||
check(state, String); |
||||
|
||||
if (!Meteor.userId()) { |
||||
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'cloud:finishOAuthAuthorization' }); |
||||
} |
||||
|
||||
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'manage-cloud')) { |
||||
throw new Meteor.Error('error-not-authorized', 'Not authorized', { method: 'cloud:connectServer' }); |
||||
} |
||||
|
||||
return finishOAuthAuthorization(code, state); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,10 @@ |
||||
RocketChat.Migrations.add({ |
||||
version: 137, |
||||
up() { |
||||
const firstUser = RocketChat.models.Users.getOldest({ emails: 1 }); |
||||
const reportStats = RocketChat.settings.get('Statistics_reporting'); |
||||
|
||||
RocketChat.models.Settings.updateValueById('Organization_Email', firstUser && firstUser.emails && firstUser.emails[0].address); |
||||
RocketChat.models.Settings.updateValueById('Register_Server', reportStats); |
||||
}, |
||||
}); |
||||
Loading…
Reference in new issue