Just wrapped up a migration from our old user management system to a more modern, API-driven platform. On paper, it was a success—all 500 users and their core data (emails, IDs, profiles) moved over cleanly. But we’re now in a nightmare scenario where the permissions layer seems completely broken post-cutover.
Users are authenticated, but they can’t see their projects, files, or dashboards. It’s like they’re logged into a blank slate. The old system used a simple role-based model stored in a SQL join table, but the new system uses a more complex policy structure defined in JSON. We mapped the roles directly, but the actual *resources* each user owns don’t seem to be linked anymore.
I suspect the issue is in how we translated the relationships. We migrated the `users` table and the `roles` table, but the new platform’s permission system requires a `user_id`, `resource_type`, and `resource_id` triplet for every access grant. Our old system just had a `user_has_project` table. Did we need to generate a policy object for every single user-resource pair during the migration? That feels wrong.
Has anyone else hit this wall after a user directory migration? Specifically, how did you handle the translation of flat, relational permissions into a modern policy-based system? I’m worried our cutover plan was too focused on data presence and not on functional access. The transition itself took a weekend, but we’re going on 48 hours of critical access issues.
—Eli
Connecting the dots.
Oof, that sounds rough. I'm still learning about permissions, but your hunch about the missing triplet data feels right. If the new system needs that `user_id`, `resource_type`, `resource_id` for every single thing a user owns, then yeah, you'd need to generate a policy object for each of those old `user_has_project` entries, wouldn't you? It's not just the role, it's the specific resource link.
Maybe you could write a script now to read the old join table and create the JSON policies for the new system? A one-time batch job to build those relationships. Good luck!
Oh man, that's such a classic migration trap. Mapping the roles but losing the individual resource assignments is exactly what happened to us last quarter with our Salesforce reports. We moved everyone to a new permission set model and suddenly, reps could only see generic accounts, not their actual territories.
You mentioned the old `user_has_project` table. If your new system needs that explicit user-resource link, then yeah, I think you do need to generate a policy for each pair. It's tedious, but maybe you can still run that translation script from your old database? That join table is your source of truth for who had access to what before.
What happens if you manually create one of those JSON policy objects for a single test user and resource? Does it fix the problem for just that one thing? That would at least confirm the theory.
That's a classic case of mapping data structures incorrectly. You moved the nouns (users, roles) but not the verbs (permissions).
The `user_has_project` table *is* your source of truth. For each row there, you need to generate the corresponding JSON policy object for the new system. It's not wrong, it's just the cost of moving to a more granular permission model. I'd write a backfill script that does this:
1. Query the old `user_has_project` table.
2. For each row, build a policy JSON with the user_id, resource_type (likely 'project'), and resource_id.
3. Batch-insert these into the new system's policy store.
Test it with one user first. If it works, run it for all 500. You'll probably have to do the same for files and dashboards if they had their own join tables.