This release includes 1 security fix for security teams reviewing exposed deployments.
Topics
+11 more
Affected surfaces
Summary
AI summaryBroad release touches Service Layer Updates, Permission System Overhaul, New Models, and Modified (8 files).
Full changelog
[2.1.0] - 2025-12-28
🎯 Major Feature: Strict RBAC with Multi-Owner Project Support
Complete implementation of Role-Based Access Control (RBAC) with support for multiple owners per project and comprehensive audit logging.
✨ Added
New Roles
- Added
Managerrole to the system- Full access to all projects
- Can assign/remove project members
- Cannot be assigned as project member (admin-level role)
New Models
-
ProjectMember Model (
server/src/Models/ProjectMember.ts)- Enables many-to-many relationship between Projects and Users
- Distinguishes between
owner(creator) andmember(assigned developer) - Tracks who added the member and when
- Unique constraint on (ProjectId, UserId)
- Prevents duplicate memberships
-
ProjectAuditLog Model (
server/src/Models/ProjectAuditLog.ts)- Comprehensive audit trail for all project modifications
- Tracks: Action, EntityType, Changes (JSON), IP Address, User Agent, Timestamp
- Supported actions:
create,update,deleteadd_member,remove_memberregenerate_webhooktoggle_ssh_key,regenerate_ssh_key
- Indexes on ProjectId, UserId, Timestamp, and Action for fast queries
New Database Migrations
-
Migration 002 (
002_create_project_members.ts)- Creates ProjectMembers table
- Migrates existing projects (adds creators as owners)
- Adds unique constraint on (ProjectId, UserId)
- Adds indexes for performance
-
Migration 003 (
003_create_project_audit_logs.ts)- Creates ProjectAuditLogs table
- Adds comprehensive indexes for querying audit history
New Service
- AuditLogService (
server/src/Services/AuditLogService.ts)- Centralized audit logging for all modifications
- Automatically captures IP address and User Agent
- Helper methods for common operations:
RecordProjectCreation()RecordProjectUpdate()- tracks changed fieldsRecordProjectDeletion()RecordWebhookRegeneration()RecordSshKeyToggle()RecordMemberAddition()RecordMemberRemoval()RecordConfigUpdate()RecordPipelineUpdate()
New API Endpoints
GET /api/projects/:id/members- Get all members of a projectPOST /api/projects/:id/members- Add member to project (Admin/Manager only)DELETE /api/projects/:id/members/:userId- Remove member from project (Admin/Manager only)
New Middleware Methods
-
RoleMiddleware:
RequireAdminOrManager- For admin/manager-only operationsRequireAdminManagerOrDeveloper- For all non-viewer operationsIsManager()- Check if user is a managerIsAdminOrManager()- Check if user is admin or manager
-
ProjectAccessMiddleware:
CheckProjectDeleteAccess- STRICT validation for project deletion- Only allows owners to delete (members cannot delete)
- Admin/Manager have full access
🔧 Changed
Permission System Overhaul
-
Project Creation:
- BEFORE: Admin only
- AFTER: Admin, Manager, or Developer
- Developers automatically become owners of their created projects
-
Project Update:
- BEFORE: Admin only
- AFTER: Admin/Manager or Project Owner/Member
- All modifications are audit logged
-
Project Deletion (STRICT):
- BEFORE: Admin only
- AFTER: Admin/Manager or Project Owner ONLY
- Members CANNOT delete projects (even if they can modify)
- Deletion is audit logged before execution
-
Webhook Regeneration:
- BEFORE: Admin only
- AFTER: Admin/Manager or Project Owner/Member
- Audit logged with timestamp
Enhanced Middleware
- ProjectAccessMiddleware - Complete rewrite:
- Now checks
ProjectMembertable instead ofCreatedByfield - Stores membership info in
req.projectMembershipfor controllers - Three validation levels:
CheckProjectAccess- View access (owners + members)CheckProjectModifyAccess- Modification access (owners + members)CheckProjectDeleteAccess- Delete access (owners only - STRICT)
- Now checks
Service Layer Updates
-
ProjectService.CreateProject():
- Now accepts
Requestparameter for audit logging - Automatically adds creator as owner in ProjectMember table
- Records project creation in audit log
- Now accepts
-
ProjectService.UpdateProject():
- Now accepts
Requestparameter for audit logging - Tracks changed fields automatically
- Records before/after values in audit log
- Only logs if fields actually changed
- Now accepts
-
ProjectService.DeleteProject():
- Now accepts
Requestparameter for audit logging - Records deletion in audit log before soft delete
- Now accepts
-
ProjectService.RegenerateWebhookSecret():
- Now accepts
Requestparameter for audit logging - Records webhook regeneration with timestamp
- Now accepts
-
ProjectService.ToggleSshKeyUsage():
- Now accepts
Requestparameter for audit logging - Records SSH key toggle with enabled/disabled state
- Now accepts
-
New ProjectService Methods:
GetProjectMembers(projectId)- Get all members with user detailsAddProjectMember(projectId, userId, role, addedBy, req)- Add member with audit logRemoveProjectMember(projectId, userId, req)- Remove member with validation- Prevents removing the last owner from a project
Model Associations
-
Added associations for ProjectMember:
Project.hasMany(ProjectMember, { as: 'Members' })User.hasMany(ProjectMember, { as: 'ProjectMemberships' })
-
Added associations for ProjectAuditLog:
Project.hasMany(ProjectAuditLog, { as: 'AuditLogs' })User.hasMany(ProjectAuditLog, { as: 'ProjectAuditLogs' })
🔒 Security Enhancements
Strict Permission Enforcement
- Developers can only delete projects they own (Role='owner' in ProjectMember)
- Members can modify but cannot delete projects
- Cannot remove the last owner from a project
- All modifications are logged with IP address and User Agent
- Before/after values tracked for all changes
Audit Trail
- Every project modification is logged with:
- User ID (who made the change)
- IP Address (where the change came from)
- User Agent (what client was used)
- Timestamp (when it happened)
- Changes (what changed - JSON format with before/after)
- Action type (create, update, delete, etc.)
- Entity type (project, config, pipeline, etc.)
📊 Final Permission Matrix
| Action | Admin | Manager | Developer (Owner) | Developer (Member) | Viewer |
|--------|-------|---------|-------------------|-------------------|--------|
| Create Project | ✅ | ✅ | ✅ | ✅ | ❌ |
| View Project | ✅ | ✅ | ✅ (own/member) | ✅ (own/member) | ✅ (all) |
| Update Project | ✅ | ✅ | ✅ (own/member) | ✅ (own/member) | ❌ |
| Delete Project | ✅ | ✅ | ✅ Owner ONLY | ❌ Cannot | ❌ |
| Regenerate Webhook | ✅ | ✅ | ✅ (own/member) | ✅ (own/member) | ❌ |
| Add Member | ✅ | ✅ | ❌ | ❌ | ❌ |
| Remove Member | ✅ | ✅ | ❌ | ❌ | ❌ |
| SSH Operations | ✅ | ✅ | ✅ (with access) | ✅ (with access) | ❌ |
🗄️ Database Schema Changes
-- New Table: ProjectMembers
CREATE TABLE ProjectMembers (
Id INT PRIMARY KEY AUTO_INCREMENT,
ProjectId INT NOT NULL,
UserId INT NOT NULL,
Role ENUM('owner', 'member') NOT NULL DEFAULT 'member',
AddedBy INT NOT NULL,
AddedAt DATETIME NOT NULL DEFAULT NOW(),
CreatedAt DATETIME NOT NULL DEFAULT NOW(),
UpdatedAt DATETIME NOT NULL DEFAULT NOW(),
UNIQUE KEY unique_project_user (ProjectId, UserId),
INDEX idx_project_members_project_id (ProjectId),
INDEX idx_project_members_user_id (UserId),
FOREIGN KEY (ProjectId) REFERENCES Projects(Id) ON DELETE CASCADE,
FOREIGN KEY (UserId) REFERENCES Users(UserId) ON DELETE CASCADE,
FOREIGN KEY (AddedBy) REFERENCES Users(UserId)
);
-- New Table: ProjectAuditLogs
CREATE TABLE ProjectAuditLogs (
Id INT PRIMARY KEY AUTO_INCREMENT,
ProjectId INT NOT NULL,
UserId INT NOT NULL,
Action ENUM('create', 'update', 'delete', 'add_member', 'remove_member',
'regenerate_webhook', 'toggle_ssh_key', 'regenerate_ssh_key') NOT NULL,
EntityType ENUM('project', 'config', 'pipeline', 'webhook', 'ssh_key', 'member') NOT NULL,
Changes TEXT NOT NULL,
IpAddress VARCHAR(45),
UserAgent TEXT,
Timestamp DATETIME NOT NULL DEFAULT NOW(),
CreatedAt DATETIME NOT NULL DEFAULT NOW(),
UpdatedAt DATETIME NOT NULL DEFAULT NOW(),
INDEX idx_project_audit_project_id (ProjectId),
INDEX idx_project_audit_user_id (UserId),
INDEX idx_project_audit_timestamp (Timestamp),
INDEX idx_project_audit_action (Action),
FOREIGN KEY (ProjectId) REFERENCES Projects(Id) ON DELETE CASCADE,
FOREIGN KEY (UserId) REFERENCES Users(UserId)
);
📝 Files Changed
Created (5 files)
server/src/Models/ProjectMember.tsserver/src/Models/ProjectAuditLog.tsserver/src/Migrations/002_create_project_members.tsserver/src/Migrations/003_create_project_audit_logs.tsserver/src/Services/AuditLogService.ts
Modified (8 files)
server/src/Types/ICommon.ts- Added Manager roleserver/src/Models/index.ts- Added new model exports and associationsserver/src/Database/MigrationRunner.ts- Added new migrationsserver/src/Middleware/RoleMiddleware.ts- Added Manager supportserver/src/Middleware/ProjectAccessMiddleware.ts- Complete rewrite for multi-ownerserver/src/Routes/ProjectRoutes.ts- Updated permissions and added member endpointsserver/src/Controllers/ProjectController.ts- Added audit logging and member managementserver/src/Services/ProjectService.ts- Added audit logging and member management
🚀 Migration Instructions
To apply these changes to your database:
# Run migrations
npm run migrate
# Or manually through the application
# Migrations will run automatically on server start
Migration Order:
001_add_created_by_to_projects(existing)002_create_project_members(new) - Creates table and migrates existing projects003_create_project_audit_logs(new) - Creates audit log table
⚠️ Breaking Changes
- ProjectService.CreateProject() now requires
Requestparameter - ProjectService.UpdateProject() now requires
Requestparameter - ProjectService.DeleteProject() now requires
Requestparameter - ProjectService.RegenerateWebhookSecret() now requires
Requestparameter - ProjectService.ToggleSshKeyUsage() now requires
Requestparameter
Migration Guide:
// Before:
await projectService.CreateProject(data);
// After:
await projectService.CreateProject(data, req);
🐛 Bug Fixes
- Fixed TypeScript strict mode issues with optional request parameters
- Fixed IP address extraction from forwarded headers
- Improved validation for request parameter parsing
📚 Documentation
- Added comprehensive inline documentation for all new methods
- Updated model documentation with association details
- Added permission matrix documentation in middleware
Full Changelog: https://github.com/FutureSolutionDev/Deploy-Center-Server/compare/2.1.0...2.1.1
Breaking Changes
- ProjectService.CreateProject(), UpdateProject(), DeleteProject(), RegenerateWebhookSecret(), ToggleSshKeyUsage() now require a `Request` parameter
- Permission matrix changes: only owners can delete projects; members cannot delete, and new roles/permissions introduced
Security Fixes
- Strict permission enforcement prevents non‑owners from deleting projects and logs all modifications with full request metadata
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About FutureSolutionDev/Deploy-Center-Server
All releases →Beta — feedback welcome: [email protected]