private async Task <UserModel> GenerateUser(RecipientRequestBase addRecipientRequest, string password) { await InitializePrivilegedConnectionAsync(); var folderIdentifier = addRecipientRequest.FolderIdentifier; var userModel = new UserModel { Identifier = ModuleUtility.GetFolderScopedUserIdentifier(folderIdentifier, addRecipientRequest.RecipientEmail, "leo"), EmailAddress = addRecipientRequest.RecipientEmail, FirstName = addRecipientRequest.FirstName, LastName = addRecipientRequest.LastName, }; userModel = await privilegedConnection.User.PostAsync(userModel); await privilegedConnection.User.PasswordPutAsync(userModel.Identifier, password); await privilegedConnection.User.AccessIdentifiersPutAsync(userModel.Identifier, new[] { "r:leoUpload", $"o:{folderIdentifier.OrganizationKey}", "x:pcms", "x:eDiscovery", $"u:{userModel.Identifier.UserKey.Replace(" ", "_")}" }); return(userModel); }
/// <summary> /// We need a way to generate users on the fly. /// </summary> /// <param name="addRecipientRequest"></param> /// <returns></returns> private async Task <UserModel> GenerateUserForEDiscovery(AddRecipientRequest addRecipientRequest, string password) { await InitializePrivilegedConnectionAsync(); var folderIdentifier = addRecipientRequest.FolderIdentifier; var userModel = new UserModel { Identifier = ModuleUtility.GetFolderScopedUserIdentifier(folderIdentifier, addRecipientRequest.RecipientEmail), EmailAddress = addRecipientRequest.RecipientEmail, FirstName = addRecipientRequest.FirstName, LastName = addRecipientRequest.LastName, }; userModel = await privilegedConnection.User.PostAsync(userModel); await privilegedConnection.User.PasswordPutAsync(userModel.Identifier, password); var accessIdentifiers = new[] { $"o:{folderIdentifier.OrganizationKey}", $"r:eDiscovery{{{folderIdentifier.FolderKey.Replace(" ", "_")}}}", // used to actually control access $"r:eDiscovery", // used to test whether a given user is an eDiscovery user $"x:pcms", // disable PCMS rules $"x:leo", // disable LEO rules }; await privilegedConnection.User.AccessIdentifiersPutAsync(userModel.Identifier, accessIdentifiers); return(userModel); }
public async Task <RecipientResponse> RemoveRecipientAsync(RemoveRecipientRequest removeRequest) { var folder = await connection.Folder.GetAsync(removeRequest.FolderIdentifier); var recipients = folder.MetaEDiscoveryRecipientListRead(); folder.MetaEDiscoveryRecipientListRemove(removeRequest.RecipientEmail); await connection.Folder.PutAsync(folder); await InitializePrivilegedConnectionAsync(); // Using the special connection here to delete the user. await privilegedConnection.User.DeleteAsync(ModuleUtility.GetFolderScopedUserIdentifier(folder.Identifier, removeRequest.RecipientEmail)); await this.auditLogStore.AddEntry( new AuditLogEntry() { EntryType = AuditLogEntryType.eDiscoveryRecipientDeleted, Message = $"An eDiscovery User has been removed {removeRequest.RecipientEmail}", ModuleType = Modules.ModuleType.eDiscovery }, folder.Identifier ); return(new RecipientResponse() { Email = removeRequest.RecipientEmail, }); }
public async Task <RecipientResponse> RegenerateRecipientPasswordAsync(RegenerateRecipientPasswordRequest regenRequest) { var folder = await connection.Folder.GetAsync(regenRequest.FolderIdentifier); var recipients = folder.MetaEDiscoveryRecipientListRead(); var password = ModuleUtility.GeneratePassword(folder, MetadataKeyConstants.E_DISCOVERY_RND_PASSWORD_LENGTH, EDiscoveryUtility.E_DISCOVERY_DEFAULT_PASSWORD_LENGTH, MetadataKeyConstants.E_DISCOVERY_RND_PASSWORD_CHARS); var recipient = recipients.Where(rec => rec.Email.ToLower() == regenRequest.RecipientEmail.ToLower()).FirstOrDefault(); if (recipient != null) { // Using the special connection here to update their password. var userIdentifier = ModuleUtility.GetFolderScopedUserIdentifier(folder.Identifier, regenRequest.RecipientEmail); await InitializePrivilegedConnectionAsync(); await privilegedConnection.User.PasswordPutAsync(userIdentifier, password.Plain); await this.auditLogStore.AddEntry( new AuditLogEntry() { EntryType = AuditLogEntryType.eDiscoveryRecipientRegenerated, Message = $"An eDiscovery has had their password regenerated {recipient.Email}", ModuleType = Modules.ModuleType.eDiscovery }, folder.Identifier ); recipient.PasswordHash = password.Hashed; recipient.ExpirationDate = ModuleUtility.GetLinkExpirationDate(folder, MetadataKeyConstants.E_DISCOVERY_EXPIRATION_LENGTH_SECONDS).Value; recipient.MagicLink = ModuleUtility.CreateMagicLink(regenRequest, managerConfiguration.EDiscoveryLandingLocation, managerConfiguration.EDiscoveryLinkEncryptionKey, regenRequest.FolderIdentifier, recipient.ExpirationDate, userIdentifier); await connection.ConcurrencyRetryBlock(async() => { folder = await connection.Folder.GetAsync(regenRequest.FolderIdentifier); folder.MetaEDiscoveryRecipientListUpsert(recipient); await connection.Folder.PutAsync(folder); }); // now we also want to send back the magic link that we generated before. return(new RecipientResponse() { Email = regenRequest.RecipientEmail, FirstName = recipient.FirstName, LastName = recipient.LastName, Password = password.Plain, MagicLink = recipient.MagicLink, ExpirationDate = recipient.ExpirationDate, }); } return(new RecipientResponse()); }
private async Task <ModelBase> RemoveOfficerAsync(RemoveOfficerRequest removeRequest) { FolderModel folder = null; await connection.ConcurrencyRetryBlock(async() => { folder = await connection.Folder.GetAsync(removeRequest.FolderIdentifier); var recipients = folder.MetaLEOUploadOfficerListRead(); var recipient = recipients.FirstOrDefault(f => f.Email == removeRequest.RecipientEmail); folder.MetaLEOUploadOfficerListRemove(removeRequest.RecipientEmail); var paths = folder.Read <List <string> >("_paths"); if (paths != null && recipient != null) { var officerPath = GetOfficerPath(folder.Identifier, recipient.FirstName, recipient.LastName); if (paths.Contains(officerPath.PathKey)) { paths = paths.Where(p => !p.StartsWith(officerPath.PathKey)).ToList(); } folder.Write("_paths", paths); } await connection.Folder.PutAsync(folder); }); await InitializePrivilegedConnectionAsync(); // Using the special connection here to delete the user. await privilegedConnection.User.DeleteAsync(ModuleUtility.GetFolderScopedUserIdentifier(folder.Identifier, removeRequest.RecipientEmail, "leo")); await this.auditLogStore.AddEntry( new AuditLogEntry() { EntryType = AuditLogEntryType.LEOUploadOfficerDeleted, Message = $"An officer has been removed {removeRequest.RecipientEmail}", ModuleType = Modules.ModuleType.LEOUpload }, folder.Identifier ); return(new RecipientResponse() { Email = removeRequest.RecipientEmail, }); }
public async Task <UserAuthenticatedResponse> AuthenticateUserAsync(AuthenticateUserRequest authenticateUserRequest, string linkEncryptionKey) { if (String.IsNullOrEmpty(authenticateUserRequest.Token)) { return(new UserAuthenticatedResponse() { IsAuthenticated = false }); } // Get the magic link object back out from the token. var magicLink = ModuleUtility.DecryptMagicLink(authenticateUserRequest.Token, linkEncryptionKey); // Now we have a magic link object, we need to compare the email on the token, with the one that was passed in. if (magicLink.RecipientEmail.ToLower() != authenticateUserRequest.Email.ToLower() || magicLink.ExipirationDate < DateTime.UtcNow // next let's check that this link hasn't expired. ) // Next we check to make sure the folder keys are the same. { return(new UserAuthenticatedResponse() { IsAuthenticated = false }); } // Before we can operate, and get any folder details, we're also going to need to authenticate the user in the backend. This will properly set things on the connection // such that it can make a backed call. try { await connection.User.AuthenticateAsync(new TokenRequestModel { Identifier = ModuleUtility.GetFolderScopedUserIdentifier(magicLink.FolderIdentifier, authenticateUserRequest.Email, "leo"), Password = authenticateUserRequest.Password }); connection.AddCookieTokenToResponse(); // Now we can do the password check. We're going to check that the password in our database matches on hash // the password that came in on the request. var folder = await connection.Folder.GetAsync(magicLink.FolderIdentifier); // get the recipients, so we can find this particular recipient. var officers = folder.MetaLEOUploadOfficerListRead(); var recipient = officers.Where(rec => rec.Email.ToLower() == magicLink.RecipientEmail.ToLower()).FirstOrDefault(); // We check to make sure that there's a recipient on this folder that matches by email, and that the plain text // password that was passed in matches the password in our database. if (recipient != null && BCrypt.Verify(authenticateUserRequest.Password, recipient.PasswordHash)) { await this.auditLogStore.AddEntry( new AuditLogEntry() { EntryType = AuditLogEntryType.LEOUploadUserLogin, Message = "An officer Has Logged in.", ModuleType = Modules.ModuleType.LEOUpload }, folder.Identifier, connection ); return(new UserAuthenticatedResponse() { IsAuthenticated = true, FolderIdentifier = folder.Identifier, PathIdentifier = GetOfficerPath(folder.Identifier, recipient.FirstName, recipient.LastName) }); } else { return(new UserAuthenticatedResponse() { IsAuthenticated = false }); } } catch (Exception) { return(new UserAuthenticatedResponse() { IsAuthenticated = false }); } }