Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed accounts to use discriminators for different types #355

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
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
6 changes: 4 additions & 2 deletions src/api/middleware/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import OfferService from "../../services/offer.js";
import ValidationReasons from "./validators/validationReasons.js";
import { or, storeInLocals } from "./utils.js";
import { verifyAndDecodeToken } from "../../lib/token.js";
import CompanyAccount from "../../models/CompanyAccount.js";
import AdminAccount from "../../models/AdminAccount.js";

// Middleware to require login in an endpoint
export const authRequired = (req, res, next) => {
Expand All @@ -27,12 +29,12 @@ export const isGod = (req, res, next) => {
};

export const isCompany = (req, res, next) => {
if (req?.user?.company) return next();
if (req.user instanceof CompanyAccount) return next();
else return next(new APIError(HTTPStatus.UNAUTHORIZED, ErrorTypes.FORBIDDEN, ValidationReasons.MUST_BE_COMPANY));
};

export const isAdmin = (req, res, next) => {
if (!req.user?.isAdmin) {
if (!(req.user instanceof AdminAccount)) {
return next(new APIError(HTTPStatus.UNAUTHORIZED, ErrorTypes.FORBIDDEN, ValidationReasons.MUST_BE_ADMIN));
}

Expand Down
42 changes: 25 additions & 17 deletions src/api/routes/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { authRequired, isGod, validToken } from "../middleware/auth.js";
import * as validators from "../middleware/validators/auth.js";
import AccountService from "../../services/account.js";
import Company from "../../models/Company.js";
import CompanyAccount from "../../models/CompanyAccount.js";
import AdminAccount from "../../models/AdminAccount.js";

const router = Router();

Expand All @@ -14,24 +16,30 @@ export default (app) => {

// Get logged in user info
router.get("/me", authRequired, async (req, res) => {
const { email, isAdmin, company: companyId } = req.user;

let company = undefined;

try {
if (companyId)
company = await Company.findById(companyId);
} catch (e) {
console.error(`Could not find the respective company of user ${req.user._id}, with id ${companyId}`, e);
const email = req.user.email;

if (req.user instanceof CompanyAccount) {
const companyId = req.user.company;
try {
const company = await Company.findById(companyId);
return res.status(HTTPStatus.OK).json({
data: {
email, isAdmin: false, company
}
});
} catch (e) {
console.error(`Could not find the respective company of user ${req.user._id}, with id ${companyId}`, e);
}
} else if (req.user instanceof AdminAccount) {
return res.status(HTTPStatus.OK).json({
data: {
email, isAdmin: true, company: null
}
});
} else {
console.error(`Unknown user type: ${req.user}`);
}

return res.status(HTTPStatus.OK).json({
data: {
email,
isAdmin,
company
},
});
return res.status(HTTPStatus.INTERNAL_SERVER_ERROR).json({});
});

// Login endpoint
Expand Down
4 changes: 2 additions & 2 deletions src/loaders/mongoose.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import mongoose from "mongoose";
import config from "../config/env.js";
import Account from "../models/Account.js";
import AdminAccount from "../models/AdminAccount.js";
import hash from "../lib/passwordHashing.js";

export default async () => {
Expand Down Expand Up @@ -40,10 +41,9 @@ const createDefaultAdmin = async () => {
return;
}

await Account.create({
await AdminAccount.create({
email: config.admin_email,
password: await hash(config.admin_password),
isAdmin: true,
});

console.info("Created default admin!");
Expand Down
27 changes: 3 additions & 24 deletions src/models/Account.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import mongoose from "mongoose";
import bcrypt from "bcrypt";

const { Schema } = mongoose;

const AccountSchema = new Schema({
Expand All @@ -11,30 +12,8 @@ const AccountSchema = new Schema({
required: true,
},
password: { type: String, required: true },
isAdmin: {
type: Boolean,
default: false,
validate: {
validator: function(isAdmin) {
return isAdmin !== !!this.company;
},
message: "A user cannot be an admin and a company representative",
},
},
company: {
type: Schema.Types.ObjectId,
ref: "Company",
required: function() {
return !this.isAdmin;
},
validate: {
validator: function(company) {
return !!company !== this.isAdmin;
},
message: "A user cannot be a company representative and an admin",

},
},
}, {
discriminatorKey: "accountType",
});

AccountSchema.methods.validatePassword = async function(password) {
Expand Down
12 changes: 12 additions & 0 deletions src/models/AdminAccount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import mongoose from "mongoose";

import Account from "./Account.js";

const { Schema } = mongoose;


const AdminAccountSchema = new Schema({});

const AdminAccount = Account.discriminator("AdminAccount", AdminAccountSchema);

export default AdminAccount;
17 changes: 17 additions & 0 deletions src/models/CompanyAccount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import mongoose from "mongoose";

import Account from "./Account.js";

const { Schema } = mongoose;

const CompanyAccountSchema = new Schema({
company: {
type: Schema.Types.ObjectId,
ref: "Company",
required: true,
},
});

const CompanyAccount = Account.discriminator("CompanyAccount", CompanyAccountSchema);

export default CompanyAccount;
23 changes: 12 additions & 11 deletions src/services/account.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import Account from "../models/Account.js";
import AdminAccount from "../models/AdminAccount.js";
import CompanyAccount from "../models/CompanyAccount.js";
import hash from "../lib/passwordHashing.js";
import Company from "../models/Company.js";
import { RECOVERY_LINK_EXPIRATION } from "../models/constants/Account.js";
Expand All @@ -14,30 +16,28 @@ class AccountService {
}

async registerAdmin(email, password) {
const account = await Account.create({
const adminAccount = await AdminAccount.create({
email,
password: await hash(password),
isAdmin: true,
password: await hash(password)
});

return {
email: account.email,
email: adminAccount.email,
};
}

async registerCompany(email, password, companyName) {

const company = await Company.create({ name: companyName });

const account = await Account.create({
const companyAccount = await CompanyAccount.create({
email,
password,
company,
company
});

return {
email: account.email,
companyName: account.company.name,
email: companyAccount.email,
companyName: companyAccount.company.name,
};
}

Expand Down Expand Up @@ -69,8 +69,9 @@ class AccountService {

async findAndDeleteByCompanyId(company) {
try {
const account = await Account.findOne({ company });
await Account.findByIdAndRemove(account._id);
const account = CompanyAccount.findOne({ company });
await CompanyAccount.findByIdAndRemove(account._id);

return account;
} catch (err) {
console.error(err);
Expand Down
4 changes: 2 additions & 2 deletions src/services/company.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
COMPANY_DELETED_NOTIFICATION,
} from "../email-templates/companyManagement.js";
import EmailService from "../lib/emailService.js";
import Account from "../models/Account.js";
import CompanyAccount from "../models/CompanyAccount.js";
import Company from "../models/Company.js";
class CompanyService {
getOffersInTimePeriod(owner, publishDate, publishEndDate, OfferModel) {
Expand Down Expand Up @@ -120,7 +120,7 @@ class CompanyService {
async _sendCompanyNotification(companyId, notification) {
try {
const company = await Company.findById(companyId);
const companyAccount = await Account.findOne({
const companyAccount = await CompanyAccount.findOne({
company
});
await EmailService.sendMail({
Expand Down
4 changes: 2 additions & 2 deletions src/services/offer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose from "mongoose";
import Company from "../models/Company.js";
import Offer from "../models/Offer.js";
import Account from "../models/Account.js";
import CompanyAccount from "../models/CompanyAccount.js";
import EmailService from "../lib/emailService.js";
import { OFFER_DISABLED_NOTIFICATION } from "../email-templates/companyOfferDisabled.js";
import OfferConstants from "../models/constants/Offer.js";
Expand Down Expand Up @@ -483,7 +483,7 @@ class OfferService {
const offer = await Offer.findById(offerId);
if (!offer) return; // validation of offerId should be done before with an error

const companyAccount = await Account.findOne({
const companyAccount = await CompanyAccount.findOne({
company: await Company.findOne({ _id: offer.owner })
});

Expand Down
Loading