public async Task CreateOrUpdateUserAsync(User user) { if (user == null) { throw new InvalidOperationException("User is null"); } if (string.IsNullOrEmpty(user.PartitionKey)) { user.PartitionKey = GetUserPartitionKeyFromId(user.Id); } if (!user.IsValid()) { throw new InvalidOperationException("User is not valid. Check that all required properties are set"); } var container = Server.Instance.Database.GetContainer(Constants.UsersContainerName); var partitionKey = new PartitionKey(user.PartitionKey); var response = await container.UpsertItemAsync(user, partitionKey); var createdItem = response.StatusCode == HttpStatusCode.Created; Log.Debug("UserServer.CreateOrUpdateUserAsync: Created user? " + createdItem); Log.Debug($"UserServer.CreateOrUpdateUserAsync: Request charge: {response.RequestCharge}. Elapsed time: {response.Diagnostics.GetClientElapsedTime()} ms"); }
public async Task <int> GetUserGalleryCountAsync(User user) { if (user == null) { throw new InvalidOperationException("User is null"); } var query = new QueryDefinition("SELECT VALUE COUNT(1) FROM c WHERE c.CreatedByUserId = @userId").WithParameter("@userId", user.Id); return(await Server.Instance.Galleries.GetGalleriesScalarByQueryAsync(query)); }
/// <summary> /// Deletes a user from the database and any references to the user, which anonymises any content they've created. /// This balances the need for a user's right for their personal data to be deleted (GDPR compliance, etc.) with ensuring the integrity of content. /// </summary> public async Task DeleteUserAsync(User user) { if (user == null) { throw new ArgumentNullException(nameof(user)); } // get galleries where the user has been involved in some way (author/comments) var query = "SELECT * FROM c WHERE c.CreatedByUserId = @userId OR c.Comments.CreatedByUserId = @userId"; var queryDefinition = new QueryDefinition(query).WithParameter("@userId", user.Id); var galleries = await Server.Instance.Galleries.GetGalleriesByQueryAsync(queryDefinition); // go through the galleries and look for user references and remove them then update the gallery foreach (var gallery in galleries) { // remove any references to gallery creations if (gallery.CreatedByUserId == user.Id) { gallery.CreatedByUserId = Constants.AnonUserId; } // remove any references to gallery comments foreach (var galleryComment in gallery.Comments.Where(q => q.CreatedByUserId == user.Id)) { galleryComment.CreatedByUserId = Constants.AnonUserId; } await Server.Instance.Galleries.UpdateGalleryAsync(gallery); } // go through any comments the user has left against images and anonymise those var images = await Server.Instance.Images.GetImagesUserHasCommentedOnAsync(user.Id); foreach (var image in images) { foreach (var comment in image.Comments.Where(c => c.CreatedByUserId == user.Id)) { comment.CreatedByUserId = Constants.AnonUserId; } await Server.Instance.Images.UpdateImageAsync(image); } // delete the user var container = Server.Instance.Database.GetContainer(Constants.UsersContainerName); var result = await container.DeleteItemAsync <User>(user.Id, new PartitionKey(user.PartitionKey)); Log.Debug("UserServer:DeleteUserAsync: Status code: " + result.StatusCode); Log.Debug("UserServer:DeleteUserAsync: Request charge: " + result.RequestCharge); }
/// <summary> /// If the user's profile picture is not being internally hosted then this method will download it and store it internally /// </summary> /// <param name="user">The user who to download the picture for.</param> /// <param name="originalPictureUrl">The URL for the original version of the picture.</param> public async Task DownloadAndStoreUserPictureAsync(User user, string originalPictureUrl) { if (user.Picture.HasValue() && user.Picture.Equals(originalPictureUrl, StringComparison.CurrentCultureIgnoreCase)) { return; } // picture URL is different, download and store it var containerClient = Server.Instance.BlobServiceClient.GetBlobContainerClient(Constants.StorageUserPicturesContainerName); // delete any old version we have currently string fileId; if (user.PictureHostedUrl.HasValue()) { fileId = user.PictureHostedUrl.Substring(user.PictureHostedUrl.LastIndexOf('/') + 1); await containerClient.DeleteBlobIfExistsAsync(fileId); } // download it and store the original picture fileId = $"{user.Id}-{DateTime.Now.Ticks}.jpg"; using var client = new HttpClient(); try { await using var imageStream = await client.GetStreamAsync(originalPictureUrl); await containerClient.UploadBlobAsync(fileId, imageStream); user.PictureHostedUrl = containerClient.Uri + "/" + fileId; user.Picture = originalPictureUrl; } catch (Exception e) { Log.Debug($"UserServer.DownloadAndStoreUserPictureAsync() - Exception downloading/uploading: {e.Message}"); } }