Skip to content

Commit

Permalink
Merge pull request #158 from ThatConference/feat/my-network
Browse files Browse the repository at this point in the history
Feat/my network
  • Loading branch information
brettski authored Nov 29, 2023
2 parents 0d57d2d + 5ba9772 commit 5072c49
Show file tree
Hide file tree
Showing 30 changed files with 2,276 additions and 1,149 deletions.
2,695 changes: 1,563 additions & 1,132 deletions package-lock.json

Large diffs are not rendered by default.

30 changes: 15 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "that-api-members",
"version": "4.2.1",
"version": "4.3.0",
"description": "THATConference.com members service.",
"main": "index.js",
"engines": {
Expand All @@ -21,14 +21,14 @@
},
"dependencies": {
"@adobe/node-fetch-retry": "^2.2.0",
"@apollo/server": "^4.9.4",
"@apollo/subgraph": "^2.5.6",
"@apollo/server": "^4.9.5",
"@apollo/subgraph": "^2.6.1",
"@google-cloud/firestore": "^7.1.0",
"@google-cloud/trace-agent": "^7.1.2",
"@graphql-tools/load-files": "^7.0.0",
"@graphql-tools/merge": "^9.0.0",
"@sentry/node": "^7.74.1",
"@thatconference/api": "^4.3.0",
"@graphql-tools/merge": "^9.0.1",
"@sentry/node": "^7.80.0",
"@thatconference/api": "^4.4.0",
"body-parser": "^1.20.2",
"cors": "^2.8.5",
"dataloader": "^2.2.2",
Expand All @@ -42,30 +42,30 @@
"lodash": "^4.17.21",
"moment": "^2.29.4",
"node-fetch": "~2.6.13",
"postmark": "^3.1.1",
"postmark": "^3.11.0",
"response-time": "^2.3.2",
"uuid": "^9.0.1"
},
"devDependencies": {
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.22.15",
"@babel/cli": "^7.23.4",
"@babel/core": "^7.23.3",
"@babel/eslint-parser": "^7.23.3",
"@babel/node": "^7.22.19",
"@babel/preset-env": "^7.23.2",
"@babel/preset-env": "^7.23.3",
"babel-jest": "^29.7.0",
"concurrently": "^8.2.2",
"cross-env": "^7.0.3",
"eslint": "^8.51.0",
"eslint": "^8.54.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jest": "^27.4.2",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-jest": "^27.6.0",
"eslint-plugin-prettier": "^5.0.1",
"husky": "^8.0.3",
"jest-cli": "^29.7.0",
"nodemon": "^3.0.1",
"prettier-eslint": "^16.1.1",
"prettier-eslint": "^16.1.2",
"prettier-eslint-cli": "^8.0.1"
},
"jest": {
Expand Down
3 changes: 3 additions & 0 deletions src/dataSources/cloudFirestore/member.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ const member = dbInstance => {
return result;
}

const get = memberId => findMe(memberId);

async function findIdFromSlug(slug) {
dlog('findIdFromSlug %s', slug);
const { size, docs } = await membersCol
Expand Down Expand Up @@ -472,6 +474,7 @@ const member = dbInstance => {
findMember,
findPublicById,
findMe,
get,
findIdFromSlug,
getSlug,
batchFindMembers,
Expand Down
24 changes: 23 additions & 1 deletion src/dataSources/cloudFirestore/sharedProfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,28 @@ const sharedProfile = dbInstance => {
});
}

function batchGet(memberIds) {
dlog('batchGet called on %d ids', memberIds?.length);
if (!Array.isArray(memberIds))
throw new Error('sharedProfiles batchGet parameter must be an array');

const docRefs = memberIds.map(id => {
const docpath = `${collectionName}/${id}/${subCollectionName}/${sharedProfileDocName}`;
return dbInstance.doc(docpath);
});
if (docRefs.length < 1) return [];

return dbInstance.getAll(...docRefs).then(docSnaps =>
docSnaps.map(doc => ({
refPath: doc.ref.path,
parsedId: doc.ref.path?.split('/')[1] ?? null,
exists: doc.exists,
id: doc.id,
...doc.data(),
})),
);
}

function create({ memberId, profile }) {
dlog('create shared profile for %s :: %o', memberId, profile);
const docRef = memberCollection
Expand All @@ -55,7 +77,7 @@ const sharedProfile = dbInstance => {
.then(() => memberId);
}

return { get, create, update, remove };
return { get, batchGet, create, update, remove };
};

export default sharedProfile;
146 changes: 146 additions & 0 deletions src/dataSources/cloudFirestore/sharingWith.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import debug from 'debug';
import { utility } from '@thatconference/api';

const dlog = debug('that:api:members:datasources:sharing-with');
const collectionName = 'members';
const subCollectionName = 'sharingWith';
const collectionGroupName = 'sharingWith';
const { entityDateForge } = utility.firestoreDateForge;
const fields = ['createdAt', 'lastUpdatedAt'];
const sharingDataDateForge = entityDateForge({ fields });

const scrubSharingData = (sharingData, isNew = false) => {
dlog('scrubing sharing data');
const scrubbedSharingData = sharingData;
const now = new Date();
if (isNew) {
scrubbedSharingData.createdAt = now;
}
scrubbedSharingData.lastUpdatedAt = now;
return scrubbedSharingData;
};

const sharingWith = dbInstance => {
dlog('sharingWith db instance created');

const memberCollection = dbInstance.collection(collectionName);

function get({ sharedById, sharedWithId }) {
dlog('get sharing record by %s for %s', sharedById, sharedWithId);
return memberCollection
.doc(sharedById)
.collection(subCollectionName)
.doc(sharedWithId)
.get()
.then(docSnap => {
let doc = null;
if (docSnap.exists) {
doc = {
id: docSnap.id,
...docSnap.data(),
};
}
return sharingDataDateForge(doc);
});
}

function findSharedById(memberId) {
dlog('findShaedById for %s', memberId);
return memberCollection
.doc(memberId)
.collection(subCollectionName)
.get()
.then(querySnap =>
querySnap.docs.map(docs => {
const doc = {
id: docs.id,
...docs.data(),
};
return sharingDataDateForge(doc);
}),
);
}

function findSharedWithId(memberId) {
dlog('findsharedwithId for %s', memberId);
return dbInstance
.collectionGroup(collectionGroupName)
.where('sharedWithId', '==', memberId)
.get()
.then(querySnap =>
querySnap.docs.map(docs => {
const doc = {
id: docs.id,
...docs.data(),
};
return sharingDataDateForge(doc);
}),
);
}

function add({ sharedById, sharedWithId, sharingData = {} }) {
dlog('add new member sharing for %s with %s', sharedById, sharedWithId);
if (!sharedById || !sharedWithId)
throw new Error(
'SharedById and SharedWidthId are both required to add a sharing',
);
const newSharingData = {
...sharingData,
sharedById,
sharedWithId,
};
scrubSharingData(newSharingData, true);

return memberCollection
.doc(sharedById)
.collection(subCollectionName)
.doc(sharedWithId)
.create(newSharingData)
.then(() => get({ sharedById, sharedWithId }));
}

function update({ sharedById, sharedWithId, sharingData = {} }) {
dlog(
'update member sharing for %s with %s: %o',
sharedById,
sharedWithId,
sharingData,
);
if (!sharedById || !sharedWithId)
throw new Error(
'SharedById and SharedWidthId are both required to update a sharing',
);
// Ensure share by and shared with don't change, they can't be updated
const updateSharingData = {
...sharingData,
sharedById,
sharedWithId,
};
scrubSharingData(updateSharingData, false);

return memberCollection
.doc(sharedById)
.collection(subCollectionName)
.doc(sharedWithId)
.update(updateSharingData)
.then(() => get({ sharedById, sharedWithId }));
}

function remove({ sharedById, sharedWithId }) {
dlog('remove sharing by %s for %s', sharedById, sharedWithId);
if (!sharedById || !sharedWithId)
throw new Error(
'sharedById and sharedWidthId are both required to remove a sharing',
);
return memberCollection
.doc(sharedById)
.collection(subCollectionName)
.doc(sharedWithId)
.delete()
.then(() => ({ sharedById, sharedWithId }));
}

return { get, findSharedById, findSharedWithId, add, update, remove };
};

export default sharingWith;
31 changes: 31 additions & 0 deletions src/events/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,35 @@ function userEvents(postmark) {
);
}

function sendNewShareEmail({
sharingWith,
sharingSharedProfile,
messageToShareWith = null,
}) {
dlog('sendNewShareEmail');
return postmark
.sendEmailWithTemplate({
TemplateAlias: 'network-new-share-with-you',
From: '[email protected]',
To: sharingWith.email,
Tag: 'network-sharing',
TemplateModel: {
sharingWith: {
firstName: sharingWith.firstName,
lastName: sharingWith.lastName,
email: sharingWith.email,
},
sharingSharedProfile,
messageToShareWith,
},
})
.catch(err =>
process.nextTick(() =>
userEventEmitter.emit('error', { err, user: sharingSharedProfile }),
),
);
}

userEventEmitter.on('error', ({ err, user }) => {
Sentry.setTag('section', 'userEventEmitter');
Sentry.setContext('user object', { user });
Expand All @@ -134,6 +163,8 @@ function userEvents(postmark) {
userEventEmitter.on('accountCreated', sendOrbitLoveActivityOnCreate);
userEventEmitter.on('accountUpdated', sendOrbitLoveActivityOnUpdate);

userEventEmitter.on('addNewSharingWith', sendNewShareEmail);

return userEventEmitter;
}

Expand Down
6 changes: 6 additions & 0 deletions src/graphql/resolvers/mutations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { fieldResolvers as adminMemberFields } from './adminMember';
import { fieldResolvers as adminMembersFields } from './adminMembers';
import { fieldResolvers as sharedProfileFields } from './sharedProfile';
import { fieldResolvers as profilesFields } from './profiles';
import { fieldResolvers as membersNetworkFields } from './membersNetwork';
import { fieldResolvers as networkSharingWithFields } from './networkSharingWith';
import { fieldResolvers as shareWithAddByFieds } from './shareWithAddBy';

export default {
...rootMutations,
Expand All @@ -18,4 +21,7 @@ export const fieldResolvers = {
...adminMembersFields,
...sharedProfileFields,
...profilesFields,
...membersNetworkFields,
...networkSharingWithFields,
...shareWithAddByFieds,
};
2 changes: 2 additions & 0 deletions src/graphql/resolvers/mutations/members.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export const fieldResolvers = {
return { memberId };
},

network: () => ({}),

admin: () => {
dlog('admin called');
return {};
Expand Down
15 changes: 15 additions & 0 deletions src/graphql/resolvers/mutations/membersNetwork.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import debug from 'debug';

const dlog = debug('that:api:members:mutation:members-network');

export const fieldResolvers = {
MembersNetworkMutation: {
add: () => ({}),

sharingWith: (_, { sharedWithId }) => {
dlog('enter sharingWith path for %s', sharedWithId);

return { sharedWithId };
},
},
};
37 changes: 37 additions & 0 deletions src/graphql/resolvers/mutations/networkSharingWith.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import debug from 'debug';
import sharingWithStore from '../../../dataSources/cloudFirestore/sharingWith';

const dlog = debug('that:api:members:network-sharing-with-mutation');

export const fieldResolvers = {
NetworkSharingWithMutation: {
update: (
{ sharedWithId },
{ shareWith },
{ dataSources: { firestore }, user },
) => {
dlog('update shared with %s', sharedWithId);

return sharingWithStore(firestore).update({
sharedById: user.sub,
sharedWithId,
sharingData: {
notes: shareWith?.notes ?? '',
},
});
},
appendNewNote: (_, { text }) => {
dlog('appending text length %d to notes', text?.length);

throw new Error('Not Implemented');
},
remove: ({ sharedWithId }, __, { dataSources: { firestore }, user }) => {
dlog('removing share with %s', sharedWithId);

// return sharedWithId;
return sharingWithStore(firestore)
.remove({ sharedById: user.sub, sharedWithId })
.then(result => result.sharedWithId);
},
},
};
Loading

0 comments on commit 5072c49

Please sign in to comment.