mirror of
https://github.com/bitwarden/server.git
synced 2025-07-04 01:22:50 -05:00
org members public api
This commit is contained in:
@ -4,7 +4,7 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public abstract class BaseAssociationWithPermissionsModel
|
||||
public abstract class AssociationWithPermissionsBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated object's unique identifier.
|
55
src/Core/Models/Api/Public/MemberBaseModel.cs
Normal file
55
src/Core/Models/Api/Public/MemberBaseModel.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public abstract class MemberBaseModel
|
||||
{
|
||||
public MemberBaseModel() { }
|
||||
|
||||
public MemberBaseModel(OrganizationUser user)
|
||||
{
|
||||
if(user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Type = user.Type;
|
||||
AccessAll = user.AccessAll;
|
||||
ExternalId = user.ExternalId;
|
||||
}
|
||||
|
||||
public MemberBaseModel(OrganizationUserUserDetails user)
|
||||
{
|
||||
if(user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Type = user.Type;
|
||||
AccessAll = user.AccessAll;
|
||||
ExternalId = user.ExternalId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The member's type (or role) within the organization.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public OrganizationUserType? Type { get; set; }
|
||||
/// <summary>
|
||||
/// Determines if this member can access all collections within the organization, or only the associated
|
||||
/// collections. If set to <c>true</c>, this option overrides any collection assignments.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool? AccessAll { get; set; }
|
||||
/// <summary>
|
||||
/// External identifier linking this member to another system, such as a user directory.
|
||||
/// </summary>
|
||||
/// <example>external_id_123456</example>
|
||||
[StringLength(300)]
|
||||
public string ExternalId { get; set; }
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public class AssociationWithPermissionsRequestModel : BaseAssociationWithPermissionsModel
|
||||
public class AssociationWithPermissionsRequestModel : AssociationWithPermissionsBaseModel
|
||||
{
|
||||
public SelectionReadOnly ToSelectionReadOnly()
|
||||
{
|
||||
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public class MemberCreateRequestModel : MemberUpdateRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The member's email address.
|
||||
/// </summary>
|
||||
/// <example>jsmith@company.com</example>
|
||||
[Required]
|
||||
[EmailAddress]
|
||||
public string Email { get; set; }
|
||||
|
||||
public override OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public class MemberUpdateRequestModel : MemberBaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The associated collections that this member can access.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsRequestModel> Collections { get; set; }
|
||||
|
||||
public virtual OrganizationUser ToOrganizationUser(OrganizationUser existingUser)
|
||||
{
|
||||
existingUser.Type = Type.Value;
|
||||
existingUser.AccessAll = AccessAll.Value;
|
||||
existingUser.ExternalId = ExternalId;
|
||||
return existingUser;
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ using Bit.Core.Models.Data;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
public class AssociationWithPermissionsResponseModel : BaseAssociationWithPermissionsModel
|
||||
public class AssociationWithPermissionsResponseModel : AssociationWithPermissionsBaseModel
|
||||
{
|
||||
public AssociationWithPermissionsResponseModel(SelectionReadOnly selection)
|
||||
{
|
||||
|
88
src/Core/Models/Api/Public/Response/MemberResponseModel.cs
Normal file
88
src/Core/Models/Api/Public/Response/MemberResponseModel.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Table;
|
||||
|
||||
namespace Bit.Core.Models.Api.Public
|
||||
{
|
||||
/// <summary>
|
||||
/// An organization member.
|
||||
/// </summary>
|
||||
public class MemberResponseModel : MemberBaseModel, IResponseModel
|
||||
{
|
||||
public MemberResponseModel(OrganizationUser user, IEnumerable<SelectionReadOnly> collections)
|
||||
: base(user)
|
||||
{
|
||||
if(user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Id = user.Id;
|
||||
Email = user.Email;
|
||||
Status = user.Status;
|
||||
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
|
||||
}
|
||||
|
||||
public MemberResponseModel(OrganizationUserUserDetails user, bool twoFactorEnabled,
|
||||
IEnumerable<SelectionReadOnly> collections)
|
||||
: base(user)
|
||||
{
|
||||
if(user == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
Id = user.Id;
|
||||
Name = user.Name;
|
||||
Email = user.Email;
|
||||
TwoFactorEnabled = twoFactorEnabled;
|
||||
Status = user.Status;
|
||||
Collections = collections?.Select(c => new AssociationWithPermissionsResponseModel(c));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// String representing the object's type. Objects of the same type share the same properties.
|
||||
/// </summary>
|
||||
/// <example>member</example>
|
||||
[Required]
|
||||
public string Object => "member";
|
||||
/// <summary>
|
||||
/// The member's unique identifier.
|
||||
/// </summary>
|
||||
/// <example>539a36c5-e0d2-4cf9-979e-51ecf5cf6593</example>
|
||||
[Required]
|
||||
public Guid Id { get; set; }
|
||||
/// <summary>
|
||||
/// The member's name, set from their user account profile.
|
||||
/// </summary>
|
||||
/// <example>John Smith</example>
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// The member's email address.
|
||||
/// </summary>
|
||||
/// <example>jsmith@company.com</example>
|
||||
[Required]
|
||||
public string Email { get; set; }
|
||||
/// <summary>
|
||||
/// Returns <c>true</c> if the member has a two-step login method enabled on their user account.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
/// <summary>
|
||||
/// The member's status within the organization. All created members start with a status of "Invited".
|
||||
/// Once a member accept's their invitation to join the organization, their status changes to "Accepted".
|
||||
/// Accepted members are then "Confirmed" by an organization administrator. Once a member is "Confirmed",
|
||||
/// their status can no longer change.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public OrganizationUserStatusType Status { get; set; }
|
||||
/// <summary>
|
||||
/// The associated collections that this member can access.
|
||||
/// </summary>
|
||||
public IEnumerable<AssociationWithPermissionsResponseModel> Collections { get; set; }
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ namespace Bit.Core.Services
|
||||
Task ResendInviteAsync(Guid organizationId, Guid invitingUserId, Guid organizationUserId);
|
||||
Task<OrganizationUser> AcceptUserAsync(Guid organizationUserId, User user, string token);
|
||||
Task<OrganizationUser> ConfirmUserAsync(Guid organizationId, Guid organizationUserId, string key, Guid confirmingUserId);
|
||||
Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<SelectionReadOnly> collections);
|
||||
Task SaveUserAsync(OrganizationUser user, Guid? savingUserId, IEnumerable<SelectionReadOnly> collections);
|
||||
Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId);
|
||||
Task DeleteUserAsync(Guid organizationId, Guid userId);
|
||||
Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds);
|
||||
|
@ -871,9 +871,14 @@ namespace Bit.Core.Services
|
||||
public async Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid? invitingUserId, string email,
|
||||
OrganizationUserType type, bool accessAll, string externalId, IEnumerable<SelectionReadOnly> collections)
|
||||
{
|
||||
var result = await InviteUserAsync(organizationId, invitingUserId, new List<string> { email }, type, accessAll,
|
||||
var results = await InviteUserAsync(organizationId, invitingUserId, new List<string> { email }, type, accessAll,
|
||||
externalId, collections);
|
||||
return result.FirstOrDefault();
|
||||
var result = results.FirstOrDefault();
|
||||
if(result == null)
|
||||
{
|
||||
throw new BadRequestException("This user has already been invited.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<OrganizationUser>> InviteUserAsync(Guid organizationId, Guid? invitingUserId,
|
||||
@ -1062,16 +1067,17 @@ namespace Bit.Core.Services
|
||||
return orgUser;
|
||||
}
|
||||
|
||||
public async Task SaveUserAsync(OrganizationUser user, Guid savingUserId, IEnumerable<SelectionReadOnly> collections)
|
||||
public async Task SaveUserAsync(OrganizationUser user, Guid? savingUserId,
|
||||
IEnumerable<SelectionReadOnly> collections)
|
||||
{
|
||||
if(user.Id.Equals(default(Guid)))
|
||||
{
|
||||
throw new BadRequestException("Invite the user first.");
|
||||
}
|
||||
|
||||
if(user.Type == OrganizationUserType.Owner)
|
||||
if(savingUserId.HasValue && user.Type == OrganizationUserType.Owner)
|
||||
{
|
||||
var savingUserOrgs = await _organizationUserRepository.GetManyByUserAsync(savingUserId);
|
||||
var savingUserOrgs = await _organizationUserRepository.GetManyByUserAsync(savingUserId.Value);
|
||||
if(!savingUserOrgs.Any(u => u.OrganizationId == user.OrganizationId && u.Type == OrganizationUserType.Owner))
|
||||
{
|
||||
throw new BadRequestException("Only owners can update other owners.");
|
||||
|
Reference in New Issue
Block a user