(ctx context.Context, req *adminv1.RemoveProjectMemberUserRequest)
| 1310 | } |
| 1311 | |
| 1312 | func (s *Server) RemoveProjectMemberUser(ctx context.Context, req *adminv1.RemoveProjectMemberUserRequest) (*adminv1.RemoveProjectMemberUserResponse, error) { |
| 1313 | observability.AddRequestAttributes(ctx, |
| 1314 | attribute.String("args.org", req.Org), |
| 1315 | attribute.String("args.project", req.Project), |
| 1316 | attribute.String("args.email", req.Email), |
| 1317 | ) |
| 1318 | |
| 1319 | proj, err := s.admin.DB.FindProjectByName(ctx, req.Org, req.Project) |
| 1320 | if err != nil { |
| 1321 | return nil, err |
| 1322 | } |
| 1323 | |
| 1324 | user, err := s.admin.DB.FindUserByEmail(ctx, req.Email) |
| 1325 | if err != nil { |
| 1326 | if !errors.Is(err, database.ErrNotFound) { |
| 1327 | return nil, err |
| 1328 | } |
| 1329 | |
| 1330 | // Only admins can remove pending invites. |
| 1331 | // NOTE: If we change invites to accept/decline (instead of auto-accept on signup), we need to revisit this. |
| 1332 | claims := auth.GetClaims(ctx) |
| 1333 | if !claims.ProjectPermissions(ctx, proj.OrganizationID, proj.ID).ManageProjectMembers { |
| 1334 | return nil, status.Error(codes.PermissionDenied, "not allowed to remove project members") |
| 1335 | } |
| 1336 | |
| 1337 | // Check if there is a pending invite |
| 1338 | invite, err := s.admin.DB.FindProjectInvite(ctx, proj.ID, req.Email) |
| 1339 | if err != nil { |
| 1340 | return nil, err |
| 1341 | } |
| 1342 | |
| 1343 | err = s.admin.DB.DeleteProjectInvite(ctx, invite.ID) |
| 1344 | if err != nil { |
| 1345 | return nil, err |
| 1346 | } |
| 1347 | return &adminv1.RemoveProjectMemberUserResponse{}, nil |
| 1348 | } |
| 1349 | |
| 1350 | // The caller must either have ManageProjectMembers permission or be the user being removed. |
| 1351 | claims := auth.GetClaims(ctx) |
| 1352 | isManager := claims.ProjectPermissions(ctx, proj.OrganizationID, proj.ID).ManageProjectMembers |
| 1353 | isSelf := claims.OwnerType() == auth.OwnerTypeUser && claims.OwnerID() == user.ID |
| 1354 | if !isManager && !isSelf { |
| 1355 | return nil, status.Error(codes.PermissionDenied, "not allowed to remove project members") |
| 1356 | } |
| 1357 | if !isSelf { |
| 1358 | currentRole, err := s.admin.DB.FindProjectMemberUserRole(ctx, proj.ID, user.ID) |
| 1359 | if err != nil { |
| 1360 | return nil, err |
| 1361 | } |
| 1362 | if currentRole.Admin && !claims.ProjectPermissions(ctx, proj.OrganizationID, proj.ID).ManageProjectAdmins { |
| 1363 | return nil, status.Error(codes.PermissionDenied, "as a non-admin you are not allowed to remove an admin") |
| 1364 | } |
| 1365 | } |
| 1366 | |
| 1367 | err = s.admin.DB.DeleteProjectMemberUser(ctx, proj.ID, user.ID) |
| 1368 | if err != nil { |
| 1369 | return nil, err |
nothing calls this directly
no test coverage detected