PhotoFlow Documentation Help

BuildingBlocks.Cloud - Technical Documentation

Write-Side Operations Documentation

Version 1.0 - April 2025

This documentation covers the command operations (write-side) of the BuildingBlocks.Cloud component, which provides a unified interface for cloud provider authentication, storage, and messaging services.

Table of Contents

  1. Architecture Overview

  2. Authentication Commands

  3. Storage Write Operations

  4. Messaging Send Operations

  5. Configuration Guide

  6. Usage Examples

  7. Error Handling

1. Architecture Overview

BuildingBlocks.Cloud is structured following Clean Architecture principles with CQRS separation for each cloud service domain. The write-side operations (commands) are handled by dedicated handlers that interact with cloud providers through provider-specific adapters.

Component Diagram

┌─────────────────────────────────────┐ │ Application Layer │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ Commands │ │ Handlers │ │ │ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────┘ │ ┌─────────────▼─────────────────────┐ │ Domain Layer │ │ ┌─────────────┐ ┌────────────┐ │ │ │ Services │ │ Entities │ │ │ └─────────────┘ └────────────┘ │ └─────────────────────────────────┘ │ ┌─────────────▼─────────────────────────┐ │ Infrastructure Layer │ │ ┌─────────────┐ ┌───────────────┐ │ │ │ Providers │ │ External APIs │ │ │ └─────────────┘ └───────────────┘ │ └───────────────────────────────────────┘

Write-Side Flow

  1. Commands are created by application code

  2. Command handlers validate and process commands

  3. Domain services implement business logic

  4. Provider adapters translate operations to provider-specific APIs

  5. Cloud provider APIs execute the actual operations

2. Authentication Commands

InitiateLoginCommand

Initiates OAuth2 login flow for a cloud provider.

public class InitiateLoginCommand : IRequest<string> { public CloudProviderType ProviderType { get; set; } public string RedirectUri { get; set; } public string[] Scopes { get; set; } public string State { get; set; } public Guid? OrganizationId { get; set; } }

HandleOAuthCallbackCommand

Processes OAuth2 callback to complete authentication.

public class HandleOAuthCallbackCommand : IRequest<AuthResult> { public CloudProviderType ProviderType { get; set; } public string Code { get; set; } public string RedirectUri { get; set; } public string State { get; set; } public Guid? OrganizationId { get; set; } }

RevokeTokenCommand

Revokes an OAuth token.

public class RevokeTokenCommand : IRequest<bool> { public CloudProviderType ProviderType { get; set; } public string Token { get; set; } public TokenType TokenType { get; set; } public string UserId { get; set; } public Guid? OrganizationId { get; set; } }

StoreTokenCommand

Securely stores OAuth tokens.

public class StoreTokenCommand : IRequest<bool> { public CloudProviderType ProviderType { get; set; } public TokenResponse Tokens { get; set; } public string UserId { get; set; } public Guid? OrganizationId { get; set; } }

3. Storage Write Operations

CreateFileCommand

Creates a new file in cloud storage.

public class CreateFileCommand : IRequest<StorageFile> { public CloudProviderType ProviderType { get; set; } public string Name { get; set; } public string MimeType { get; set; } public byte[] Content { get; set; } public string ParentFolderId { get; set; } public IDictionary<string, string> Metadata { get; set; } public Guid? OrganizationId { get; set; } }

CreateFolderCommand

Creates a new folder in cloud storage.

public class CreateFolderCommand : IRequest<StorageFolder> { public CloudProviderType ProviderType { get; set; } public string Name { get; set; } public string ParentFolderId { get; set; } public IDictionary<string, string> Metadata { get; set; } public Guid? OrganizationId { get; set; } }

UpdateFileCommand

Updates an existing file in cloud storage.

public class UpdateFileCommand : IRequest<StorageFile> { public CloudProviderType ProviderType { get; set; } public string FileId { get; set; } public string NewName { get; set; } public byte[] Content { get; set; } public bool UpdateContent { get; set; } public IDictionary<string, string> Metadata { get; set; } public Guid? OrganizationId { get; set; } }

DeleteFileCommand

Deletes a file from cloud storage.

public class DeleteFileCommand : IRequest<bool> { public CloudProviderType ProviderType { get; set; } public string FileId { get; set; } public bool Permanent { get; set; } public Guid? OrganizationId { get; set; } }

DeleteFolderCommand

Deletes a folder from cloud storage.

public class DeleteFolderCommand : IRequest<bool> { public CloudProviderType ProviderType { get; set; } public string FolderId { get; set; } public bool Recursive { get; set; } public bool Permanent { get; set; } public Guid? OrganizationId { get; set; } }

ShareItemCommand

Creates a shareable link for a file or folder.

public class ShareItemCommand : IRequest<StorageSharedLink> { public CloudProviderType ProviderType { get; set; } public string ItemId { get; set; } public SharePermission Permission { get; set; } public DateTime? ExpiresAt { get; set; } public string Password { get; set; } public bool AllowDownload { get; set; } public Guid? OrganizationId { get; set; } }

4. Messaging Send Operations

SendEmailCommand

Sends an email message.

public class SendEmailCommand : IRequest<MessageResponse> { public CloudProviderType ProviderType { get; set; } public string From { get; set; } public string FromName { get; set; } public List<string> To { get; set; } public List<string> Cc { get; set; } public List<string> Bcc { get; set; } public string Subject { get; set; } public string PlainTextBody { get; set; } public string HtmlBody { get; set; } public List<EmailAttachment> Attachments { get; set; } public IDictionary<string, string> Headers { get; set; } public MessagePriority Priority { get; set; } = MessagePriority.Normal; public Guid? OrganizationId { get; set; } }

SendTemplatedEmailCommand

Sends an email using a template.

public class SendTemplatedEmailCommand : IRequest<MessageResponse> { public CloudProviderType ProviderType { get; set; } public string From { get; set; } public string FromName { get; set; } public List<string> To { get; set; } public List<string> Cc { get; set; } public List<string> Bcc { get; set; } public string Subject { get; set; } public string TemplateId { get; set; } public object TemplateData { get; set; } public List<EmailAttachment> Attachments { get; set; } public MessagePriority Priority { get; set; } = MessagePriority.Normal; public Guid? OrganizationId { get; set; } }

SendSmsCommand

Sends an SMS message.

public class SendSmsCommand : IRequest<MessageResponse> { public CloudProviderType ProviderType { get; set; } public string From { get; set; } public string To { get; set; } public string Message { get; set; } public MessagePriority Priority { get; set; } = MessagePriority.Normal; public Guid? OrganizationId { get; set; } }

5. Configuration Guide

OAuth2 Configuration

{ "Cloud": { "Google": { "Auth": { "ClientId": "your-google-client-id", "ClientSecret": "your-google-client-secret", "AuthorizationEndpoint": "https://accounts.google.com/o/oauth2/auth", "TokenEndpoint": "https://oauth2.googleapis.com/token", "UserInfoEndpoint": "https://www.googleapis.com/oauth2/v2/userinfo", "DefaultScopes": [ "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" ] }, "Storage": { "DriveApiEndpoint": "https://www.googleapis.com/drive/v3", "DefaultFolderId": "root" } }, "Microsoft": { "Auth": { "ClientId": "your-microsoft-client-id", "ClientSecret": "your-microsoft-client-secret", "TenantId": "common", "AuthorizationEndpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize", "TokenEndpoint": "https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token", "UserInfoEndpoint": "https://graph.microsoft.com/v1.0/me", "DefaultScopes": [ "User.Read", "Files.ReadWrite" ] } } } }

Token Storage Configuration

{ "Cloud": { "TokenStorage": { "Type": "EncryptedFile", // Options: InMemory, EncryptedFile, Database "FilePath": "tokens", // For EncryptedFile "ConnectionString": "", // For Database "EncryptionKey": "" // Leave empty to use data protection API } } }

6. Usage Examples

Authentication Flow

// 1. Inject the service private readonly ICloudLoginService _cloudLoginService; private readonly ITokenManager _tokenManager; // 2. Initiate login (usually in controller action) public async Task<IActionResult> LoginWithGoogle() { var redirectUri = "https://yourapp.com/oauth/callback/google"; var scopes = new[] { "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/drive" }; var loginUrl = await _cloudLoginService.InitiateLoginAsync( CloudProviderType.Google, redirectUri, scopes); return Redirect(loginUrl); } // 3. Handle the callback public async Task<IActionResult> GoogleCallback(string code, string state) { var redirectUri = "https://yourapp.com/oauth/callback/google"; var result = await _cloudLoginService.HandleCallbackAsync( CloudProviderType.Google, code, redirectUri, state); if (result.Success) { // User authenticated successfully // Store user information in your system return RedirectToAction("Dashboard"); } return RedirectToAction("Error", new { message = "Authentication failed" }); }

Storage Operations

// File upload public async Task<IActionResult> UploadFile(IFormFile file, string folderId) { using var memoryStream = new MemoryStream(); await file.CopyToAsync(memoryStream); var command = new CreateFileCommand { ProviderType = CloudProviderType.Google, Name = file.FileName, MimeType = file.ContentType, Content = memoryStream.ToArray(), ParentFolderId = folderId, OrganizationId = _currentUser.OrganizationId }; var result = await _mediator.Send(command); return Ok(new { FileId = result.Id, Name = result.Name }); } // Create folder public async Task<IActionResult> CreateFolder(string name, string parentFolderId) { var command = new CreateFolderCommand { ProviderType = CloudProviderType.Google, Name = name, ParentFolderId = parentFolderId, OrganizationId = _currentUser.OrganizationId }; var result = await _mediator.Send(command); return Ok(new { FolderId = result.Id, Name = result.Name }); } // Create shareable link public async Task<IActionResult> ShareFile(string fileId) { var command = new ShareItemCommand { ProviderType = CloudProviderType.Google, ItemId = fileId, Permission = SharePermission.View, ExpiresAt = DateTime.UtcNow.AddDays(7), AllowDownload = true, OrganizationId = _currentUser.OrganizationId }; var result = await _mediator.Send(command); return Ok(new { Url = result.Url, ExpiresAt = result.ExpiresAt }); }

Messaging Operations

// Send email public async Task<IActionResult> SendWelcomeEmail(string to, string username) { var command = new SendTemplatedEmailCommand { ProviderType = CloudProviderType.Google, From = "noreply@yourdomain.com", FromName = "Your App", To = new List<string> { to }, Subject = "Welcome to Our Platform", TemplateId = "welcome-email", TemplateData = new { Username = username, Year = DateTime.Now.Year }, Priority = MessagePriority.High, OrganizationId = _currentUser.OrganizationId }; var result = await _mediator.Send(command); return Ok(new { Success = result.Success, MessageId = result.MessageId }); } // Send SMS public async Task<IActionResult> SendVerificationSms(string phoneNumber, string code) { var command = new SendSmsCommand { ProviderType = CloudProviderType.Twilio, From = "+15551234567", To = phoneNumber, Message = $"Your verification code is: {code}", Priority = MessagePriority.High, OrganizationId = _currentUser.OrganizationId }; var result = await _mediator.Send(command); return Ok(new { Success = result.Success, MessageId = result.MessageId }); }

7. Error Handling

The BuildingBlocks.Cloud package uses a consistent exception model for write operations:

Exception Type

Description

HTTP Status Code

CloudAuthenticationException

Authentication failures

401 Unauthorized

CloudProviderException

Provider-specific errors

502 Bad Gateway

CloudPermissionException

Permission/authorization issues

403 Forbidden

CloudValidationException

Invalid input or configuration

400 Bad Request

CloudStorageException

Storage operation failures

500 Internal Error

CloudMessagingException

Messaging operation failures

500 Internal Error

Example error handling:

try { var result = await _mediator.Send(command); return Ok(result); } catch (CloudAuthenticationException ex) { _logger.LogWarning(ex, "Authentication error"); return Unauthorized(new { error = ex.Message }); } catch (CloudPermissionException ex) { _logger.LogWarning(ex, "Permission error"); return Forbid(ex.Message); } catch (CloudValidationException ex) { _logger.LogWarning(ex, "Validation error"); return BadRequest(new { error = ex.Message, details = ex.Errors }); } catch (CloudException ex) { _logger.LogError(ex, "Cloud operation error"); return StatusCode(500, new { error = "An error occurred processing your request" }); }

This technical documentation covers the key write-side operations of the BuildingBlocks.Cloud component. For additional details, refer to the API reference documentation and example projects included with the package.

Similar code found with 4 license types

Last modified: 20 December 2025