diff --git a/Backend.Tests/Controllers/UserRoleControllerTests.cs b/Backend.Tests/Controllers/UserRoleControllerTests.cs index a8689173ab..fe8830466d 100644 --- a/Backend.Tests/Controllers/UserRoleControllerTests.cs +++ b/Backend.Tests/Controllers/UserRoleControllerTests.cs @@ -48,7 +48,12 @@ public async Task Setup() _projId = (await _projRepo.Create(new Project { Name = "UserRoleControllerTests" }))!.Id; } - private UserRole RandomUserRole(Role role = Role.Harvester) + private ProjectRole ProjectRoleInProj(Role role = Role.Harvester) + { + return new ProjectRole { ProjectId = _projId, Role = role }; + } + + private UserRole UserRoleInProj(Role role = Role.Harvester) { return new UserRole { ProjectId = _projId, Role = role }; } @@ -59,7 +64,7 @@ public async Task TestGetAllUserRoles() var roles = new List { Role.Harvester, Role.Editor, Role.Administrator }; foreach (var role in roles) { - await _userRoleRepo.Create(RandomUserRole(role)); + await _userRoleRepo.Create(UserRoleInProj(role)); } var getResult = await _userRoleController.GetProjectUserRoles(_projId); @@ -97,14 +102,14 @@ public async Task TestHasPermissionNotAuthorized() [Test] public async Task TestGetCurrentPermissions() { - var userRole = await _userRoleRepo.Create(RandomUserRole()); + var userRole = await _userRoleRepo.Create(UserRoleInProj()); var user = await _userRepo.Create(new User()); _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.HttpContextWithUserId(user!.Id); user.ProjectRoles[_projId] = userRole.Id; await _userRepo.Update(user.Id, user); - await _userRoleRepo.Create(RandomUserRole()); - await _userRoleRepo.Create(RandomUserRole()); + await _userRoleRepo.Create(UserRoleInProj()); + await _userRoleRepo.Create(UserRoleInProj()); var result = await _userRoleController.GetCurrentPermissions(_projId); Assert.That(result, Is.InstanceOf()); @@ -179,7 +184,7 @@ public async Task TestGetCurrentPermissionsNotAuthorized() [Test] public async Task TestCreateUserRole() { - var userRole = RandomUserRole(); + var userRole = UserRoleInProj(); var id = (string)((ObjectResult)await _userRoleController.CreateUserRole(_projId, userRole)).Value!; userRole.Id = id; Assert.That(await _userRoleRepo.GetAllUserRoles(_projId), Does.Contain(userRole)); @@ -188,7 +193,7 @@ public async Task TestCreateUserRole() [Test] public async Task TestCreateUserRolesMissingProject() { - var userRole = RandomUserRole(); + var userRole = UserRoleInProj(); var result = await _userRoleController.CreateUserRole(MissingId, userRole); Assert.That(result, Is.InstanceOf()); } @@ -197,20 +202,29 @@ public async Task TestCreateUserRolesMissingProject() public async Task TestCreateUserRolesNoPermission() { _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.UnauthorizedHttpContext(); - var userRole = await _userRoleRepo.Create(RandomUserRole()); + var userRole = await _userRoleRepo.Create(UserRoleInProj()); var result = await _userRoleController.CreateUserRole(_projId, userRole); Assert.That(result, Is.InstanceOf()); } + [Test] + public async Task TestCreateUserRolesSecondOwner() + { + var firstOwner = await _userRoleController.CreateUserRole(_projId, UserRoleInProj(Role.Owner)); + Assert.That(firstOwner, Is.InstanceOf()); + var secondOwner = await _userRoleController.CreateUserRole(_projId, UserRoleInProj(Role.Owner)); + Assert.That(secondOwner, Is.InstanceOf()); + } + [Test] public async Task TestUpdateUserRole() { - var userRole = RandomUserRole(Role.Harvester); + var userRole = UserRoleInProj(Role.Harvester); await _userRoleRepo.Create(userRole); var user = new User { ProjectRoles = { [_projId] = userRole.Id } }; var userId = (await _userRepo.Create(user))!.Id; _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.HttpContextWithUserId(userId); - var projectRole = new ProjectRole { ProjectId = _projId, Role = Role.Editor }; + var projectRole = ProjectRoleInProj(Role.Editor); await _userRoleController.UpdateUserRole(userId, projectRole); var result = await _userRoleController.GetCurrentPermissions(_projId); @@ -226,13 +240,12 @@ public async Task TestUpdateUserRole() [Test] public async Task TestUpdateUserRoleNoChange() { - var userRole = RandomUserRole(Role.Harvester); + var userRole = UserRoleInProj(Role.Harvester); await _userRoleRepo.Create(userRole); var user = new User { ProjectRoles = { [_projId] = userRole.Id } }; var userId = (await _userRepo.Create(user))!.Id; _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.HttpContextWithUserId(userId); - var projectRole = new ProjectRole { ProjectId = _projId, Role = userRole.Role }; - var result = await _userRoleController.UpdateUserRole(userId, projectRole); + var result = await _userRoleController.UpdateUserRole(userId, ProjectRoleInProj(userRole.Role)); Assert.That(((ObjectResult)result).StatusCode, Is.EqualTo(StatusCodes.Status304NotModified)); } @@ -240,7 +253,7 @@ public async Task TestUpdateUserRoleNoChange() public async Task TestCreateNewUpdateUserRole() { var userId = (await _userRepo.Create(new User()))!.Id; - var projectRole = new ProjectRole { ProjectId = _projId, Role = Role.Editor }; + var projectRole = ProjectRoleInProj(Role.Editor); var updateResult = await _userRoleController.UpdateUserRole(userId, projectRole); var newUserRoleId = (string)((OkObjectResult)updateResult).Value!; _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.HttpContextWithUserId(userId); @@ -258,12 +271,11 @@ public async Task TestCreateNewUpdateUserRole() [Test] public async Task TestUpdateUserRolesMissingIds() { - var projectRole = new ProjectRole { ProjectId = _projId, Role = Role.Editor }; - + var projectRole = ProjectRoleInProj(Role.Editor); var missingUserIdResult = await _userRoleController.UpdateUserRole(MissingId, projectRole); Assert.That(missingUserIdResult, Is.InstanceOf()); - var userRoleId = (await _userRoleRepo.Create(RandomUserRole(Role.Harvester))).Id; + var userRoleId = (await _userRoleRepo.Create(UserRoleInProj(Role.Harvester))).Id; projectRole.ProjectId = MissingId; var missingProjIdResult = await _userRoleController.UpdateUserRole(userRoleId, projectRole); Assert.That(missingProjIdResult, Is.InstanceOf()); @@ -273,15 +285,35 @@ public async Task TestUpdateUserRolesMissingIds() public async Task TestUpdateUserRolesNoPermission() { _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.UnauthorizedHttpContext(); - var userRoleId = (await _userRoleRepo.Create(RandomUserRole(Role.Harvester))).Id; - var result = await _userRoleController.UpdateUserRole(userRoleId, new ProjectRole()); + var userRoleId = (await _userRoleRepo.Create(UserRoleInProj(Role.Harvester))).Id; + var result = await _userRoleController.UpdateUserRole(userRoleId, ProjectRoleInProj()); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestUpdateUserRolesToOwner() + { + var userRoleId = (await _userRoleRepo.Create(UserRoleInProj(Role.Administrator))).Id; + var user = new User { ProjectRoles = { [_projId] = userRoleId } }; + var userId = (await _userRepo.Create(user))!.Id; + var result = await _userRoleController.UpdateUserRole(userId, ProjectRoleInProj(Role.Owner)); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestUpdateUserRolesFromOwner() + { + var userRoleId = (await _userRoleRepo.Create(UserRoleInProj(Role.Owner))).Id; + var user = new User { ProjectRoles = { [_projId] = userRoleId } }; + var userId = (await _userRepo.Create(user))!.Id; + var result = await _userRoleController.UpdateUserRole(userId, ProjectRoleInProj(Role.Administrator)); Assert.That(result, Is.InstanceOf()); } [Test] public async Task TestDeleteUserRole() { - var userRole = RandomUserRole(); + var userRole = UserRoleInProj(); await _userRoleRepo.Create(userRole); var user = new User { ProjectRoles = { [_projId] = userRole.Id } }; var userId = (await _userRepo.Create(user))!.Id; @@ -305,16 +337,30 @@ public async Task TestDeleteUserRole() public async Task TestDeleteUserRoleNoPermission() { _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.UnauthorizedHttpContext(); - var userRole = await _userRoleRepo.Create(RandomUserRole()); - var result = await _userRoleController.DeleteUserRole(_projId, userRole.Id); + var userRole = await _userRoleRepo.Create(UserRoleInProj()); + var user = new User { ProjectRoles = { [_projId] = userRole.Id } }; + var userId = (await _userRepo.Create(user))!.Id; + var result = await _userRoleController.DeleteUserRole(_projId, userId); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestDeleteUserRoleOwner() + { + var userRole = await _userRoleRepo.Create(UserRoleInProj(Role.Owner)); + var user = new User { ProjectRoles = { [_projId] = userRole.Id } }; + var userId = (await _userRepo.Create(user))!.Id; + var result = await _userRoleController.DeleteUserRole(_projId, userId); Assert.That(result, Is.InstanceOf()); } [Test] public async Task TestDeleteUserRoleMissingIds() { - var userRole = await _userRoleRepo.Create(RandomUserRole()); - var projectResult = await _userRoleController.DeleteUserRole(MissingId, userRole.Id); + var userRole = await _userRoleRepo.Create(UserRoleInProj()); + var user = new User { ProjectRoles = { [_projId] = userRole.Id } }; + var userId = (await _userRepo.Create(user))!.Id; + var projectResult = await _userRoleController.DeleteUserRole(MissingId, userId); Assert.That(projectResult, Is.InstanceOf()); var wordResult = await _userRoleController.DeleteUserRole(_projId, MissingId); @@ -324,9 +370,9 @@ public async Task TestDeleteUserRoleMissingIds() [Test] public async Task TestDeleteAllUserRoles() { - await _userRoleRepo.Create(RandomUserRole()); - await _userRoleRepo.Create(RandomUserRole()); - await _userRoleRepo.Create(RandomUserRole()); + await _userRoleRepo.Create(UserRoleInProj()); + await _userRoleRepo.Create(UserRoleInProj()); + await _userRoleRepo.Create(UserRoleInProj()); Assert.That(await _userRoleRepo.GetAllUserRoles(_projId), Has.Count.EqualTo(3)); @@ -348,5 +394,98 @@ public async Task TestDeleteAllUserRolesNoPermission() var result = await _userRoleController.DeleteProjectUserRoles(_projId); Assert.That(result, Is.InstanceOf()); } + + [Test] + public async Task TestChangeOwnerNoPermission() + { + _userRoleController.ControllerContext.HttpContext = PermissionServiceMock.UnauthorizedHttpContext(); + var oldRole = await _userRoleRepo.Create(UserRoleInProj(Role.Owner)); + var oldOwner = new User { ProjectRoles = { [_projId] = oldRole.Id } }; + var oldId = (await _userRepo.Create(oldOwner))!.Id; + var newId = (await _userRepo.Create(new()))!.Id; + + var result = await _userRoleController.ChangeOwner(_projId, oldId, newId); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestChangeOwnerSameId() + { + var oldRole = await _userRoleRepo.Create(UserRoleInProj(Role.Owner)); + var oldOwner = new User { ProjectRoles = { [_projId] = oldRole.Id } }; + var oldId = (await _userRepo.Create(oldOwner))!.Id; + var newId = (await _userRepo.Create(new()))!.Id; + + var result = await _userRoleController.ChangeOwner(_projId, oldId, oldId); + Assert.That(result, Is.InstanceOf()); + + result = await _userRoleController.ChangeOwner(_projId, newId, newId); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestChangeOwnerMissingProjectOrUser() + { + var oldRole = await _userRoleRepo.Create(UserRoleInProj(Role.Owner)); + var oldOwner = new User { ProjectRoles = { [_projId] = oldRole.Id } }; + var oldId = (await _userRepo.Create(oldOwner))!.Id; + var newId = (await _userRepo.Create(new()))!.Id; + + var result = await _userRoleController.ChangeOwner(MissingId, oldId, newId); + Assert.That(result, Is.InstanceOf()); + + result = await _userRoleController.ChangeOwner(_projId, MissingId, newId); + Assert.That(result, Is.InstanceOf()); + + result = await _userRoleController.ChangeOwner(_projId, oldId, MissingId); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestChangeOwnerOldUserNotOwner() + { + var oldRole = await _userRoleRepo.Create(UserRoleInProj(Role.Editor)); + var oldEditor = new User { ProjectRoles = { [_projId] = oldRole.Id } }; + var oldEditorId = (await _userRepo.Create(oldEditor))!.Id; + var oldOtherId = (await _userRepo.Create(new()))!.Id; + var newId = (await _userRepo.Create(new()))!.Id; + + var result = await _userRoleController.ChangeOwner(_projId, oldEditorId, newId); + Assert.That(result, Is.InstanceOf()); + + result = await _userRoleController.ChangeOwner(_projId, oldOtherId, newId); + Assert.That(result, Is.InstanceOf()); + } + + [Test] + public async Task TestChangeOwnerNewRole() + { + var oldRole = await _userRoleRepo.Create(UserRoleInProj(Role.Owner)); + var oldOwner = new User { ProjectRoles = { [_projId] = oldRole.Id } }; + var oldId = (await _userRepo.Create(oldOwner))!.Id; + var newId = (await _userRepo.Create(new()))!.Id; + + var result = await _userRoleController.ChangeOwner(_projId, oldId, newId); + Assert.That(result, Is.InstanceOf()); + Assert.That((await _userRoleRepo.GetUserRole(_projId, oldRole.Id))?.Role, Is.EqualTo(Role.Administrator)); + var newRoleId = (await _userRepo.GetUser(newId))!.ProjectRoles[_projId]; + Assert.That((await _userRoleRepo.GetUserRole(_projId, newRoleId))?.Role, Is.EqualTo(Role.Owner)); + } + + [Test] + public async Task TestChangeOwnerUpdateRole() + { + var oldRole = await _userRoleRepo.Create(UserRoleInProj(Role.Owner)); + var oldOwner = new User { ProjectRoles = { [_projId] = oldRole.Id } }; + var oldId = (await _userRepo.Create(oldOwner))!.Id; + var newRole = await _userRoleRepo.Create(UserRoleInProj()); + var newOwner = new User { ProjectRoles = { [_projId] = newRole.Id } }; + var newId = (await _userRepo.Create(newOwner))!.Id; + + var result = await _userRoleController.ChangeOwner(_projId, oldId, newId); + Assert.That(result, Is.InstanceOf()); + Assert.That((await _userRoleRepo.GetUserRole(_projId, oldRole.Id))?.Role, Is.EqualTo(Role.Administrator)); + Assert.That((await _userRoleRepo.GetUserRole(_projId, newRole.Id))?.Role, Is.EqualTo(Role.Owner)); + } } } diff --git a/Backend/Controllers/UserRoleController.cs b/Backend/Controllers/UserRoleController.cs index b87331dee3..290dd9d90d 100644 --- a/Backend/Controllers/UserRoleController.cs +++ b/Backend/Controllers/UserRoleController.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using BackendFramework.Helper; using BackendFramework.Interfaces; @@ -147,6 +148,13 @@ public async Task CreateUserRole(string projectId, [FromBody, Bin return NotFound(projectId); } + // Prevent a second project owner + if (userRole.Role == Role.Owner + && (await _userRoleRepo.GetAllUserRoles(projectId)).Any((role) => role.Role == Role.Owner)) + { + return Forbid("This project already has an owner"); + } + await _userRoleRepo.Create(userRole); return Ok(userRole.Id); } @@ -183,6 +191,12 @@ public async Task DeleteUserRole(string projectId, string userId) return NotFound(userRoleId); } + // Prevent deleting the project owner. + if (userRole.Role == Role.Owner) + { + return Forbid("Cannot use this function to remove the project owner's role"); + } + // Prevent deleting role of another user who has more permissions than the actor. if (!await _permissionService.ContainsProjectRole(HttpContext, userRole.Role, projectId)) { @@ -212,6 +226,11 @@ public async Task UpdateUserRole( return Forbid(); } + // Prevent making a new project owner. + if (projectRole.Role == Role.Owner) + { + return Forbid("Cannot use this function to give a user the project owner role"); + } // Prevent upgrading another user to have more permissions than the actor. if (!await _permissionService.ContainsProjectRole(HttpContext, projectRole.Role, projectId)) { @@ -248,6 +267,11 @@ public async Task UpdateUserRole( return NotFound(userRoleId); } + // Prevent downgrading the project owner. + if (userRole.Role == Role.Owner) + { + return Forbid("Cannot use this function to change the project owner's role"); + } // Prevent downgrading another user who has more permissions than the actor. if (!await _permissionService.ContainsProjectRole(HttpContext, userRole.Role, projectId)) { @@ -263,5 +287,95 @@ public async Task UpdateUserRole( _ => StatusCode(StatusCodes.Status304NotModified, userRoleId) }; } + + /// + /// Change project owner from user with first specified id to user with second specified id. + /// Can only be used by the project owner or a site admin. + /// + /// Id of updated UserRole + [HttpGet("changeowner/{oldUserId}/{newUserId}", Name = "ChangeOwner")] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))] + public async Task ChangeOwner(string projectId, string oldUserId, string newUserId) + { + // Ensure the actor has sufficient permission to change project owner + if (!await _permissionService.ContainsProjectRole(HttpContext, Role.Owner, projectId)) + { + return Forbid(); + } + + // Ensure that the old and new owners' ids are different + if (oldUserId.Equals(newUserId, System.StringComparison.OrdinalIgnoreCase)) + { + return BadRequest($"the user ids for the old and new owners should be different"); + } + + // Ensure the project exists + var proj = await _projRepo.GetProject(projectId); + if (proj is null) + { + return NotFound(projectId); + } + + // Fetch the users + var oldOwner = await _userRepo.GetUser(oldUserId, false); + if (oldOwner is null) + { + return NotFound(oldUserId); + } + var newOwner = await _userRepo.GetUser(newUserId, false); + if (newOwner is null) + { + return NotFound(newUserId); + } + + // Ensure that the user from whom ownership is being moved is the owner + if (!oldOwner.ProjectRoles.TryGetValue(projectId, out var oldRoleId)) + { + return BadRequest($"{oldUserId} is not a project user"); + } + var oldUserRole = await _userRoleRepo.GetUserRole(projectId, oldRoleId); + if (oldUserRole is null || oldUserRole.Role != Role.Owner) + { + return BadRequest($"{oldUserId} is not the project owner"); + } + + // Add or update the role of the new owner + ResultOfUpdate newResult; + if (!newOwner.ProjectRoles.TryGetValue(projectId, out var newRoleId)) + { + // Generate the userRole + var newUsersRole = new UserRole { ProjectId = projectId, Role = Role.Owner }; + newUsersRole = await _userRoleRepo.Create(newUsersRole); + newRoleId = newUsersRole.Id; + + // Update the user + newOwner.ProjectRoles.Add(projectId, newRoleId); + newResult = await _userRepo.Update(newOwner.Id, newOwner); + } + else + { + // Update the user role + var newUsersRole = await _userRoleRepo.GetUserRole(projectId, newRoleId); + if (newUsersRole is null) + { + return NotFound(newRoleId); + } + newUsersRole.Role = Role.Owner; + newResult = await _userRoleRepo.Update(newRoleId, newUsersRole); + } + if (newResult != ResultOfUpdate.Updated) + { + return StatusCode(StatusCodes.Status304NotModified, newRoleId); + }; + + // Change the old owner to a project admin + oldUserRole.Role = Role.Administrator; + var oldResult = await _userRoleRepo.Update(oldRoleId, oldUserRole); + return oldResult switch + { + ResultOfUpdate.Updated => Ok(oldUserRole), + _ => StatusCode(StatusCodes.Status304NotModified, oldUserRole) + }; + } } } diff --git a/src/api/api/user-role-api.ts b/src/api/api/user-role-api.ts index f7a94dd786..43f6432900 100644 --- a/src/api/api/user-role-api.ts +++ b/src/api/api/user-role-api.ts @@ -50,6 +50,60 @@ export const UserRoleApiAxiosParamCreator = function ( configuration?: Configuration ) { return { + /** + * + * @param {string} projectId + * @param {string} oldUserId + * @param {string} newUserId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + changeOwner: async ( + projectId: string, + oldUserId: string, + newUserId: string, + options: any = {} + ): Promise => { + // verify required parameter 'projectId' is not null or undefined + assertParamExists("changeOwner", "projectId", projectId); + // verify required parameter 'oldUserId' is not null or undefined + assertParamExists("changeOwner", "oldUserId", oldUserId); + // verify required parameter 'newUserId' is not null or undefined + assertParamExists("changeOwner", "newUserId", newUserId); + const localVarPath = + `/v1/projects/{projectId}/userroles/changeowner/{oldUserId}/{newUserId}` + .replace(`{${"projectId"}}`, encodeURIComponent(String(projectId))) + .replace(`{${"oldUserId"}}`, encodeURIComponent(String(oldUserId))) + .replace(`{${"newUserId"}}`, encodeURIComponent(String(newUserId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { + method: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @param {string} projectId @@ -415,6 +469,35 @@ export const UserRoleApiAxiosParamCreator = function ( export const UserRoleApiFp = function (configuration?: Configuration) { const localVarAxiosParamCreator = UserRoleApiAxiosParamCreator(configuration); return { + /** + * + * @param {string} projectId + * @param {string} oldUserId + * @param {string} newUserId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async changeOwner( + projectId: string, + oldUserId: string, + newUserId: string, + options?: any + ): Promise< + (axios?: AxiosInstance, basePath?: string) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.changeOwner( + projectId, + oldUserId, + newUserId, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, /** * * @param {string} projectId @@ -611,6 +694,24 @@ export const UserRoleApiFactory = function ( ) { const localVarFp = UserRoleApiFp(configuration); return { + /** + * + * @param {string} projectId + * @param {string} oldUserId + * @param {string} newUserId + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + changeOwner( + projectId: string, + oldUserId: string, + newUserId: string, + options?: any + ): AxiosPromise { + return localVarFp + .changeOwner(projectId, oldUserId, newUserId, options) + .then((request) => request(axios, basePath)); + }, /** * * @param {string} projectId @@ -722,6 +823,34 @@ export const UserRoleApiFactory = function ( }; }; +/** + * Request parameters for changeOwner operation in UserRoleApi. + * @export + * @interface UserRoleApiChangeOwnerRequest + */ +export interface UserRoleApiChangeOwnerRequest { + /** + * + * @type {string} + * @memberof UserRoleApiChangeOwner + */ + readonly projectId: string; + + /** + * + * @type {string} + * @memberof UserRoleApiChangeOwner + */ + readonly oldUserId: string; + + /** + * + * @type {string} + * @memberof UserRoleApiChangeOwner + */ + readonly newUserId: string; +} + /** * Request parameters for createUserRole operation in UserRoleApi. * @export @@ -862,6 +991,27 @@ export interface UserRoleApiUpdateUserRoleRequest { * @extends {BaseAPI} */ export class UserRoleApi extends BaseAPI { + /** + * + * @param {UserRoleApiChangeOwnerRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof UserRoleApi + */ + public changeOwner( + requestParameters: UserRoleApiChangeOwnerRequest, + options?: any + ) { + return UserRoleApiFp(this.configuration) + .changeOwner( + requestParameters.projectId, + requestParameters.oldUserId, + requestParameters.newUserId, + options + ) + .then((request) => request(this.axios, this.basePath)); + } + /** * * @param {UserRoleApiCreateUserRoleRequest} requestParameters Request parameters. diff --git a/src/backend/index.ts b/src/backend/index.ts index 718d125f51..250807bb5a 100644 --- a/src/backend/index.ts +++ b/src/backend/index.ts @@ -790,6 +790,15 @@ export async function removeUserRole( await userRoleApi.deleteUserRole(params, defaultOptions()); } +export async function changeProjectOwner( + projectId: string, + oldUserId: string, + newUserId: string +): Promise { + const params = { projectId, oldUserId, newUserId }; + await userRoleApi.changeOwner(params, defaultOptions()); +} + /* WordController.cs */ export async function areInFrontier( diff --git a/src/components/ProjectUsers/CancelConfirmDialogCollection.tsx b/src/components/ProjectUsers/CancelConfirmDialogCollection.tsx index eb3b5c16cb..d0c0f407b7 100644 --- a/src/components/ProjectUsers/CancelConfirmDialogCollection.tsx +++ b/src/components/ProjectUsers/CancelConfirmDialogCollection.tsx @@ -5,7 +5,11 @@ import { useTranslation } from "react-i18next"; import { toast } from "react-toastify"; import { Role } from "api/models"; -import { addOrUpdateUserRole, removeUserRole } from "backend"; +import { + addOrUpdateUserRole, + changeProjectOwner, + removeUserRole, +} from "backend"; import { CancelConfirmDialog } from "components/Dialogs"; import { asyncRefreshProjectUsers } from "components/Project/ProjectActions"; import { useAppDispatch } from "rootRedux/hooks"; @@ -97,14 +101,7 @@ export default function CancelConfirmDialogCollection( } function makeOwner(userId: string): void { - addOrUpdateUserRole(props.projectId, Role.Owner, userId) - .then(() => { - addOrUpdateUserRole( - props.projectId, - Role.Administrator, - props.currentUserId - ); - }) + changeProjectOwner(props.projectId, props.currentUserId, userId) .then(() => { setMakeOwner(false); setAnchorEl(undefined);