feat: role-based feature visibility — App Profiles + Platform Profiles (backend) - #2669
Open
ppatel9703 wants to merge 25 commits into
Open
feat: role-based feature visibility — App Profiles + Platform Profiles (backend)#2669ppatel9703 wants to merge 25 commits into
ppatel9703 wants to merge 25 commits into
Conversation
…rm Profiles) Part A — App Profiles: - AbstractSecurityUtils: 4 new tables (APP_PROFILE, APP_FEATURE, APP_PROFILE_FEATURE, APP_USER_PROFILE) bootstrapped in initialize() - AppProfileUtils: full CRUD for profiles, features, profile-feature assignments, user-profile assignments, and feature evaluation (checkFeature, getUserFeatures — enabled-only, fail-closed) - 16 reactors in prerna.reactor.appprofile covering all Pixel operations - SecurityProjectUtils: cascade deleteUserProfile calls in removeProjectUser, removeExpiredProjectUser, and removeProjectUsers to prevent stale assignments Part B — Platform Profiles: - AbstractSecurityUtils: 3 new tables (PLATFORM_PROFILE, PLATFORM_PROFILE_FEATURE, PLATFORM_USER_PROFILE) - PlatformProfileUtils: CRUD for platform profiles, predefined nav-key feature toggles, user assignments, and getUserFeatures (fail-open for unassigned users) - 9 reactors in prerna.reactor.platformprofile Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
getProfiles() and getFeatures() used SelectQueryStruct/WrapperManager which performs OWL metadata lookups. APP_PROFILE and APP_FEATURE are not registered in SEMOSS's schema, so getPhysicalPropertyNameFromConceptualName returns null causing NPE during SQL composition. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add getPlatformProfileUsers() to PlatformProfileUtils — queries PLATFORM_USER_PROFILE for all users assigned to a given profile - Add GetPlatformProfileUsersReactor (admin-only) so the admin UI Members tab can list users assigned to each platform profile Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Contributor
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
…code quality - Multi-profile: users can be assigned to multiple profiles simultaneously; GetAppUserFeatures returns union of features across all assignments - Group-style profiles (isGroup=true): named sub-groups with independent feature flags; users assigned to sub-groups via AssignAppUserSubgroup - Delegated BU admin: APP_PROFILE_MANAGER table grants 'assign' permission so non-owners can manage user assignments without full profile management rights - New DB tables: APP_PROFILE_SUBGROUP, APP_SUBGROUP_FEATURE, APP_USER_SUBGROUP, APP_PROFILE_MANAGER (via SecurityOwlCreator + AbstractSecurityUtils migration) - New Pixel commands: GetUserAppProfiles, GetAppUserFeatures, CheckAppFeature, AssignAppUserProfile, RemoveAppUserProfile, CreateAppSubgroup, UpdateAppSubgroup, DeleteAppSubgroup, GetAppSubgroups, SetAppSubgroupFeature, GetAppSubgroupFeatures, AssignAppUserSubgroup, RemoveAppUserSubgroup, AddAppProfileManager, GetAppProfileManagers, RemoveAppProfileManager, GetUserAppProfile - Renamed for domain clarity: GetProfileFeatures→GetAppProfileFeatures, SetProfileFeature→SetAppProfileFeature, SetSubgroupFeature→SetAppSubgroupFeature, GetSubgroupFeatures→GetAppSubgroupFeatures, GetSubgroupUsers→GetAppSubgroupUsers, GetProfileUsers→GetAppProfileUsers, AddProfileManager→AddAppProfileManager, GetProfileManagers→GetAppProfileManagers, RemoveProfileManager→RemoveAppProfileManager - Backwards-compat aliases kept with @deprecated for old Pixel names - Code quality: classLogger on all reactors, ReactorKeysEnum constants for all key strings (9 new enum entries added), PixelOperationType on all NounMetadata returns, CUSTOM_DATA_STRUCTURE for list-of-maps (was VECTOR), N+1 queries eliminated in getProfiles() and getSubgroups() via SQL subqueries, canEvaluateFeatures admin bypass added - featureKey param renamed from "key" in CreateAppFeature/UpdateAppFeature Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d read access to profile managers - AppProfileUtils: `getExplicitUserSubgroups` now returns PROFILE_ID so the parent group profile can be looked up for each subgroup membership - AppProfileUtils: `checkFeature` now unions subgroup features with the parent group profile's base features, so group-level toggles apply to all members - AppProfileUtils: `getUserFeatures` does the same union for the full feature list returned to the client - 8 read-only reactors (GetAppFeatures, GetAppProfileFeatures, GetAppProfileManagers, GetAppProfileUsers, GetAppProfiles, GetAppSubgroupFeatures, GetAppSubgroups, GetUserProfile) changed from `canManageProfiles` to `canAssignProfiles` so profile managers can view profiles and assign users without needing full admin - PlatformProfileUtils: import cleanup and remove deprecated nav.build from predefined feature keys Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c, convert reads to SQS - Move AppProfileUtils from prerna.auth.utils to prerna.reactor.appprofile - Move PlatformProfileUtils from prerna.auth.utils to prerna.reactor.platformprofile - Add prerna.reactor.appprofile and prerna.reactor.platformprofile to SecurityDb access allowlist in SystemEngineRegistry - Add SecurityProjectUtils import for relocated AppProfileUtils - Convert AppProfileUtils.getFeatures() from PreparedStatement to SelectQueryStruct (simple single-table read); keep correlated subqueries and JOINs as PreparedStatement - Add class-level Javadoc to all 34 appprofile reactors and 10 platform- profile reactors - Add method-level Javadoc to all public static methods in both util classes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…and convert reads to QS - Move 30 appprofile reactors from flat package into feature/, profile/, subgroup/, manager/, user/ sub-packages for maintainability - Remove legacy alias reactors (AssignUserProfile, RemoveUserProfile, GetUserAppProfile, GetUserFeatures) that duplicated newer equivalents - Refactor AppProfileUtils read methods to use aliased QueryColumnSelector + QueryExecutionUtility.flushRsToMap/flushToInteger, eliminating raw JDBC (ResultSet, WrapperManager, PreparedStatement) from all read paths - Replace correlated subqueries in getProfiles/getSubgroups with LEFT JOIN + GROUP BY + COUNT via QS relations - Convert PlatformProfileUtils reads to same QS + QueryExecutionUtility pattern; replace canManage check with SecurityAdminUtils.userIsAdmin Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AssignAppUserProfile, AssignAppUserSubgroup, and AssignUserPlatformProfile now accept a list of userIds so the frontend can batch-assign in one call. Each user is processed independently and the response buckets assigned, skipped (already in profile), and errors (user not found or DB error). Platform profiles remain one-per-user by design — assigning a user already in a different platform profile replaces that assignment (DELETE + INSERT). App profiles continue to be additive — a user can be in multiple profiles. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the entire IS_GROUP/subgroup hierarchy from the app profile system. All profiles are now flat — features and users are managed directly on the profile, with no subgroup layer. Deleted (9 files): - subgroup/AssignAppUserSubgroupReactor.java - subgroup/CreateAppSubgroupReactor.java - subgroup/DeleteAppSubgroupReactor.java - subgroup/GetAppSubgroupFeaturesReactor.java - subgroup/GetAppSubgroupUsersReactor.java - subgroup/GetAppSubgroupsReactor.java - subgroup/RemoveAppUserSubgroupReactor.java - subgroup/SetAppSubgroupFeatureReactor.java - subgroup/UpdateAppSubgroupReactor.java Modified: - AppProfileUtils: removed all subgroup CRUD/query methods; createProfile/ updateProfile signatures drop isGroup param (always writes false to DB); getProfiles removes IS_GROUP from SELECT/GROUP BY; deleteProfile removes subgroup cascade; getUserFeatures returns Map<String,Boolean>; feature resolution is now explicit-profile → default-profile (no subgroup step); getExplicitUserProfiles rewritten as two-query in-memory join; adds duplicate profile name guard on createProfile; removes canEvaluateFeatures - CreateAppProfileReactor: removed IS_GROUP key from keysToGet/keyRequired - UpdateAppProfileReactor: removed IS_GROUP key from keysToGet/keyRequired - CheckAppFeatureReactor, CheckFeatureReactor, GetAppUserFeaturesReactor: removed canEvaluateFeatures access guard (any app viewer can evaluate) - GetUserAppProfilesReactor: updated return type to List<Map<String,Object>>, removed canEvaluateFeatures guard Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Role-Based Feature Visibility system to SEMOSS with two independent subsystems:
Both systems are backed by new security DB tables, fully integrated into the SEMOSS OWL/metamodel, and exposed via Pixel reactors.
What Changed
New Tables (Security DB)
App Profile system — 5 tables (group/subgroup tables removed in this branch):
APP_FEATUREfeatureId,featureKey,appId)APP_PROFILEisDefaultflag;IS_GROUPcolumn retained but alwaysfalse)APP_PROFILE_FEATUREAPP_USER_PROFILEAPP_PROFILE_MANAGERPlatform Profile system — 3 tables:
PLATFORM_PROFILEPLATFORM_PROFILE_FEATUREPLATFORM_USER_PROFILETables are created in
AbstractSecurityUtilson startup (idempotentCREATE IF NOT EXISTS) and registered inSecurityOwlCreatorwith full OWL relations.App Profile Reactors — 21 reactors in
src/prerna/reactor/appprofile/feature/CreateAppFeature,UpdateAppFeature,DeleteAppFeature,GetAppFeaturesCheckAppFeature,CheckFeature(alias),GetAppUserFeaturesprofile/CreateAppProfile,UpdateAppProfile,DeleteAppProfile,GetAppProfilesSetAppProfileFeature,GetAppProfileFeatures,GetAppProfileUsersmanager/AddAppProfileManager,RemoveAppProfileManager,GetAppProfileManagersuser/AssignAppUserProfile,RemoveAppUserProfileGetUserAppProfiles,GetUserProfile(legacy alias)Removed in this branch (group/subgroup model):
subgroup/— 9 reactors deleted:CreateAppSubgroup,UpdateAppSubgroup,DeleteAppSubgroup,GetAppSubgroups,SetAppSubgroupFeature,GetAppSubgroupFeatures,GetAppSubgroupUsers,AssignAppUserSubgroup,RemoveAppUserSubgroupPlatform Profile Reactors — 10 reactors in
src/prerna/reactor/platformprofile/CreatePlatformProfile,UpdatePlatformProfile,DeletePlatformProfile,GetPlatformProfilesSetPlatformFeature,GetPlatformFeaturesAssignUserPlatformProfile,RemoveUserPlatformProfile,GetPlatformProfileUsersGetUserPlatformFeaturesSupporting Changes
AbstractSecurityUtils.javaSecurityOwlCreator.javaReactorKeysEnum.javaFEATURE_KEY,ENABLED,IS_DEFAULT,IS_GROUP,PROFILE_IDkeysSystemEngineRegistry.javaprerna.reactor.appprofileto security DB allowed prefix setKey Design Decisions
Flat Profile Model (group/subgroup removed)
The original design included group-type profiles with subgroups, which caused four concrete bugs:
setProfileFeaturethrew for group profiles but the UI rendered toggles anywayuserCountwas wrong for group profiles (countedAPP_USER_PROFILEnotAPP_USER_SUBGROUP)All profiles are now flat. Feature states are set directly on the profile.
IS_GROUPcolumn is retained in the DB schema for continuity but is always written asfalseand never read.Feature Resolution Order (App Profiles)
IS_DEFAULT=true) as fallbackfalseif no assignment and no defaultAccess Control
APP_PROFILE_MANAGERfor that appCheckAppFeature,GetAppUserFeatures,GetUserAppProfiles): any authenticated user, returns only their own data —canEvaluateFeaturesguard removedgetUserFeatures return type
AppProfileUtils.getUserFeaturesnow returnsMap<String, Boolean>(featureKey → true/false for every feature in the app's catalogue). Previously returnedMap<String, Object>with nested feature metadata.getExplicitUserProfiles — two-query in-memory join
OWL join traversal between
APP_USER_PROFILEandAPP_PROFILEwas unreliable. Replaced with two single-table queries joined in memory.Duplicate profile name guard
createProfilerejects duplicate names per app at the application layer before INSERT.Bulk Assignment
AssignAppUserProfileaccepts a list of user IDs. Returns{ assigned, skipped, errors }— each user processed independently.Platform Profile — replace semantics
A user can be in at most one platform profile. Assigning to a new profile deletes the prior assignment first. App profiles are additive (a user can be in multiple).
How to Test
Checklist
RDF_Map.prop,social.properties,db/,server.xml)AbstractSecurityUtilsSecurityOwlCreatorSystemEngineRegistryallowlist updated for new package prefixQueryColumnSelectoraliases +QueryExecutionUtility(no raw JDBC for reads)