| 775 | } |
| 776 | |
| 777 | public async Task<BoardInviteDto> CreateBoardInviteAsync(int boardId, string role, int requesterId) |
| 778 | { |
| 779 | var board = await _db.Boards.Include(b => b.Members).FirstOrDefaultAsync(b => b.Id == boardId); |
| 780 | |
| 781 | if (board == null) throw new KeyNotFoundException("Board not found"); |
| 782 | |
| 783 | // Only Workspace Owners or Admins can create board invites |
| 784 | var workspace = await _db.Workspaces |
| 785 | .Include(w => w.Members) |
| 786 | .FirstOrDefaultAsync(w => w.Id == board.WorkspaceId); |
| 787 | |
| 788 | if (workspace == null) throw new KeyNotFoundException("Workspace not found"); |
| 789 | |
| 790 | var isWsAdmin = workspace.OwnerId == requesterId || |
| 791 | workspace.Members.Any(m => m.UserId == requesterId && m.Role == "Admin" && m.Status == "Accepted"); |
| 792 | |
| 793 | if (!isWsAdmin) |
| 794 | throw new UnauthorizedAccessException("Only workspace admins can create invite links for boards."); |
| 795 | |
| 796 | var invite = new BoardInvite |
| 797 | { |
| 798 | Token = Guid.NewGuid().ToString("N"), |
| 799 | BoardId = boardId, |
| 800 | Role = role, |
| 801 | CreatorId = requesterId, |
| 802 | CreatedAt = DateTime.UtcNow, |
| 803 | IsActive = true |
| 804 | }; |
| 805 | |
| 806 | _db.BoardInvites.Add(invite); |
| 807 | await _db.SaveChangesAsync(); |
| 808 | |
| 809 | return new BoardInviteDto |
| 810 | { |
| 811 | Token = invite.Token, |
| 812 | Role = invite.Role, |
| 813 | BoardId = invite.BoardId, |
| 814 | BoardName = board.Name, |
| 815 | CreatedAt = invite.CreatedAt |
| 816 | }; |
| 817 | } |
| 818 | |
| 819 | public async Task<BoardInviteDto?> GetBoardInviteByTokenAsync(string token) |
| 820 | { |