Guidance on implementing tenant field from multi-tenant example #3112
Replies: 3 comments 3 replies
-
@IAmNatch You could import the relationship from As for the useAuth hook, I believe the roles field on the user collection needs Want to give that a shot and let us know how it goes? |
Beta Was this translation helpful? Give feedback.
-
My tenant field is named 'client,' but otherwise this code is working for me: import type { Field, Condition } from "payload/types";
import { superAdminFieldAccess } from "../../access/superAdmins";
import { isSuperAdmin } from "../../utilities/isSuperAdmin";
import { clientAdminFieldAccess } from "./access/clientAdmins";
import type { User } from "payload/generated-types";
export const client: Field = {
name: "client",
type: "relationship",
relationTo: "clients",
index: true,
admin: {
position: "sidebar",
// @ts-ignore - TS can't match the user types :(
condition: (data, siblingData, { user }) => isSuperAdmin(user),
},
access: {
create: superAdminFieldAccess,
read: clientAdminFieldAccess,
update: superAdminFieldAccess,
},
hooks: {
beforeChange: [
async ({ req, req: { user }, data }) => {
if ((await isSuperAdmin(user)) && data?.client) {
return data.client;
}
return user?.lastLoggedInClient?.id;
},
],
},
}; |
Beta Was this translation helpful? Give feedback.
-
One more suggestion, if you are doing multi-tenancy and you run across this discussion, you can use the Bonjour package to broadcast mdns, and you don't need to mess with your hosts file. I have a Clients collection instead of Tenants, and instead of an array of domains, I have a single "subdomain" field. I loop through those and broadcast each using Bonjour. This results in being able to access each in your browser at http://clientsubdomain.local:3000. If you add a new subdomain, you'll need to restart your server so that it picks up the change. import express from "express";
import payload from "payload";
import Bonjour from "bonjour-service";
import dotenv from "dotenv";
dotenv.config();
const app = express();
const port = 3000;
// Create a new instance of Bonjour
const bonjour = new Bonjour();
// Redirect to Admin panel
app.get("/", (_, res) => {
res.redirect("/admin");
});
const start = async () => {
// Initialize Payload
await payload.init({
secret: process.env.PAYLOAD_SECRET,
express: app,
onInit: async () => {
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`);
// Fetch unique subdomains from the Clients collection
const clients = await payload.find({
collection: "clients",
});
const subdomains = [];
clients.docs.forEach((client) => {
if (client.subdomain) {
subdomains.push(client.subdomain);
}
});
// Broadcast each unique subdomain using Bonjour
subdomains.forEach((subdomain) => {
bonjour.publish({
name: subdomain, // Use the subdomain as the name
type: "http",
port: port,
host: `${subdomain}.local`, // Append .local to the subdomain
});
console.log(`mDNS broadcast started with name "${subdomain}.local"`);
});
},
});
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
};
// Handle server shutdown and stop broadcasting
process.on("SIGINT", () => {
bonjour.unpublishAll(() => {
bonjour.destroy();
console.log("mDNS broadcast stopped");
process.exit(0);
});
});
start(); |
Beta Was this translation helpful? Give feedback.
-
Hi there,
I've been working through implementing multi-tenancy in my payload instance based on the multi-tenant example directory.
One thing I've been stuck on is following this comment regarding the tenant field.
Based on my understanding of this, I would expect that we could either:
Create a new component that wraps the base
relationship
field, fetch the complete user object, and then return null if the role is incorrect. Two issues I can see with this:useAuth
React Hook provides detailed enough user information to evaluate the role.Add a condition the the field itself - This doesn't appear possible based on the limited user param passed to condition fields.
Has anyone else run into this?
Beta Was this translation helpful? Give feedback.
All reactions