Skip to main content

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:

  1. Owner enters email and clicks "Add"
  2. Frontend calls RbacService.inviteUserToProject()
  3. Backend validates ownership and allowlist
  4. Firebase custom claims updated immediately
  5. PermissionRefreshService notifies of changes
  6. UI refreshes member list and clears form

Remove User Flow:

  1. Owner clicks role chip → dropdown appears
  2. Owner clicks "Remove access"
  3. Frontend calls RbacService.removeUserFromProject()
  4. Backend validates ownership and removes permissions
  5. Firebase custom claims updated immediately
  6. PermissionRefreshService notifies of changes
  7. 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

RoleValueColorPermissions
Owner4Primary (Blue)Full management
Editor3Default (Gray)Edit content
Prompter2Warn (Orange)AI prompts
Reader1Accent (Purple)View only

User Experience

Project Owner Experience:

  1. Clear Control: All management options available
  2. Visual Feedback: Loading states and confirmations
  3. Error Handling: Clear error messages
  4. Immediate Updates: Real-time permission changes

Non-Owner Experience:

  1. Read-Only View: Can see all members and roles
  2. Clear Messaging: Understands permission limitations
  3. No Broken UI: All controls properly disabled
  4. 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.