Skip to content

Commit

Permalink
Add multi-org selector (#2568)
Browse files Browse the repository at this point in the history
* Fix: Remove brief error message, new sso users see on initial signing in

* Add multi-org selector

* Change default to true. remove unnecessary try/catch
  • Loading branch information
tzjames committed Jun 6, 2024
1 parent 162e278 commit 3807a8c
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
addMemberToOrg,
addPendingMemberToOrg,
expandOrgMembers,
findVerifiedOrgForNewUser,
findVerifiedOrgsForNewUser,
getContextFromReq,
getInviteUrl,
getNumberOfUniqueMembersAndInvites,
Expand Down Expand Up @@ -390,9 +390,14 @@ export async function putMember(
throw new Error("User is not verified");
}

// ensure org matches calculated verified org
const organization = await findVerifiedOrgForNewUser(req.email);
if (!organization || organization.id !== orgId) {
// ensure org matches one of the calculated verified org
const organizations = await findVerifiedOrgsForNewUser(req.email);
if (!organizations) {
throw new Error("Invalid orgId");
}

const organization = organizations.find((o) => o.id === orgId);
if (!organization) {
throw new Error("Invalid orgId");
}

Expand Down
29 changes: 16 additions & 13 deletions packages/back-end/src/routers/users/users.controller.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Response } from "express";
import { OrganizationInterface } from "@back-end/types/organization";
import { AuthRequest } from "../../types/AuthRequest";
import { usingOpenId } from "../../services/auth";
import { createUser, getUserByEmail } from "../../services/users";
import { findOrganizationsByMemberId } from "../../models/OrganizationModel";
import {
addMemberFromSSOConnection,
findVerifiedOrgForNewUser,
findVerifiedOrgsForNewUser,
getContextFromReq,
validateLoginMethod,
} from "../../services/organizations";
Expand Down Expand Up @@ -213,26 +214,28 @@ export async function postUnwatchItem(
}
}

export async function getRecommendedOrg(req: AuthRequest, res: Response) {
export async function getRecommendedOrgs(req: AuthRequest, res: Response) {
const { email } = req;
const user = await getUserByEmail(email);
if (!user?.verified) {
return res.status(200).json({
message: "no verified user found",
});
}
const org = await findVerifiedOrgForNewUser(email);
if (org) {
const currentUserIsPending = !!org?.pendingMembers?.find(
(m) => m.id === user.id
);
const orgs = await findVerifiedOrgsForNewUser(email);
if (orgs) {
return res.status(200).json({
organization: {
id: org.id,
name: org.name,
members: org?.members?.length || 0,
currentUserIsPending,
},
organizations: orgs.map((org: OrganizationInterface) => {
const currentUserIsPending = !!org?.pendingMembers?.find(
(m) => m.id === user.id
);
return {
id: org.id,
name: org.name,
members: org?.members?.length || 0,
currentUserIsPending,
};
}),
});
}
res.status(200).json({
Expand Down
2 changes: 1 addition & 1 deletion packages/back-end/src/routers/users/users.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ router.put("/name", usersController.putUserName);
router.get("/watching", usersController.getWatchedItems);
router.post("/watch/:type/:id", usersController.postWatchItem);
router.post("/unwatch/:type/:id", usersController.postUnwatchItem);
router.get("/getRecommendedOrg", usersController.getRecommendedOrg);
router.get("/getRecommendedOrgs", usersController.getRecommendedOrgs);

export { router as usersRouter };
17 changes: 12 additions & 5 deletions packages/back-end/src/services/organizations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ export async function addMemberFromSSOConnection(
return organization;
}

export async function findVerifiedOrgForNewUser(email: string) {
export async function findVerifiedOrgsForNewUser(email: string) {
const domain = email.toLowerCase().split("@")[1];
const isFreeDomain = freeEmailDomains.includes(domain);
if (isFreeDomain) {
Expand All @@ -1005,10 +1005,17 @@ export async function findVerifiedOrgForNewUser(email: string) {
return null;
}

// get the org with the most members
return organizations.reduce((prev, current) => {
return prev.members.length > current.members.length ? prev : current;
});
if (IS_CLOUD) {
// On cloud, return an array with only the single org with the most members, as the others are probably just "test" accounts.
return [
organizations.reduce((prev, current) => {
return prev.members.length > current.members.length ? prev : current;
}),
];
} else {
// On multi-org self hosted sites, all orgs with the domain should be available to users to join not just the one with the most members
return organizations;
}
}

export async function expandOrgMembers(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
.recommendedOrgBox {
display: flex;
align-items: center;
justify-content: center;
padding: 1.2rem;
border: 1px solid #e0e0e0;
border-radius: 4px;
margin-bottom: 1rem;

.recommendedOrgRow {
display: flex;
align-items: center;
justify-content: center;
}

.recommendedOrgLogo {
margin-right: 10px;
position: relative;
Expand Down
Loading

0 comments on commit 3807a8c

Please sign in to comment.