/// <summary> /// Adds (if needed) user or team to the shared folder and set user access permissions. /// </summary> /// <param name="sharedFolderUid">Shared Folder UID.</param> /// <param name="userId">User email or Team UID.</param> /// <param name="userType">Type of <see cref="userId"/> parameter.</param> /// <param name="options">Shared Folder User Permissions.</param> /// <returns>Awaitable task.</returns> /// <remarks> /// If <seealso cref="options"/> parameter is <c>null</c> then user gets default user permissions when added./> /// </remarks> /// <exception cref="Authentication.KeeperApiException"></exception> /// <seealso cref="IVaultSharedFolder.PutUserToSharedFolder"/> public async Task PutUserToSharedFolder(string sharedFolderUid, string userId, UserType userType, ISharedFolderUserOptions options) { var sharedFolder = this.GetSharedFolder(sharedFolderUid); var perm = this.ResolveSharedFolderAccessPath(Auth.Username, sharedFolderUid, true); if (perm == null) { throw new VaultException("You don't have permission to manage users."); } var request = new SharedFolderUpdateCommand { pt = Auth.AuthContext.SessionToken.Base64UrlEncode(), operation = "update", shared_folder_uid = sharedFolder.Uid, from_team_uid = perm.UserType == UserType.Team ? perm.UserId : null, name = CryptoUtils.EncryptAesV1(Encoding.UTF8.GetBytes(sharedFolder.Name), sharedFolder.SharedFolderKey).Base64UrlEncode(), forceUpdate = true, }; if (userType == UserType.User) { if (sharedFolder.UsersPermissions.Any(x => x.UserType == UserType.User && x.UserId == userId)) { request.updateUsers = new[] { new SharedFolderUpdateUser { Username = userId, ManageUsers = options?.ManageUsers, ManageRecords = options?.ManageRecords, } }; } else { var pkRq = new PublicKeysCommand { keyOwners = new[] { userId }, }; var pkRs = await Auth.ExecuteAuthCommand <PublicKeysCommand, PublicKeysResponse>(pkRq); if (pkRs.publicKeys == null || pkRs.publicKeys.Length == 0) { throw new VaultException($"Cannot get public key of user: {userId}"); } var pk = pkRs.publicKeys[0]; if (!string.IsNullOrEmpty(pk.resultCode)) { throw new KeeperApiException(pk.resultCode, pk.message); } var publicKey = CryptoUtils.LoadPublicKey(pk.publicKey.Base64UrlDecode()); request.addUsers = new[] { new SharedFolderUpdateUser { Username = userId, ManageUsers = options?.ManageUsers, ManageRecords = options?.ManageRecords, SharedFolderKey = CryptoUtils.EncryptRsa(sharedFolder.SharedFolderKey, publicKey).Base64UrlEncode(), } }; } } else { if (sharedFolder.UsersPermissions.Any(x => x.UserType == UserType.Team && x.UserId == userId)) { request.updateTeams = new[] { new SharedFolderUpdateTeam { TeamUid = userId, ManageUsers = options?.ManageUsers, ManageRecords = options?.ManageRecords, } }; } else { string encryptedSharedFolderKey; if (TryGetTeam(userId, out var team)) { encryptedSharedFolderKey = CryptoUtils.EncryptAesV1(sharedFolder.SharedFolderKey, team.TeamKey).Base64UrlEncode(); } else { var tkRq = new TeamGetKeysCommand { teams = new[] { userId }, }; var tkRs = await Auth.ExecuteAuthCommand <TeamGetKeysCommand, TeamGetKeysResponse>(tkRq); if (tkRs.keys == null || tkRs.keys.Length == 0) { throw new VaultException($"Cannot get public key of team: {userId}"); } var tk = tkRs.keys[0]; if (!string.IsNullOrEmpty(tk.resultCode)) { throw new KeeperApiException(tk.resultCode, tk.message); } var tpk = CryptoUtils.LoadPublicKey(tk.key.Base64UrlDecode()); encryptedSharedFolderKey = CryptoUtils.EncryptRsa(sharedFolder.SharedFolderKey, tpk).Base64UrlEncode(); } request.addTeams = new[] { new SharedFolderUpdateTeam { TeamUid = userId, ManageUsers = options?.ManageUsers, ManageRecords = options?.ManageRecords, SharedFolderKey = encryptedSharedFolderKey, } }; } } var response = await Auth.ExecuteAuthCommand <SharedFolderUpdateCommand, SharedFolderUpdateResponse>(request); foreach (var arr in (new[] { response.addUsers, response.updateUsers })) { var failed = arr?.FirstOrDefault(x => x.Status != "success"); if (failed != null) { throw new VaultException($"Put \"{failed.Username}\" to Shared Folder \"{sharedFolder.Name}\" error: {failed.Status}"); } } foreach (var arr in (new[] { response.addTeams, response.updateTeams })) { var failed = arr?.FirstOrDefault(x => x.Status != "success"); if (failed != null) { throw new VaultException($"Put Team Uid \"{failed.TeamUid}\" to Shared Folder \"{sharedFolder.Name}\" error: {failed.Status}"); } } await ScheduleSyncDown(TimeSpan.FromSeconds(0)); }
public static async Task PopulateTeamKeys(this EnterpriseData enterprise, IDictionary <string, byte[]> teamKeys, Action <string> warnings = null) { var toLoad = new HashSet <string>(); foreach (var teamUid in teamKeys.Keys.ToArray()) { if (enterprise.TryGetTeam(teamUid, out var team)) { if (team.TeamKey != null) { teamKeys[teamUid] = team.TeamKey; } else { toLoad.Add(teamUid); } } } if (toLoad.Count > 0) { var teamKeyRq = new TeamGetKeysCommand { teams = toLoad.ToArray() }; var teamKeyRs = await enterprise.Auth.ExecuteAuthCommand <TeamGetKeysCommand, TeamGetKeysResponse>(teamKeyRq); if (teamKeyRs.keys != null) { foreach (var tk in teamKeyRs.keys) { byte[] key = null; if (!string.IsNullOrEmpty(tk.key)) { try { switch (tk.keyType) { case 1: key = CryptoUtils.DecryptAesV1(tk.key.Base64UrlDecode(), enterprise.Auth.AuthContext.DataKey); break; case 2: key = CryptoUtils.DecryptRsa(tk.key.Base64UrlDecode(), enterprise.Auth.AuthContext.PrivateKey); break; default: warnings?.Invoke($"Team \'{tk.teamUid}\' unsupported key type: {tk.keyType}"); break; } } catch (Exception e) { warnings?.Invoke(e.Message); } } if (key == null) { continue; } if (enterprise.TryGetTeam(tk.teamUid, out var team)) { team.TeamKey = key; } teamKeys[tk.teamUid] = key; } } } }