Skip to content

Commit

Permalink
feat(user): tenant owner can sign in to its tenant app
Browse files Browse the repository at this point in the history
  • Loading branch information
dipendraupreti committed Feb 9, 2024
1 parent 431e4c5 commit 14158d1
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { formatDate } from "@dzangolab/fastify-slonik";
import { UserService } from "@dzangolab/fastify-user";
import { ROLE_USER, UserService } from "@dzangolab/fastify-user";
import UserRoles from "supertokens-node/recipe/userroles";

import { ROLE_TENANT_OWNER } from "../../../constants";
import Email from "../../utils/email";
import isTenantOwnerEmail from "../../utils/isTenantOwnerEmail";

import type {
AuthUser,
Expand All @@ -20,11 +23,21 @@ const emailPasswordSignIn = (
const { config, log, slonik } = fastify;

return async (input) => {
input.email = Email.addTenantPrefix(
config,
input.email,
input.userContext.tenant
);
if (
input.userContext.tenant &&
!(await isTenantOwnerEmail(
config,
slonik,
input.email,
input.userContext.tenant
))
) {
input.email = Email.addTenantPrefix(
config,
input.email,
input.userContext.tenant
);
}

const originalResponse = await originalImplementation.emailPasswordSignIn(
input
Expand All @@ -40,12 +53,29 @@ const emailPasswordSignIn = (
UserUpdateInput
>(config, slonik, input.userContext.dbSchema);

const user = await userService.findById(originalResponse.user.id);
let user = await userService.findById(originalResponse.user.id);

if (!user) {
log.error(`User record not found for userId ${originalResponse.user.id}`);
const { roles } = await UserRoles.getRolesForUser(
originalResponse.user.id
);

if (input.userContext.tenant && roles.includes(ROLE_TENANT_OWNER)) {
if (input.userContext.tenant) {
await UserRoles.addRoleToUser(originalResponse.user.id, ROLE_USER);
}

user = (await userService.create({
id: originalResponse.user.id,
email: originalResponse.user.email,
})) as User & QueryResultRow;
} else {
log.error(
`User record not found for userId ${originalResponse.user.id}`
);

return { status: "WRONG_CREDENTIALS_ERROR" };
return { status: "WRONG_CREDENTIALS_ERROR" };
}
}

user.lastLoginAt = Date.now();
Expand Down
41 changes: 41 additions & 0 deletions packages/multi-tenant/src/supertokens/utils/isTenantOwnerEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { UserService } from "@dzangolab/fastify-user";
import humps from "humps";

import getMultiTenantConfig from "../../lib/getMultiTenantConfig";

import type { Tenant } from "../../types/tenant";
import type { ApiConfig } from "@dzangolab/fastify-config";
import type { Database } from "@dzangolab/fastify-slonik";
import type {
User,
UserCreateInput,
UserUpdateInput,
} from "@dzangolab/fastify-user";
import type { QueryResultRow } from "slonik";

const isTenantOwnerEmail = async (
config: ApiConfig,
database: Database,
email: string,
tenant: Tenant
) => {
const userService = new UserService<
User & QueryResultRow,
UserCreateInput,
UserUpdateInput
>(config, database);

const multiTenantConfig = getMultiTenantConfig(config);

const owner = await userService.findById(
tenant[humps.camelize(multiTenantConfig.table.columns.ownerId)]
);

if (owner) {
return email === owner.email;
}

return false;
};

export default isTenantOwnerEmail;

0 comments on commit 14158d1

Please sign in to comment.