Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ USER node:node
WORKDIR /src
COPY --chown=node:node . .

# Workaround https://github.com/CyCoreSystems/go-meteor/issues/6
RUN meteor npm install --save postcss-easy-import

RUN meteor npm install --production
RUN meteor npm install
RUN meteor build --architecture os.linux.x86_64 --directory /bundle
RUN cd /bundle/bundle/programs/server && npm install

Expand Down
3 changes: 1 addition & 2 deletions imports/api/rest/put-pending-invitations.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { invite } from '../../util/email-invite'
import { Meteor } from 'meteor/meteor'

import { reloadCaseFields } from '../cases'
import UnitRolesData from '../unit-roles-data'
import UnitRolesData, { defaultRoleVisibility } from '../unit-roles-data'
import { logger } from '../../util/logger'
import { defaultRoleVisibility } from '../units'

export default (req, res) => {
if (req.query.accessToken !== process.env.API_ACCESS_TOKEN) {
Expand Down
136 changes: 133 additions & 3 deletions imports/api/unit-roles-data.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ import { check } from 'meteor/check'
import { HTTP } from 'meteor/http'
import { Random } from 'meteor/random'
import randToken from 'rand-token'
import { addUserToRole, defaultRoleVisibility } from './units'
import { findOrCreateUser } from './custom-users'
import UnitMetaData from './unit-meta-data'
import PendingInvitations, { KEEP_DEFAULT, REMOVE_USER, REPLACE_DEFAULT, collectionName as pendingInvitaitonsCollName } from './pending-invitations'
import PendingInvitations, {
KEEP_DEFAULT,
REMOVE_USER,
REPLACE_DEFAULT,
collectionName as pendingInvitationsCollName
} from './pending-invitations'
import unitUserInvitedTemplate from '../email-templates/unit-user-invited'
import { logger } from '../util/logger'
import { getIncrementFor } from './increment-counters'
Expand Down Expand Up @@ -42,6 +46,23 @@ export const possibleRoles = [
}
]

export const defaultRoleVisibility = {
[roleEnum.TENANT]: true,
[roleEnum.OWNER_LANDLORD]: true,
[roleEnum.CONTRACTOR]: true,
[roleEnum.MGT_COMPANY]: true,
[roleEnum.AGENT]: true,
'Occupant': true
}

export const roleSortOrder = [
roleEnum.TENANT,
roleEnum.OWNER_LANDLORD,
roleEnum.AGENT,
roleEnum.MGT_COMPANY,
roleEnum.CONTRACTOR
]

const UnitRolesData = new Mongo.Collection(collectionName)

const roleDocMemberMatcher = memberId => roleDoc => roleDoc.members.find(member => member.id === memberId)
Expand Down Expand Up @@ -77,6 +98,115 @@ export function inviteUserToRole (invitorId, unitMongoId, inviteeUser, roleType,
return { accessToken }
}

export const addUserToRole = (
invitingUser, inviteeUser, unitBzId, role, invType, isOccupant, errorLogParams = {}, doLiveUpdate, isVisible = true,
isDefaultInvited = true, roleVisibility = defaultRoleVisibility
) => {
// Filling up role visibility in case some of it is missing
roleVisibility = Object.assign({}, defaultRoleVisibility, roleVisibility)

// Creating matching invitation records
const invitationObj = {
invitedBy: invitingUser.bugzillaCreds.id,
invitee: inviteeUser.bugzillaCreds.id,
mefeInvitationIdIntValue: getIncrementFor(pendingInvitationsCollName),
type: invType,
unitId: unitBzId,
role,
isOccupant
}

// TODO: Once all dependencies of role resolving are moved from invitations to UnitRolesData, remove this
// Creating the invitation as pending first
const invitationId = PendingInvitations.insert(invitationObj)

// Linking invitation to user
Meteor.users.update(inviteeUser._id, {
$push: {
receivedInvites: {
unitId: invitationObj.unitId,
invitedBy: invitingUser._id,
timestamp: Date.now(),
type: invitationObj.type,
invitationId,
role,
isOccupant
}
}
})

// Adding to the user to a role on BZ using lambda
try {
HTTP.call('POST', process.env.INVITE_LAMBDA_URL, {
data: [Object.assign({ _id: invitationId }, invitationObj)],
headers: {
Authorization: `Bearer ${process.env.API_ACCESS_TOKEN}`
}
})
} catch (e) {
logger.error({
...errorLogParams,
step: 'INVITE lambda request, unit cleanup might be necessary',
error: e
})
throw new Meteor.Error('Invite API Lambda error', e, { lambdaStatusCode: e.response.statusCode })
}

// Marking the pending invitation as "done", now that the API responded with success
PendingInvitations.update({ _id: invitationId }, {
$set: {
done: true
}
})
Meteor.users.update({
_id: inviteeUser._id,
'receivedInvites.invitationId': invitationId
}, {
$set: {
'receivedInvites.$.done': true
}
})

// Updating the roles collection to sync with BZ's state
const unitRoleQuery = {
roleType: role,
unitBzId
}

const unitRoleModifier = {
$push: {
members: {
id: inviteeUser._id,
isVisible,
isDefaultInvited,
isOccupant,
roleVisibility
}
}
}

UnitRolesData.update(unitRoleQuery, unitRoleModifier)

// Matching the role if the defaultAssigneeId is not defined and sets it to the current user. Does nothing otherwise
let doForceAssigneeUpdate
switch (invType) {
case REPLACE_DEFAULT:
doForceAssigneeUpdate = true
break
default:
doForceAssigneeUpdate = false
}
const assigneeUpdateQuery = doForceAssigneeUpdate ? unitRoleQuery : {
defaultAssigneeId: -1,
...unitRoleQuery
}
UnitRolesData.update(assigneeUpdateQuery, {
$set: {
defaultAssigneeId: inviteeUser._id
}
})
}

export function removeRoleMember (requestorId, unitBzId, email, errorLogParams) {
const unitMeta = UnitMetaData.findOne({ bzId: unitBzId })
const unitRoles = UnitRolesData.find({ unitBzId }).fetch()
Expand All @@ -102,7 +232,7 @@ export function removeRoleMember (requestorId, unitBzId, email, errorLogParams)
const invitationObj = {
invitedBy: requestorUser.bugzillaCreds.id,
invitee: userToRemove.bugzillaCreds.id,
mefeInvitationIdIntValue: getIncrementFor(pendingInvitaitonsCollName),
mefeInvitationIdIntValue: getIncrementFor(pendingInvitationsCollName),
type: REMOVE_USER,
unitId: unitBzId,
role: toRemoveRole.roleType,
Expand Down
149 changes: 7 additions & 142 deletions imports/api/units.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ import _ from 'lodash'
import publicationFactory from './base/rest-resource-factory'
import { makeAssociationFactory, withUsers, withDocs } from './base/associations-helper'
import UnitMetaData, { unitTypes, collectionName as unitMetaCollName } from './unit-meta-data'
import UnitRolesData, { possibleRoles, roleEnum, collectionName as unitRolesCollName } from './unit-roles-data'
import PendingInvitations, { REPLACE_DEFAULT, collectionName as pendingInvitationsCollName } from './pending-invitations'
import UnitRolesData, {
possibleRoles,
roleSortOrder,
addUserToRole,
collectionName as unitRolesCollName
} from './unit-roles-data'
import { REPLACE_DEFAULT } from './pending-invitations'
import { callAPI } from '../util/bugzilla-api'
import { logger } from '../util/logger'
import FailedUnitCreations from './failed-unit-creations'
Expand All @@ -25,23 +30,6 @@ export const factoryOptions = {

export let serverHelpers

export const defaultRoleVisibility = {
[roleEnum.TENANT]: true,
[roleEnum.OWNER_LANDLORD]: true,
[roleEnum.CONTRACTOR]: true,
[roleEnum.MGT_COMPANY]: true,
[roleEnum.AGENT]: true,
'Occupant': true
}

const roleSortOrder = [
roleEnum.TENANT,
roleEnum.OWNER_LANDLORD,
roleEnum.AGENT,
roleEnum.MGT_COMPANY,
roleEnum.CONTRACTOR
]

if (Meteor.isServer) {
serverHelpers = {
getAPIUnitByName (unitName, apiKey) {
Expand Down Expand Up @@ -192,129 +180,6 @@ export const getUnitRoles = (unit, userId) => {
)
}

export const addUserToRole = (
invitingUser, inviteeUser, unitBzId, role, invType, isOccupant, errorLogParams = {}, doLiveUpdate, isVisible = true,
isDefaultInvited = true, roleVisibility = defaultRoleVisibility
) => {
// Filling up role visibility in case some of it is missing
roleVisibility = Object.assign({}, defaultRoleVisibility, roleVisibility)

// Creating matching invitation records
const invitationObj = {
invitedBy: invitingUser.bugzillaCreds.id,
invitee: inviteeUser.bugzillaCreds.id,
mefeInvitationIdIntValue: getIncrementFor(pendingInvitationsCollName),
type: invType,
unitId: unitBzId,
role,
isOccupant
}

// TODO: Once all dependencies of role resolving are moved from invitations to UnitRolesData, remove this
// Creating the invitation as pending first
const invitationId = PendingInvitations.insert(invitationObj)

// Linking invitation to user
Meteor.users.update(inviteeUser._id, {
$push: {
receivedInvites: {
unitId: invitationObj.unitId,
invitedBy: invitingUser._id,
timestamp: Date.now(),
type: invitationObj.type,
invitationId,
role,
isOccupant
}
}
})

// Adding to the user to a role on BZ using lambda
try {
HTTP.call('POST', process.env.INVITE_LAMBDA_URL, {
data: [Object.assign({ _id: invitationId }, invitationObj)],
headers: {
Authorization: `Bearer ${process.env.API_ACCESS_TOKEN}`
}
})
} catch (e) {
logger.error({
...errorLogParams,
step: 'INVITE lambda request, unit cleanup might be necessary',
error: e
})
throw new Meteor.Error('Invite API Lambda error', e, { lambdaStatusCode: e.response.statusCode })
}

// Marking the pending invitation as "done", now that the API responded with success
PendingInvitations.update({ _id: invitationId }, {
$set: {
done: true
}
})
Meteor.users.update({
_id: inviteeUser._id,
'receivedInvites.invitationId': invitationId
}, {
$set: {
'receivedInvites.$.done': true
}
})

// Updating the roles collection to sync with BZ's state
const unitRoleQuery = {
roleType: role,
unitBzId
}

const unitRoleModifier = {
$push: {
members: {
id: inviteeUser._id,
isVisible,
isDefaultInvited,
isOccupant,
roleVisibility
}
}
}

UnitRolesData.update(unitRoleQuery, unitRoleModifier)

// Matching the role if the defaultAssigneeId is not defined and sets it to the current user. Does nothing otherwise
let doForceAssigneeUpdate
switch (invType) {
case REPLACE_DEFAULT:
doForceAssigneeUpdate = true
break
default:
doForceAssigneeUpdate = false
}
const assigneeUpdateQuery = doForceAssigneeUpdate ? unitRoleQuery : {
defaultAssigneeId: -1,
...unitRoleQuery
}
UnitRolesData.update(assigneeUpdateQuery, {
$set: {
defaultAssigneeId: inviteeUser._id
}
})

if (doLiveUpdate) {
try {
const response = callAPI('get', `/rest/product?ids=${unitBzId}`, {}, true, true)
const unitItem = factoryOptions.dataResolver(response.data)[0]
pubObj.handleChanged(unitItem, ['components'])
} catch (e) {
logger.error({
...errorLogParams,
step: 'Fetching unit info for live update after invite, proceeding with no error',
error: e
})
}
}
}

const rolesProjByOwnership = (userId, unitItem) => {
return {
unitId: 1,
Expand Down
3 changes: 1 addition & 2 deletions imports/migrations/13_add_role_visibility_to_all_members.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Migrations } from 'meteor/percolate:migrations'
import UnitRolesData from '../api/unit-roles-data'
import { defaultRoleVisibility } from '../api/units'
import UnitRolesData, { defaultRoleVisibility } from '../api/unit-roles-data'

Migrations.add({
version: 13,
Expand Down
Loading