Sharing Settings UI Implementation
Overview
The sharing settings window has been completely implemented with full invite and remove user functionality. Only project owners can manage project access, with enforcement at both frontend and backend levels.
Key Features
✅ Owner-Only Access Control
- Frontend: UI controls only enabled for project owners
- Backend: API calls rejected for non-owners
- Visual Indicators: Clear messaging for non-owners
✅ Invite Users
- Email Input: Enabled for project owners
- Default Role: New users invited as "Reader"
- Real-time Updates: Immediate token refresh and UI updates
- Validation: Email format and duplicate prevention
✅ Remove User Access
- Role Dropdown: Click role chip to see options
- Remove Option: "Remove access" in dropdown menu
- Safety: Owners cannot remove themselves
- Immediate Effect: Real-time permission updates
✅ Smart UI
- Permission Notice: Info message for non-owners
- Loading States: Visual feedback during operations
- Error Handling: Clear error messages
- Role Colors: Visual distinction between roles
Updated Components
ShareDialogComponent - web-ng-m3/src/app/components/share-dialog/share-dialog.component.ts
New Methods:
// Check if current user is project owner
async isCurrentUserProjectOwner(projectId: string): Promise<boolean>
// Invite user to project
async onAddPeople(): Promise<void>
// Remove user from project
async onRemoveUser(member: ProjectMember): Promise<void>
// Check if user can be managed
canManageUser(member: ProjectMember): boolean
// Get role color for chips
getRoleColor(role: number): string
New Properties:
isOwner: boolean = false; // Current user is project owner
currentUserEmail: string | null; // Current user's email
RbacService - web-ng-m3/src/app/services/rbac.service.ts
New Methods:
// Check ownership
async isCurrentUserProjectOwner(projectId: string): Promise<boolean>
// Remove user (now properly implemented)
async removeUserFromProject(projectId: string, userEmail: string): Promise<any>
UI Implementation
Role Management
For Non-Owners:
<mat-chip-set class="role-chip">
<mat-chip [color]="getRoleColor(member.role)" selected>
{{ member.roleDisplayName }}
</mat-chip>
</mat-chip-set>
For Owners:
<button mat-button [matMenuTriggerFor]="roleMenu" class="role-button">
<mat-chip [color]="getRoleColor(member.role)" selected>
{{ member.roleDisplayName }}
</mat-chip>
<mat-icon>arrow_drop_down</mat-icon>
</button>
<mat-menu #roleMenu="matMenu">
<button mat-menu-item (click)="onRemoveUser(member)">
<mat-icon color="warn">person_remove</mat-icon>
<span>Remove access</span>
</button>
</mat-menu>
Invite Users Section
Input Field:
<mat-form-field [matTooltip]="isOwner ? 'Enter email address to invite user as Reader' : 'Only project owners can invite users'">
<input matInput
[(ngModel)]="newMemberEmail"
placeholder="Enter email address"
type="email"
[disabled]="!isOwner || loading">
<button mat-icon-button matSuffix
(click)="onAddPeople()"
[disabled]="!isOwner || loading || !newMemberEmail.trim()">
<mat-icon>person_add</mat-icon>
</button>
</mat-form-field>
Permission Notice:
<div *ngIf="!isOwner" class="permission-notice">
<mat-icon>info</mat-icon>
<span>Only project owners can manage access to this project.</span>
</div>
Permission Flow
Invite User Flow:
- Owner enters email and clicks "Add"
- Frontend calls
RbacService.inviteUserToProject() - Backend validates ownership and allowlist
- Firebase custom claims updated immediately
- PermissionRefreshService notifies of changes
- UI refreshes member list and clears form
Remove User Flow:
- Owner clicks role chip → dropdown appears
- Owner clicks "Remove access"
- Frontend calls
RbacService.removeUserFromProject() - Backend validates ownership and removes permissions
- Firebase custom claims updated immediately
- PermissionRefreshService notifies of changes
- UI refreshes member list
Security Features
Frontend Protection:
- ✅ Controls disabled for non-owners
- ✅ Self-removal prevention
- ✅ Input validation
- ✅ Loading states prevent double-clicks
Backend Protection:
- ✅
isProjectOwner()check on all operations - ✅ Google Group allowlist validation
- ✅ User existence validation
- ✅ Audit logging
Real-time Updates:
- ✅ Immediate Firebase token refresh
- ✅ Cache clearing on permission changes
- ✅ UI state synchronization
- ✅ Error handling and rollback
Role System
| Role | Value | Color | Permissions |
|---|---|---|---|
| Owner | 4 | Primary (Blue) | Full management |
| Editor | 3 | Default (Gray) | Edit content |
| Prompter | 2 | Warn (Orange) | AI prompts |
| Reader | 1 | Accent (Purple) | View only |
User Experience
Project Owner Experience:
- Clear Control: All management options available
- Visual Feedback: Loading states and confirmations
- Error Handling: Clear error messages
- Immediate Updates: Real-time permission changes
Non-Owner Experience:
- Read-Only View: Can see all members and roles
- Clear Messaging: Understands permission limitations
- No Broken UI: All controls properly disabled
- Informative: Helpful tooltips and notices
Testing Scenarios
Invite User Testing:
# 1. As project owner
- Enter valid email → should invite successfully
- Enter existing member email → should show error
- Enter invalid email → should show validation error
# 2. As non-owner
- All controls should be disabled
- Should see permission notice
Remove User Testing:
# 1. As project owner
- Click other user's role chip → should show dropdown
- Click "Remove access" → should remove user
- Try to remove self → should show error
# 2. As non-owner
- Click role chips → should be non-interactive
- No dropdown menus available
Future Enhancements
Phase 2: Role Management
- Add role change options to dropdown
- Support for multiple role types
- Bulk permission operations
Phase 3: Advanced Features
- Invitation expiration
- Email notifications
- Permission templates
- Access request system
Troubleshooting
Common Issues:
User Still Has Access After Removal:
- Check browser console for permission refresh logs
- Try hard refresh (
Ctrl+F5) - Verify Firebase token refresh occurred
Invite Button Disabled:
- Verify current user is project owner
- Check for JavaScript errors
- Ensure email field has valid content
Role Dropdown Not Appearing:
- Verify user is project owner
- Check if clicking on other users (not self)
- Ensure Material Menu module imported
Debug Logs:
[ShareDialog] Current user is project owner: true
[RbacService] Inviting user@example.com to project PROJECT-123 with role 1
[PermissionRefreshService] Permission change detected: invite user@example.com for project PROJECT-123
[ShareDialog] Successfully invited user, reloading members
Implementation Status
✅ Complete Features:
- Project ownership checking
- User invitation with email validation
- User removal with safety checks
- Real-time permission updates
- UI/UX for both owners and non-owners
- Error handling and loading states
- Role visualization with colors
- Permission refresh coordination
🚀 Ready for Production Use!
The sharing settings window now provides a complete, secure, and user-friendly experience for project collaboration management.