Skip to content

Commit

Permalink
types and other for saas/api (#156, progress)
Browse files Browse the repository at this point in the history
  • Loading branch information
tima101 committed May 19, 2021
1 parent b804431 commit 172de89
Show file tree
Hide file tree
Showing 17 changed files with 139 additions and 64 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Open source project is located in the `saas` folder. If you purchased our book,
GOOGLE_CLIENTSECRET=
# Used in api/server/aws-s3.ts and api/server/aws-ses.ts
AWS_REGION=
AWS_ACCESSKEYID=
AWS_SECRETACCESSKEY=
Expand Down Expand Up @@ -397,8 +398,6 @@ All code in this repository is provided under the [MIT License](https://github.c
├── .gitignore
├── LICENSE.md
├── README.md
├── docker-compose.yml
├── mongo-user.sh
├── package.json
├── yarn.lock
```
6 changes: 4 additions & 2 deletions saas/api/server/api/team-leader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,13 @@ router.post('/stripe/fetch-checkout-session', async (req, res, next) => {
try {
const { mode, teamId } = req.body;

const user = await User.findById(req.user.id).select(['stripeCustomer', 'email']).lean();
const user = await User.findById(req.user.id)
.select(['stripeCustomer', 'email'])
.setOptions({ lean: true });

const team = await Team.findById(teamId)
.select(['stripeSubscription', 'slug', 'teamLeaderId'])
.lean();
.setOptions({ lean: true });

if (!user || !team || team.teamLeaderId !== req.user.id) {
throw new Error('Permission denied');
Expand Down
14 changes: 12 additions & 2 deletions saas/api/server/aws-s3.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import * as url from 'url';
import * as aws from 'aws-sdk';

async function signRequestForUpload({ fileName, fileType, prefix, bucket }) {
async function signRequestForUpload({
fileName,
fileType,
prefix,
bucket,
}: {
fileName: string;
fileType: string;
prefix: string;
bucket: string;
}) {
const randomStringForPrefix =
Math.random().toString(36).substring(2, 12) + Math.random().toString(36).substring(2, 12);

Expand All @@ -21,7 +31,7 @@ async function signRequestForUpload({ fileName, fileType, prefix, bucket }) {

const s3 = new aws.S3({
apiVersion: 'latest',
region: 'us-east-1',
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESSKEYID,
secretAccessKey: process.env.AWS_SECRETACCESSKEY,
});
Expand Down
2 changes: 1 addition & 1 deletion saas/api/server/aws-ses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as aws from 'aws-sdk';
export default function sendEmail(options) {
const ses = new aws.SES({
apiVersion: 'latest',
region: 'us-east-1',
region: process.env.AWS_REGION,
accessKeyId: process.env.AWS_ACCESSKEYID,
secretAccessKey: process.env.AWS_SECRETACCESSKEY,
});
Expand Down
16 changes: 13 additions & 3 deletions saas/api/server/mailchimp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,18 @@ const LIST_IDS = {
signups: process.env.MAILCHIMP_SAAS_ALL_LIST_ID,
};

function callAPI({ path, method, data }): Promise<Response> {
function callAPI({
path,
method,
data,
}: {
path: string;
method: string;
data: {
email_address: string;
status: string;
};
}): Promise<Response> {
const ROOT_URI = `https://${process.env.MAILCHIMP_REGION}.api.mailchimp.com/3.0`;

return fetch(`${ROOT_URI}${path}`, {
Expand All @@ -19,9 +30,8 @@ function callAPI({ path, method, data }): Promise<Response> {
});
}

async function addToMailchimp({ email, listName }) {
async function addToMailchimp({ email, listName }: { email: string; listName: string }) {
const data = {
// eslint-disable-next-line
email_address: email,
status: 'subscribed',
};
Expand Down
18 changes: 13 additions & 5 deletions saas/api/server/models/Discussion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ const mongoSchema = new mongoose.Schema({
type: String,
required: true,
},
memberIds: [String],
memberIds: [
{
type: String,
},
],
createdAt: {
type: Date,
required: true,
Expand Down Expand Up @@ -104,7 +108,7 @@ class DiscussionClass extends mongoose.Model {

const filter: any = { teamId, memberIds: userId };

const discussions: any[] = await this.find(filter).lean();
const discussions: any[] = await this.find(filter).setOptions({ lean: true });

return { discussions };
}
Expand Down Expand Up @@ -134,7 +138,9 @@ class DiscussionClass extends mongoose.Model {
throw new Error('Bad data');
}

const discussion = await this.findById(id).select('teamId createdUserId').lean();
const discussion = await this.findById(id)
.select('teamId createdUserId')
.setOptions({ lean: true });

const team = await this.checkPermissionAndGetTeam({
userId,
Expand Down Expand Up @@ -164,7 +170,7 @@ class DiscussionClass extends mongoose.Model {
throw new Error('Bad data');
}

const discussion = await this.findById(id).select('teamId').lean();
const discussion = await this.findById(id).select('teamId').setOptions({ lean: true });

await this.checkPermissionAndGetTeam({ userId, teamId: discussion.teamId });

Expand All @@ -180,7 +186,9 @@ class DiscussionClass extends mongoose.Model {
throw new Error('Bad data');
}

const team = await Team.findById(teamId).select('memberIds teamLeaderId').lean();
const team = await Team.findById(teamId)
.select('memberIds teamLeaderId')
.setOptions({ lean: true });

if (!team || team.memberIds.indexOf(userId) === -1) {
throw new Error('Team not found');
Expand Down
4 changes: 2 additions & 2 deletions saas/api/server/models/EmailTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export async function insertTemplates() {
];

for (const t of templates) {
const et = await EmailTemplate.findOne({ name: t.name }).lean();
const et = await EmailTemplate.findOne({ name: t.name }).setOptions({ lean: true });
const message = t.message.replace(/\n/g, '').replace(/[ ]+/g, ' ').trim();

if (!et) {
Expand All @@ -88,7 +88,7 @@ export async function insertTemplates() {
export default async function getEmailTemplate(name: string, params: any) {
await insertTemplates();

const et = await EmailTemplate.findOne({ name }).lean();
const et = await EmailTemplate.findOne({ name }).setOptions({ lean: true });

if (!et) {
throw new Error('Email Template is not found in database.');
Expand Down
30 changes: 18 additions & 12 deletions saas/api/server/models/Invitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,14 @@ class InvitationClass extends mongoose.Model {
throw new Error('Bad data');
}

const team = await Team.findById(teamId).lean();
const team = await Team.findById(teamId).setOptions({ lean: true });
if (!team || team.teamLeaderId !== userId) {
throw new Error('Team does not exist or you have no permission');
}

const registeredUser = await User.findOne({ email }).select('defaultTeamSlug').lean();
const registeredUser = await User.findOne({ email })
.select('defaultTeamSlug')
.setOptions({ lean: true });

if (registeredUser) {
if (team.memberIds.includes(registeredUser._id.toString())) {
Expand All @@ -90,7 +92,9 @@ class InvitationClass extends mongoose.Model {
}

let token;
const invitation = await this.findOne({ teamId, email }).select('token').lean();
const invitation = await this.findOne({ teamId, email })
.select('token')
.setOptions({ lean: true });

if (invitation) {
token = invitation.token;
Expand Down Expand Up @@ -129,33 +133,35 @@ class InvitationClass extends mongoose.Model {
console.log('Email sending error:', err);
});

return await this.findOne({ teamId, email }).lean();
return await this.findOne({ teamId, email }).setOptions({ lean: true });
}

public static async getTeamInvitations({ userId, teamId }) {
const team = await Team.findOne({ _id: teamId }).select('teamLeaderId').lean();
const team = await Team.findOne({ _id: teamId })
.select('teamLeaderId')
.setOptions({ lean: true });

if (userId !== team.teamLeaderId) {
throw new Error('You have no permission.');
}

return this.find({ teamId }).select('email').lean();
return this.find({ teamId }).select('email').setOptions({ lean: true });
}

public static async getTeamByToken({ token }) {
if (!token) {
throw new Error('Bad data');
}

const invitation = await this.findOne({ token }).lean();
const invitation = await this.findOne({ token }).setOptions({ lean: true });

if (!invitation) {
throw new Error('Invitation not found');
}

const team = await Team.findById(invitation.teamId)
.select('name slug avatarUrl memberIds')
.lean();
.setOptions({ lean: true });

if (!team) {
throw new Error('Team does not exist');
Expand All @@ -169,15 +175,15 @@ class InvitationClass extends mongoose.Model {
throw new Error('Bad data');
}

const invitation = await this.findOne({ token }).lean();
const invitation = await this.findOne({ token }).setOptions({ lean: true });

if (!invitation) {
throw new Error('Invitation not found');
}

const team = await Team.findById(invitation.teamId)
.select('name slug avatarUrl memberIds')
.lean();
.setOptions({ lean: true });

if (!team) {
throw new Error('Team does not exist');
Expand All @@ -193,7 +199,7 @@ class InvitationClass extends mongoose.Model {
throw new Error('Bad data');
}

const invitation = await this.findOne({ token }).lean();
const invitation = await this.findOne({ token }).setOptions({ lean: true });

if (!invitation || invitation.email !== user.email) {
throw new Error('Invitation not found');
Expand All @@ -203,7 +209,7 @@ class InvitationClass extends mongoose.Model {

const team = await Team.findById(invitation.teamId)
.select('memberIds slug teamLeaderId')
.lean();
.setOptions({ lean: true });

if (!team) {
throw new Error('Team does not exist');
Expand Down
16 changes: 11 additions & 5 deletions saas/api/server/models/Post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class PostClass extends mongoose.Model {

const filter: any = { discussionId };

const posts: any[] = await this.find(filter).sort({ createdAt: 1 }).lean();
const posts: any[] = await this.find(filter).sort({ createdAt: 1 }).setOptions({ lean: true });

return posts;
}
Expand Down Expand Up @@ -156,7 +156,9 @@ class PostClass extends mongoose.Model {
throw new Error('Bad data');
}

const post = await this.findById(id).select('createdUserId discussionId').lean();
const post = await this.findById(id)
.select('createdUserId discussionId')
.setOptions({ lean: true });

await this.checkPermissionAndGetTeamAndDiscussion({
userId,
Expand All @@ -180,7 +182,9 @@ class PostClass extends mongoose.Model {
throw new Error('Bad data');
}

const post = await this.findById(id).select('createdUserId discussionId content').lean();
const post = await this.findById(id)
.select('createdUserId discussionId content')
.setOptions({ lean: true });

await this.checkPermissionAndGetTeamAndDiscussion({
userId,
Expand All @@ -206,7 +210,7 @@ class PostClass extends mongoose.Model {

const discussion = await Discussion.findById(discussionId)
.select('teamId memberIds slug')
.lean();
.setOptions({ lean: true });

if (!discussion) {
throw new Error('Discussion not found');
Expand All @@ -216,7 +220,9 @@ class PostClass extends mongoose.Model {
throw new Error('Permission denied');
}

const team = await Team.findById(discussion.teamId).select('memberIds slug').lean();
const team = await Team.findById(discussion.teamId)
.select('memberIds slug')
.setOptions({ lean: true });

if (!team || team.memberIds.indexOf(userId) === -1) {
throw new Error('Team not found');
Expand Down
20 changes: 11 additions & 9 deletions saas/api/server/models/Team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ const mongoSchema = new mongoose.Schema({
type: String,
required: true,
},
memberIds: {
type: [String],
required: true,
},
memberIds: [
{
type: String,
required: true,
},
],
defaultTeam: {
type: Boolean,
default: false,
Expand Down Expand Up @@ -183,12 +185,12 @@ class TeamClass extends mongoose.Model {

await this.updateOne({ _id: teamId }, { $set: modifier }, { runValidators: true });

return this.findById(teamId, 'name avatarUrl slug defaultTeam').lean();
return this.findById(teamId, 'name avatarUrl slug defaultTeam').setOptions({ lean: true });
}

public static getAllTeamsForUser(userId: string) {
console.log(`userId:${userId}`);
return this.find({ memberIds: userId }).lean();
return this.find({ memberIds: userId }).setOptions({ lean: true });
}

public static async removeMember({ teamId, teamLeaderId, userId }) {
Expand Down Expand Up @@ -259,13 +261,13 @@ class TeamClass extends mongoose.Model {
{ new: true, runValidators: true },
)
.select('isSubscriptionActive stripeSubscription')
.lean();
.setOptions({ lean: true });
}

public static async cancelSubscriptionAfterFailedPayment({ subscriptionId }) {
const team: any = await this.find({ 'stripeSubscription.id': subscriptionId })
.select('teamLeaderId isSubscriptionActive stripeSubscription isPaymentFailed')
.lean();
.setOptions({ lean: true });
if (!team.isSubscriptionActive) {
throw new Error('Team is already unsubscribed.');
}
Expand All @@ -285,7 +287,7 @@ class TeamClass extends mongoose.Model {
{ new: true, runValidators: true },
)
.select('isSubscriptionActive stripeSubscription isPaymentFailed')
.lean();
.setOptions({ lean: true });
}
}

Expand Down
Loading

0 comments on commit 172de89

Please sign in to comment.