Skip to content

Commit

Permalink
Merge branch 'main' into crowd-linux
Browse files Browse the repository at this point in the history
  • Loading branch information
garrrikkotua committed Sep 5, 2023
2 parents b43a77a + ecb00e9 commit 09d9918
Show file tree
Hide file tree
Showing 50 changed files with 2,118 additions and 15 deletions.
2 changes: 1 addition & 1 deletion backend/.env.dist.local
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,4 @@ CROWD_WEEKLY_EMAILS_ENABLED="true"
CROWD_ANALYTICS_IS_ENABLED=
CROWD_ANALYTICS_TENANT_ID=
CROWD_ANALYTICS_BASE_URL=
CROWD_ANALYTICS_API_TOKEN=
CROWD_ANALYTICS_API_TOKEN=
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Permissions from '../../../security/permissions'
import IntegrationService from '../../../services/integrationService'
import PermissionChecker from '../../../services/user/permissionChecker'

export default async (req, res) => {
new PermissionChecker(req).validateHas(Permissions.values.tenantEdit)
const payload = await new IntegrationService(req).groupsioConnectOrUpdate(req.body)
await req.responseHandler.success(req, res, payload)
}
9 changes: 9 additions & 0 deletions backend/src/api/integration/helpers/groupsioGetToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Permissions from '../../../security/permissions'
import IntegrationService from '../../../services/integrationService'
import PermissionChecker from '../../../services/user/permissionChecker'

export default async (req, res) => {
new PermissionChecker(req).validateHas(Permissions.values.tenantEdit)
const payload = await new IntegrationService(req).groupsioGetToken(req.body)
await req.responseHandler.success(req, res, payload)
}
9 changes: 9 additions & 0 deletions backend/src/api/integration/helpers/groupsioVerifyGroup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Permissions from '../../../security/permissions'
import IntegrationService from '../../../services/integrationService'
import PermissionChecker from '../../../services/user/permissionChecker'

export default async (req, res) => {
new PermissionChecker(req).validateHas(Permissions.values.tenantEdit)
const payload = await new IntegrationService(req).groupsioVerifyGroup(req.body)
await req.responseHandler.success(req, res, payload)
}
15 changes: 15 additions & 0 deletions backend/src/api/integration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,21 @@ export default (app) => {
safeWrap(require('./helpers/hubspotStopSyncOrganization').default),
)

app.post(
'/tenant/:tenantId/groupsio-connect',
safeWrap(require('./helpers/groupsioConnectOrUpdate').default),
)

app.post(
'/tenant/:tenantId/groupsio-get-token',
safeWrap(require('./helpers/groupsioGetToken').default),
)

app.post(
'/tenant/:tenantId/groupsio-verify-group',
safeWrap(require('./helpers/groupsioVerifyGroup').default),
)

// if (TWITTER_CONFIG.clientId) {
// /**
// * Using the passport.authenticate this endpoint forces a
Expand Down
8 changes: 6 additions & 2 deletions backend/src/database/repositories/segmentRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,12 @@ class SegmentRepository extends RepositoryBase<
}
})

// TODO: Add member count to segments after implementing member relations
return { count, rows, limit: criteria.limit, offset: criteria.offset }
return {
count,
rows: rows.map((sr) => SegmentRepository.populateRelations(sr)),
limit: criteria.limit,
offset: criteria.offset,
}
}

private async queryIntegrationsForSubprojects(subprojects) {
Expand Down
18 changes: 18 additions & 0 deletions backend/src/serverless/integrations/usecases/groupsio/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface GroupsioIntegrationData {
email: string
token: string
groupNames: GroupName[]
}

export interface GroupsioGetToken {
email: string
password: string
twoFactorCode?: string
}

export interface GroupsioVerifyGroup {
groupName: GroupName
cookie: string
}

export type GroupName = string
112 changes: 111 additions & 1 deletion backend/src/services/integrationService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createAppAuth } from '@octokit/auth-app'
import { request } from '@octokit/request'
import moment from 'moment'
import axios from 'axios'
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import { PlatformType } from '@crowd/types'
import {
HubspotFieldMapperFactory,
Expand Down Expand Up @@ -44,6 +44,11 @@ import OrganizationService from './organizationService'
import MemberSyncRemoteRepository from '@/database/repositories/memberSyncRemoteRepository'
import OrganizationSyncRemoteRepository from '@/database/repositories/organizationSyncRemoteRepository'
import MemberRepository from '@/database/repositories/memberRepository'
import {
GroupsioIntegrationData,
GroupsioGetToken,
GroupsioVerifyGroup,
} from '@/serverless/integrations/usecases/groupsio/types'

const discordToken = DISCORD_CONFIG.token || DISCORD_CONFIG.token2

Expand Down Expand Up @@ -1403,4 +1408,109 @@ export default class IntegrationService {

return integration
}

async groupsioConnectOrUpdate(integrationData: GroupsioIntegrationData) {
const transaction = await SequelizeRepository.createTransaction(this.options)
let integration

// integration data should have the following fields
// email, token, array of groups
// we shouldn't store password and 2FA token in the database
// user should update them every time thety change something

try {
this.options.log.info('Creating Groups.io integration!')
integration = await this.createOrUpdate(
{
platform: PlatformType.GROUPSIO,
settings: {
email: integrationData.email,
token: integrationData.token,
groups: integrationData.groupNames,
updateMemberAttributes: true,
},
status: 'in-progress',
},
transaction,
)

await SequelizeRepository.commitTransaction(transaction)
} catch (err) {
await SequelizeRepository.rollbackTransaction(transaction)
throw err
}

this.options.log.info(
{ tenantId: integration.tenantId },
'Sending Groups.io message to int-run-worker!',
)
const emitter = await getIntegrationRunWorkerEmitter()
await emitter.triggerIntegrationRun(
integration.tenantId,
integration.platform,
integration.id,
true,
)

return integration
}

async groupsioGetToken(data: GroupsioGetToken) {
const config: AxiosRequestConfig = {
method: 'post',
url: 'https://groups.io/api/v1/login',
params: {
email: data.email,
password: data.password,
twofactor: data.twoFactorCode,
},
headers: {
'Content-Type': 'application/json',
},
}

let response: AxiosResponse

try {
response = await axios(config)

// we need to get cookie from the response

const cookie = response.headers['set-cookie'][0].split(';')[0]

return {
groupsioCookie: cookie,
}
} catch (err) {
if ('two_factor_required' in response.data) {
throw new Error400(this.options.language, 'errors.groupsio.twoFactorRequired')
}
throw new Error400(this.options.language, 'errors.groupsio.invalidCredentials')
}
}

async groupsioVerifyGroup(data: GroupsioVerifyGroup) {
const groupName = data.groupName

const config: AxiosRequestConfig = {
method: 'post',
url: `https://groups.io/api/v1/gettopics?group_name=${encodeURIComponent(groupName)}`,
headers: {
'Content-Type': 'application/json',
Cookie: data.cookie,
},
}

let response: AxiosResponse

try {
response = await axios(config)

return {
group: response?.data?.data?.group_id,
}
} catch (err) {
throw new Error400(this.options.language, 'errors.groupsio.invalidGroup')
}
}
}
1 change: 1 addition & 0 deletions backend/src/types/webhooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export enum WebhookType {
GITHUB = 'GITHUB',
DISCORD = 'DISCORD',
DISCOURSE = 'DISCOURSE',
GROUPSIO = 'GROUPSIO',
}

export enum DiscordWebsocketEvent {
Expand Down
3 changes: 3 additions & 0 deletions frontend/public/icons/crowd-icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 09d9918

Please sign in to comment.