Skip to content

Commit 785fcb0

Browse files
author
Lasim
committed
feat: add team and team membership functionality
- Introduced new tables for teams and team memberships in the SQLite schema. - Implemented TeamService to handle team creation, retrieval, and management. - Added logic to create a default team for users upon registration. - Updated database migration files to reflect the new schema changes. - Enhanced the schema definitions to include enums for team roles. - Modified the registration process to include team creation.
1 parent c1054c7 commit 785fcb0

File tree

12 files changed

+1453
-3
lines changed

12 files changed

+1453
-3
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ You can also run DeployStack on your own infrastructure for maximum control:
9292

9393
3. Start development servers:
9494

95+
Create a `services/backend/.env` file in the root directory with the following content:
96+
97+
```env
98+
DEPLOYSTACK_FRONTEND_URL=http://localhost:5173
99+
```
100+
95101
```bash
96102
# Start frontend development server
97103
npm run dev:frontend

services/backend/ROLES.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,198 @@ The RBAC system provides fine-grained access control through roles and permissio
2424
- `users.create` - Create new users
2525
- `roles.manage` - Manage roles and permissions
2626
- `system.admin` - Administrative system access
27+
- `teams.create` - Create new teams
28+
- `teams.view` - View team details
29+
- `teams.edit` - Edit team settings
30+
- `teams.delete` - Delete teams
31+
- `teams.manage` - Full team management
32+
- `team.members.view` - View team members
33+
- `team.members.manage` - Manage team member roles
2734

2835
### Global User (`global_user`)
2936

3037
- **Description**: Standard user with basic profile access
3138
- **Permissions**:
3239
- `profile.view` - View own profile
3340
- `profile.edit` - Edit own profile
41+
- `teams.create` - Create new teams (up to 3)
42+
- `teams.view` - View team details
43+
- `teams.edit` - Edit own team settings
44+
- `teams.delete` - Delete own teams
45+
- `team.members.view` - View team members
46+
47+
### Team Administrator (`team_admin`)
48+
49+
- **Description**: Full management access within a specific team
50+
- **Permissions**:
51+
- `teams.view` - View team details
52+
- `teams.edit` - Edit team settings
53+
- `teams.delete` - Delete team (if owner)
54+
- `teams.manage` - Full team management
55+
- `team.members.view` - View team members
56+
- `team.members.manage` - Manage team member roles
57+
58+
### Team User (`team_user`)
59+
60+
- **Description**: Basic team member with limited access
61+
- **Permissions**:
62+
- `teams.view` - View team details
63+
- `team.members.view` - View team members
64+
65+
## Team System
66+
67+
DeployStack includes a comprehensive team management system that allows users to organize their work into teams. Each user automatically gets their own team upon registration and can create up to 3 teams total.
68+
69+
### Team Features
70+
71+
- **Automatic Team Creation**: Every new user gets a default team created with their username
72+
- **Team Ownership**: Each team has an owner who has full administrative control
73+
- **Single User Teams**: Currently, teams support only one user per team
74+
- **Team Limits**: Users can create up to 3 teams maximum
75+
- **Unique Slugs**: Teams have URL-friendly slugs with automatic conflict resolution
76+
77+
### Team Database Schema
78+
79+
#### Teams Table
80+
81+
```sql
82+
CREATE TABLE teams (
83+
id TEXT PRIMARY KEY,
84+
name TEXT NOT NULL,
85+
slug TEXT NOT NULL UNIQUE,
86+
description TEXT,
87+
owner_id TEXT NOT NULL REFERENCES authUser(id) ON DELETE CASCADE,
88+
created_at INTEGER NOT NULL,
89+
updated_at INTEGER NOT NULL
90+
);
91+
```
92+
93+
#### Team Memberships Table
94+
95+
```sql
96+
CREATE TABLE teamMemberships (
97+
id TEXT PRIMARY KEY,
98+
team_id TEXT NOT NULL REFERENCES teams(id) ON DELETE CASCADE,
99+
user_id TEXT NOT NULL REFERENCES authUser(id) ON DELETE CASCADE,
100+
role TEXT NOT NULL, -- 'team_admin' or 'team_user'
101+
joined_at INTEGER NOT NULL,
102+
UNIQUE(team_id, user_id)
103+
);
104+
```
105+
106+
### Team Registration Flow
107+
108+
When a user registers:
109+
110+
1. User account is created with appropriate global role
111+
2. A default team is automatically created using the user's username
112+
3. The user is added as `team_admin` of their new team
113+
4. If username conflicts exist, slug gets incremented (e.g., `john-doe-2`)
114+
115+
### Team Management
116+
117+
#### Team Creation
118+
119+
- Users can create up to 3 teams
120+
- Team names are converted to URL-friendly slugs
121+
- Automatic conflict resolution for duplicate slugs
122+
- Team owner becomes `team_admin` automatically
123+
124+
#### Team Roles
125+
126+
- **Team Admin**: Full control over team settings and management
127+
- **Team User**: Basic team member (for future expansion)
128+
129+
#### Team Permissions
130+
131+
| Permission | Description |
132+
|------------|-------------|
133+
| `teams.create` | Create new teams (up to limit) |
134+
| `teams.view` | View team details |
135+
| `teams.edit` | Edit team settings |
136+
| `teams.delete` | Delete team |
137+
| `teams.manage` | Full team management |
138+
| `team.members.view` | View team members |
139+
| `team.members.manage` | Manage team member roles |
140+
141+
### Team API Endpoints
142+
143+
#### Get User's Teams
144+
145+
```http
146+
GET /api/users/me/teams
147+
Authorization: Required (authenticated user)
148+
```
149+
150+
#### Create Team
151+
152+
```http
153+
POST /api/teams
154+
Authorization: Required (teams.create permission)
155+
Content-Type: application/json
156+
157+
{
158+
"name": "My New Team",
159+
"description": "Team description"
160+
}
161+
```
162+
163+
#### Get Team by ID
164+
165+
```http
166+
GET /api/teams/:id
167+
Authorization: Required (teams.view permission)
168+
```
169+
170+
#### Update Team
171+
172+
```http
173+
PUT /api/teams/:id
174+
Authorization: Required (teams.edit permission)
175+
Content-Type: application/json
176+
177+
{
178+
"name": "Updated Team Name",
179+
"description": "Updated description"
180+
}
181+
```
182+
183+
#### Delete Team
184+
185+
```http
186+
DELETE /api/teams/:id
187+
Authorization: Required (teams.delete permission)
188+
```
189+
190+
#### Get Team Members
191+
192+
```http
193+
GET /api/teams/:id/members
194+
Authorization: Required (team.members.view permission)
195+
```
196+
197+
### Team Service Methods
198+
199+
The `TeamService` class provides comprehensive team management:
200+
201+
```typescript
202+
// Create team
203+
const team = await TeamService.createTeam({
204+
name: 'My Team',
205+
owner_id: userId,
206+
description: 'Team description'
207+
});
208+
209+
// Get user's teams
210+
const teams = await TeamService.getUserTeams(userId);
211+
212+
// Check team limits
213+
const canCreate = await TeamService.canUserCreateTeam(userId);
214+
215+
// Team membership checks
216+
const isAdmin = await TeamService.isTeamAdmin(teamId, userId);
217+
const isOwner = await TeamService.isTeamOwner(teamId, userId);
218+
```
34219

35220
## Database Schema
36221

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
PRAGMA foreign_keys=OFF;--> statement-breakpoint
2+
CREATE TABLE `__new_authUser` (
3+
`id` text PRIMARY KEY NOT NULL,
4+
`username` text NOT NULL,
5+
`email` text NOT NULL,
6+
`auth_type` text NOT NULL,
7+
`first_name` text,
8+
`last_name` text,
9+
`github_id` text,
10+
`hashed_password` text,
11+
`role_id` text,
12+
FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`) ON UPDATE no action ON DELETE no action
13+
);
14+
--> statement-breakpoint
15+
INSERT INTO `__new_authUser`("id", "username", "email", "auth_type", "first_name", "last_name", "github_id", "hashed_password", "role_id") SELECT "id", "username", "email", "auth_type", "first_name", "last_name", "github_id", "hashed_password", "role_id" FROM `authUser`;--> statement-breakpoint
16+
DROP TABLE `authUser`;--> statement-breakpoint
17+
ALTER TABLE `__new_authUser` RENAME TO `authUser`;--> statement-breakpoint
18+
PRAGMA foreign_keys=ON;--> statement-breakpoint
19+
CREATE UNIQUE INDEX `authUser_username_unique` ON `authUser` (`username`);--> statement-breakpoint
20+
CREATE UNIQUE INDEX `authUser_email_unique` ON `authUser` (`email`);--> statement-breakpoint
21+
CREATE UNIQUE INDEX `authUser_github_id_unique` ON `authUser` (`github_id`);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
CREATE TABLE `teamMemberships` (
2+
`id` text PRIMARY KEY NOT NULL,
3+
`team_id` text NOT NULL,
4+
`user_id` text NOT NULL,
5+
`role` text NOT NULL,
6+
`joined_at` integer NOT NULL,
7+
FOREIGN KEY (`team_id`) REFERENCES `teams`(`id`) ON UPDATE no action ON DELETE cascade,
8+
FOREIGN KEY (`user_id`) REFERENCES `authUser`(`id`) ON UPDATE no action ON DELETE cascade
9+
);
10+
--> statement-breakpoint
11+
CREATE TABLE `teams` (
12+
`id` text PRIMARY KEY NOT NULL,
13+
`name` text NOT NULL,
14+
`slug` text NOT NULL,
15+
`description` text,
16+
`owner_id` text NOT NULL,
17+
`created_at` integer NOT NULL,
18+
`updated_at` integer NOT NULL,
19+
FOREIGN KEY (`owner_id`) REFERENCES `authUser`(`id`) ON UPDATE no action ON DELETE cascade
20+
);
21+
--> statement-breakpoint
22+
CREATE UNIQUE INDEX `teams_slug_unique` ON `teams` (`slug`);

0 commit comments

Comments
 (0)