### Install and Start Bitwarden Server on Linux/macOS Source: https://github.com/bitwarden/server/blob/main/README.md Use these commands to download the Bitwarden installation script, make it executable, and then install and start the server on Linux or macOS systems. ```bash curl -s -L -o bitwarden.sh \ "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux" \ && chmod +x bitwarden.sh ./bitwarden.sh install ./bitwarden.sh start ``` -------------------------------- ### Install and Start Bitwarden Server on Windows Source: https://github.com/bitwarden/server/blob/main/README.md Use these PowerShell commands to download the Bitwarden installation script and then install and start the server on Windows systems. ```powershell Invoke-RestMethod -OutFile bitwarden.ps1 \ -Uri "https://func.bitwarden.com/api/dl/?app=self-host&platform=windows" .itwarden.ps1 -install .itwarden.ps1 -start ``` -------------------------------- ### Install Dependencies Source: https://github.com/bitwarden/server/blob/main/src/Core/MailTemplates/Mjml/README.md Installs all necessary project dependencies using npm ci. ```shell npm ci ``` -------------------------------- ### Start SeederApi Source: https://github.com/bitwarden/server/blob/main/util/SeederApi/README.md Navigate to the SeederApi directory and run the dotnet command to start the API. The API typically runs on http://localhost:5000. ```bash cd util/SeederApi dotnet run ``` -------------------------------- ### Run Bitwarden AppHost Source: https://github.com/bitwarden/server/blob/main/AppHost/README.md Navigate to the AppHost directory and run the dotnet command to start the Aspire dashboard and all Bitwarden services. ```bash cd AppHost dotnet run ``` -------------------------------- ### Example Policy Enforcement Flow Source: https://github.com/bitwarden/server/blob/main/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/README.md Demonstrates how a consumer calls the policy requirement query and then enforces the returned requirement. This includes the internal steps taken by the query and the consumer's logic for handling the requirement. ```csharp // Consumer calls: var requirement = await _policyRequirementQuery.GetAsync(userId); // Internally: // 1. PolicyRequirementQuery finds DisableSendPolicyRequirementFactory // 2. Queries: policyRepository.GetPolicyDetailsByUserIdsAndPolicyType([userId], PolicyType.DisableSend) // 3. For each PolicyDetails row: factory.Enforce(row) // → filters out Owners, Admins, Invited/Revoked members, and provider users // 4. factory.Create(filteredRows) // → DisableSendPolicyRequirement { DisableSend = filteredRows.Any() } // 5. Returns: DisableSendPolicyRequirement { DisableSend = true } // Consumer enforces: if (requirement.DisableSend) { throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send."); } ``` -------------------------------- ### Create Free or Premium Individual Account Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/presets.md These presets create individual accounts with no vault data, suitable for testing account setup flows. Login emails are predefined for each type. ```bash dotnet run -- preset --name free --mangle ``` ```bash dotnet run -- preset --name premium --mangle ``` -------------------------------- ### Full Enterprise Org with Named Folders + Favorites Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/permission-testing.md This command generates a full enterprise organization setup that includes named folders and favorites, useful for testing comprehensive organizational structures. ```bash dotnet run -- preset --name qa.zero-knowledge-labs-enterprise --mangle ``` -------------------------------- ### Enabling UseMyFeature for Enterprise Organizations (MSSQL Migration) Source: https://github.com/bitwarden/server/blob/main/src/Core/AdminConsole/OrganizationFeatures/OrganizationAbility/README.md Example MSSQL migration script to enable a new feature ('UseMyFeature') for all organizations on Enterprise plan types. Verify 'PlanType' values against 'src/Core/Billing/Enums/PlanType.cs'. ```sql -- Example: Enable UseMyFeature for all Enterprise organizations -- Check src/Core/Billing/Enums/PlanType.cs for current values UPDATE [dbo].[Organization] SET UseMyFeature = 1 WHERE PlanType IN (4, 5, 10, 11, 14, 15, 19, 20) -- All Enterprise plan types (2019, 2020, 2023, current) ``` -------------------------------- ### Register Mailer Services with Extension Method Source: https://github.com/bitwarden/server/blob/main/src/Core/Platform/Mail/README.md Register the Mailer services in your DI container using the provided extension method for simplified setup. ```csharp using Bit.Core.Platform.Mailer; services.AddMailer(); ``` -------------------------------- ### Configure Git Hooks for Auto-Formatting Source: https://github.com/bitwarden/server/blob/main/README.md Install the pre-commit git hook to automatically format code before commits. This ensures consistent code style across the project. ```bash git config --local core.hooksPath .git-hooks ``` -------------------------------- ### Using IMemoryCache for Caching Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md An example of using the built-in IMemoryCache service to cache data. This approach leverages .NET's integrated caching mechanism, offering features like absolute expiration and priority settings. ```csharp public class MyService { private readonly IMemoryCache _memoryCache; public MyService(IMemoryCache memoryCache) { _memoryCache = memoryCache; } public async Task GetDataAsync(string key) { return await _memoryCache.GetOrCreateAsync(key, async entry => { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30); entry.SetPriority(CacheItemPriority.High); return await _repository.GetDataAsync(key); }); } } ``` -------------------------------- ### Run Basic QA Enterprise Preset Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/fresh-database.md Use this command to quickly set up a standard enterprise organization with known users, groups, collections, and encrypted vault items for QA purposes. The owner's email will be printed in the CLI output. ```bash dotnet run -- preset --name qa.enterprise-basic --mangle ``` -------------------------------- ### Azure Notification Hub Pool Configuration Source: https://github.com/bitwarden/server/blob/main/src/Core/Platform/PushRegistration/README.md Example JSON configuration for sharding devices across multiple Azure Notification Hubs. It includes settings for registration start and end dates to manage device distribution over time. ```json { "GlobalSettings": { "NotificationHubPool": { "NotificationHubs": [ { "HubName": "first", "ConnectionString": "anh-connection-string-1", "EnableSendTracing": true, "RegistrationStartDate": "1900-01-01T00:00:00.0000000Z", "RegistrationEndDate": "2025-01-01T00:00:00.0000000Z" }, { "HubName": "second", "ConnectionString": "anh-connection-string-2", "EnableSendTracing": false, "RegistrationStartDate": "2025-01-01T00:00:00.0000000Z", "RegistrationEndDate": null } ] } } } ``` -------------------------------- ### Build Seeder Project Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/README.md After running a preset, build the Seeder project to verify the generated test data. ```bash dotnet build util/Seeder/Seeder.csproj ``` -------------------------------- ### Send Push Notification Source: https://github.com/bitwarden/server/blob/main/src/Core/Platform/Push/README.md Example of sending a push notification to a user's devices. Ensure `IPushNotificationService` is injected and `PushNotification` is correctly populated. ```csharp await pushNotificationService.PushAsync(new PushNotification { Type = PushType.MyNotificationType, Target = NotificationTarget.User, TargetId = userId, Payload = new MyPayload { Message = "Request accepted", }, ExcludeCurrentContext = false, }); ``` -------------------------------- ### Seed Data with SeederApi Source: https://github.com/bitwarden/server/blob/main/util/SeederApi/README.md Send a POST request to the /seed endpoint with a scene template name and arguments. Include the X-Play-Id header for tracking seeded data. Ensure the password is at least 8 characters and the email uses a top-level domain of example.com. ```bash curl -X POST http://localhost:5000/seed \ -H "Content-Type: application/json" \ -H "X-Play-Id: test-run-123" \ -d '{ "template": "SingleUserScene", "arguments": { "email": "test@example.com", "password": "REPLACE_ME" } }' ``` -------------------------------- ### Use IDistributedCache with JSON Helpers Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md Utilize helper methods for getting and setting JSON data with IDistributedCache. Includes setting data with a specified expiration time. ```csharp using Bit.Core.Utilities; public async Task GetDataAsync(string key) { return await _cache.TryGetValue(key); } public async Task SetDataAsync(string key, MyData data) { await _cache.SetAsync(key, data, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30) }); } ``` -------------------------------- ### Enable Self-Hosted Mode Source: https://github.com/bitwarden/server/blob/main/AppHost/README.md Set 'SelfHost' to 'true' and provide a password for the self-hosted database using dotnet user-secrets. ```bash dotnet user-secrets set "SelfHost" "true" dotnet user-secrets set "Database:SelfHostPassword" "" ``` -------------------------------- ### Using a Custom MJML Component Source: https://github.com/bitwarden/server/blob/main/src/Core/MailTemplates/Mjml/README.md Example of how to use a custom MJML component, `mj-bw-hero`, within an MJML template. This component accepts attributes for image source and title. ```html ``` -------------------------------- ### Integration Test for Cache Expiration Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md An integration test demonstrating how to verify that expired items are removed from the cache. This example uses `IDistributedCache` and specifically targets `EntityFrameworkCache` for expiration scanning. ```csharp using System.Text; using Microsoft.Extensions.Caching.Distributed; using Xunit; using StackExchange.Redis; using Microsoft.EntityFrameworkCore; [DatabaseTheory, DatabaseData] public async Task Cache_ExpirationScanning_RemovesExpiredItems(IDistributedCache cache) { // Set item with 1-second expiration await cache.SetAsync("key", Encoding.UTF8.GetBytes("value"), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(1) }); // Wait for expiration await Task.Delay(TimeSpan.FromSeconds(2)); // Trigger expiration scan var entityCache = cache as EntityFrameworkCache; await entityCache.ScanForExpiredItemsAsync(); // Verify item is removed var result = await cache.GetAsync("key"); Assert.Null(result); } ``` -------------------------------- ### Build and Run Seeder Utility Source: https://github.com/bitwarden/server/blob/main/util/SeederUtility/README.md Build the Seeder Utility project and run commands with options. Default user password is 'asdfasdfasdf'. ```bash dotnet build dotnet run -- [options] ``` -------------------------------- ### List Available Presets Source: https://github.com/bitwarden/server/blob/main/util/SeederUtility/README.md Displays a list of all available named presets for fixture-based seeding. ```bash # List available presets dotnet run -- preset --list ``` -------------------------------- ### Configure ExtendedCache for Organization Abilities Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md Configure ExtendedCache with specific settings for duration, eager refresh, and fail-safe mode. This setup is ideal for data that is read frequently but updated infrequently. ```csharp services.AddExtendedCache("OrganizationAbilities", globalSettings, new GlobalSettings.ExtendedCacheSettings { Duration = TimeSpan.FromMinutes(10), EagerRefreshThreshold = 0.9, // Refresh at 90% of TTL IsFailSafeEnabled = true, FailSafeMaxDuration = TimeSpan.FromHours(1) // Serve stale data up to 1 hour on backend failures }); ``` -------------------------------- ### Generate SQL Migration Script Source: https://github.com/bitwarden/server/blob/main/util/SqlServerEFScaffold/README.MD Create a SQL script to initialize a database based on your Entity Framework models. This is useful for code-first development. ```bash dotnet ef migrations add Init ``` ```bash dotnet ef migrations script ``` -------------------------------- ### Create Listener Configuration Source: https://github.com/bitwarden/server/blob/main/src/Core/Dirt/EventIntegrations/README.md Instantiates the listener configuration object. This object should be populated with necessary global settings. ```csharp var exampleConfiguration = new ExampleListenerConfiguration(globalSettings); ``` -------------------------------- ### Unit Test for IDistributedCache Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md Shows a unit test for `IDistributedCache` using `MemoryDistributedCache`. This is useful for testing cache set and get operations without a real distributed cache provider. ```csharp using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; using Xunit; [Fact] public async Task TestDistributedCache() { var cache = new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions())); await cache.SetStringAsync("key", "value"); var result = await cache.GetStringAsync("key"); Assert.Equal("value", result); } ``` -------------------------------- ### Run QA Collection Permissions Preset Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/permission-testing.md Use this command to set up an enterprise organization with collections pre-configured for testing permission edge cases, including readOnly, hidePasswords, and manage combinations. ```bash dotnet run -- preset --name qa.collection-permissions-enterprise --mangle ``` -------------------------------- ### Run Scale Test: 1,000 Users Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/scale-testing.md This preset simulates a larger environment with 1,000 users, 100 groups, 2,000 collections, and 10,000 ciphers. Ensure you use the correct preset name for this configuration. ```bash dotnet run -- preset --name scale.lg-balanced-wayne-enterprises --mangle ``` -------------------------------- ### Create Policy Handler Class Source: https://github.com/bitwarden/server/blob/main/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyUpdateEvents/README.md Implement event interfaces like IPolicyValidationEvent, IEnforceDependentPoliciesEvent, and IOnPolicyPreUpdateEvent. Set the PolicyType and define required policies. This example shows validation and pre-update side effects for AutomaticUserConfirmationPolicy. ```csharp public class AutomaticUserConfirmationPolicyEventHandler( IAutomaticUserConfirmationOrganizationPolicyComplianceHandler handler, IOrganizationUserRepository organizationUserRepository, IDeleteEmergencyAccessCommand deleteEmergencyAccessCommand) : IPolicyValidationEvent, IEnforceDependentPoliciesEvent, IOnPolicyPreUpdateEvent { public PolicyType Type => PolicyType.AutomaticUserConfirmation; // IEnforceDependentPoliciesEvent: SingleOrg must be enabled before this policy can be enabled public IEnumerable RequiredPolicies => [PolicyType.SingleOrg]; // IPolicyValidationEvent: Validates org compliance public async Task ValidateAsync(SavePolicyModel savePolicyModel, Policy? currentPolicy) { var policyUpdate = savePolicyModel.PolicyUpdate; var isNotEnablingPolicy = policyUpdate is not { Enabled: true }; var policyAlreadyEnabled = currentPolicy is { Enabled: true }; if (isNotEnablingPolicy || policyAlreadyEnabled) { return string.Empty; } return (await handler.IsOrganizationCompliantAsync( new AutomaticUserConfirmationOrganizationPolicyComplianceHandlerRequest(policyUpdate.OrganizationId))) .Match( error => error.Message, _ => string.Empty); } // IOnPolicyPreUpdateEvent: Removes emergency access grants for org users before enabling public async Task ExecutePreUpsertSideEffectAsync(SavePolicyModel policyRequest, Policy? currentPolicy) { var isNotEnablingPolicy = policyRequest.PolicyUpdate is not { Enabled: true }; var policyAlreadyEnabled = currentPolicy is { Enabled: true }; if (isNotEnablingPolicy || policyAlreadyEnabled) { return; } var orgUsers = await organizationUserRepository.GetManyByOrganizationAsync(policyRequest.PolicyUpdate.OrganizationId, null); var orgUserIds = orgUsers.Where(w => w.UserId != null).Select(s => s.UserId!.Value).ToList(); await deleteEmergencyAccessCommand.DeleteAllByUserIdsAsync(orgUserIds); } // IOnPolicyPostUpdateEvent: No implementation is needed since this handler doesn’t require it. } ``` -------------------------------- ### Enable Ngrok Community Plugin Source: https://github.com/bitwarden/server/blob/main/AppHost/README.md Create an AppHost.csproj.user file to enable the ngrok community plugin for webhook tunneling. This file is typically ignored by git. ```xml true ``` -------------------------------- ### Run Families Plan Preset Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/fresh-database.md Use this command to seed a database with data representative of a Families plan subscription. ```bash dotnet run -- preset --name qa.families-basic --mangle ``` -------------------------------- ### Caching Decision Tree Logic Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md This logic guides the selection of a caching option based on data sharing needs, persistence requirements, write rates, and whether the working set fits in memory. It covers scenarios for distributed caches, in-memory caches, and combined strategies. ```text Does your data need to be shared across all instances in a horizontally-scaled deployment? ├─ YES │ │ │ Do you need long-term persistence with TTL (days/weeks)? │ ├─ YES │ │ │ │ │ Is it OK for a write on one instance to take a while to reach the │ │ in-memory caches on other instances (no cross-instance invalidation)? │ │ ├─ NO → Use `IDistributedCache` with persistent keyed service (every read hits the store) │ │ └─ YES │ │ │ │ │ Does the working set fit comfortably in process memory? │ │ ├─ NO → Use `IDistributedCache` with persistent keyed service │ │ │ (L1 becomes overhead at high cardinality — see Sizing) │ │ └─ YES → Use `ExtendedCache` paired with the persistent cache │ │ (in-memory cache + Cosmos/SQL/EF distributed cache — │ │ see "Pairing ExtendedCache with Cosmos DB" below) │ │ │ └─ NO │ │ │ Is the write rate sustained-high (cross-instance backplane traffic │ would dominate)? │ ├─ YES → Use `IDistributedCache` (default) — backplane is a liability here │ └─ NO → Use `ExtendedCache` │ │ │ Notes: │ - With Redis configured: memory + distributed + backplane │ - With a non-Redis IDistributedCache registered: memory + distributed, no backplane │ - With nothing registered: memory-only with stampede protection │ - Provides fail-safe, eager refresh, circuit breaker │ - For org/provider abilities: Use GetOrSetAsync with preloading pattern │ └─ NO (single instance or manual sync acceptable) │ Use `ExtendedCache` with memory-only mode (EnableDistributedCache = false) │ Notes: - Same performance as raw IMemoryCache - Built-in stampede protection, eager refresh, fail-safe - "Free" Redis/backplane if needed at a later date (but not required) - Only use specialized in-memory cache if ExtendedCache API doesn't fit - Working set must still fit in process memory — see Sizing *Stampede protection = prevents cache stampedes (multiple simultaneous requests for the same expired/missing key triggering redundant backend calls) ``` -------------------------------- ### Registering and Using ExtendedCache with Persistent Cache Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md This snippet demonstrates how to register an ExtendedCache aliased to a persistent distributed cache (Cosmos) and use it within a service to cache organization analytics snapshots. It includes registration for the cache and the service, as well as methods for getting or setting snapshots and invalidating them. ```csharp services.AddDistributedCache(globalSettings); services.AddKeyedSingleton< IDistributedCache>( "OrganizationAnalytics", (sp, _) => sp.GetRequiredKeyedService("persistent")); services.AddExtendedCache("OrganizationAnalytics", globalSettings, new GlobalSettings.ExtendedCacheSettings { UseSharedDistributedCache = false, Duration = TimeSpan.FromHours(6), EagerRefreshThreshold = 0.9f, // refresh in background at 90% of TTL IsFailSafeEnabled = true, FailSafeMaxDuration = TimeSpan.FromHours(24), // serve stale up to 24h on factory failures }); public class OrganizationAnalyticsService { private readonly IFusionCache _cache; private readonly IOrganizationAnalyticsRepository _repository; public OrganizationAnalyticsService( [FromKeyedServices("OrganizationAnalytics")] IFusionCache cache, IOrganizationAnalyticsRepository repository) { _cache = cache; _repository = repository; } public async Task GetSnapshotAsync(Guid organizationId) { return await _cache.GetOrSetAsync( $"org:{organizationId}:analytics-snapshot", async _ => await _repository.ComputeSnapshotAsync(organizationId) ); } public async Task InvalidateAsync(Guid organizationId) { // No backplane on Cosmos — this clears the current instance's L1 and removes the // entry from L2. Other instances continue serving their L1 entries until TTL. await _cache.RemoveAsync($"org:{organizationId}:analytics-snapshot"); } } ``` -------------------------------- ### Run Seeder Command Template Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/README.md Use this template to run a seeder command. Replace `` with the specific seeder command you intend to execute. ```bash dotnet run -- ``` -------------------------------- ### Seed with QA Enterprise Preset Source: https://github.com/bitwarden/server/blob/main/util/SeederUtility/README.md Applies the 'qa.enterprise-basic' preset for seeding, ensuring known users and relationships. Mangling is enabled. ```bash # QA preset with known users and relationships dotnet run -- preset --name qa.enterprise-basic --mangle ``` -------------------------------- ### Create Individual User with Premium Subscription Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/fresh-database.md Use this command to create a single user with a premium subscription and an empty vault, without associating them with an organization. ```bash dotnet run -- individual --subscription premium --first-name Jane --last-name Smith --vault ``` -------------------------------- ### Migrate from In-Memory to ExtendedCache Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md Illustrates the changes required to switch from a local in-memory cache to ExtendedCache, including service registration and data access patterns. ```csharp // Field private readonly ConcurrentDictionary _cache = new(); private readonly IRepository _repository; // Constructor public MyService(IRepository repository) { _repository = repository; } // Usage public async Task GetDataAsync(string key) { if (_cache.TryGetValue(key, out var cached)) { return cached; } var data = await _repository.GetAsync(key); _cache.TryAdd(key, data); return data; } ``` ```csharp // Registration services.AddExtendedCache("MyFeature", globalSettings); // Constructor public MyService( [FromKeyedServices("MyFeature")] IFusionCache cache, IRepository repository) { _cache = cache; _repository = repository; } // Usage public async Task GetDataAsync(string key) { return await _cache.GetOrSetAsync( key, async _ => await _repository.GetAsync(key) ); } ``` -------------------------------- ### Pipeline Path: Fixture to Entity Source: https://github.com/bitwarden/server/blob/main/util/Seeder/CLAUDE.md Illustrates the data flow from a fixture to a server entity, involving multiple transformation and encryption steps. ```text SeedVaultItem → CipherSeed.FromSeedItem() → CipherSeed → {Type}CipherSeeder.Create(options) → CipherViewDto → encrypt_fields (Rust FFI) → EncryptedCipherDto → EncryptedCipherDtoExtensions → Server Cipher Entity ``` -------------------------------- ### Add and Commit Changes Source: https://github.com/bitwarden/server/blob/main/src/Core/MailTemplates/README.md Stage your asset changes and commit them with a descriptive message. ```bash git add path/to/your-asset.png git commit -m "commit message" ``` -------------------------------- ### Production-Realistic Auth for E2E Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/bug-reproduction.md Include the `--kdf-iterations` flag with a high value, such as 600000, to simulate production-realistic key derivation function iterations for end-to-end testing of authentication flows. ```bash dotnet run -- organization -n BugRepro -d repro.example -u 200 -c 500 --collections 800 -g 8 --kdf-iterations 600000 ``` -------------------------------- ### Policy Requirement Query Architecture Source: https://github.com/bitwarden/server/blob/main/src/Core/AdminConsole/OrganizationFeatures/Policies/PolicyRequirements/README.md Illustrates the internal flow of the PolicyRequirementQuery, showing how it finds factories, fetches policy details, filters them, and creates the final requirement object. ```csharp IPolicyRepository (database) │ ▼ PolicyRequirementQuery (implements IPolicyRequirementQuery) │ │ For each query: │ 1. Finds the registered factory for type T │ 2. Fetches PolicyDetails rows for the user and policy type │ 3. Calls factory.Enforce() on each row to filter inapplicable policies │ 4. Calls factory.Create() on the remaining rows to produce T │ └──▶ IPolicyRequirementFactory ├─ Enforce(PolicyDetails) → bool └─ Create(IEnumerable) → T : IPolicyRequirement ``` -------------------------------- ### Run Free Personal Vault Preset Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/fresh-database.md This command seeds a database with data for a single user on a free personal plan. ```bash dotnet run -- preset --name qa.stark-free-basic --mangle ``` -------------------------------- ### Scale with High Permission Density Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/permission-testing.md This command is designed for performance testing, creating a large-scale organization with 2,500 users and a high density of permissions to stress-test the system. ```bash dotnet run -- preset --name scale.lg-highperm-tyrell-corp --mangle ``` -------------------------------- ### OrganizationAbilityService with ExtendedCache Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md Implement a service that uses ExtendedCache for retrieving and managing organization abilities. It demonstrates caching, retrieval, and invalidation strategies. ```csharp public class OrganizationAbilityService { private readonly IFusionCache _cache; private readonly IOrganizationRepository _organizationRepository; public OrganizationAbilityService( [FromKeyedServices("OrganizationAbilities")] IFusionCache cache, IOrganizationRepository organizationRepository) { _cache = cache; _organizationRepository = organizationRepository; } public async Task> GetOrganizationAbilitiesAsync() { return await _cache.GetOrSetAsync>( "all-org-abilities", async _ => { var abilities = await _organizationRepository.GetManyAbilitiesAsync(); return abilities.ToDictionary(a => a.Id); } ); } public async Task GetOrganizationAbilityAsync(Guid orgId) { var abilities = await GetOrganizationAbilitiesAsync(); abilities.TryGetValue(orgId, out var ability); return ability; } public async Task UpsertOrganizationAbilityAsync(Organization organization) { // Update database await _organizationRepository.ReplaceAsync(organization); // Invalidate cache - with Redis backplane, this broadcasts to all instances await _cache.RemoveAsync("all-org-abilities"); } } ``` -------------------------------- ### Inject Custom OTP Token Provider Source: https://github.com/bitwarden/server/blob/main/src/Core/Auth/Identity/TokenProviders/OtpTokenProvider/readme.md Demonstrates how to inject a custom OTP token provider with specific options into a class constructor. ```csharp public class UserEmailTokenProvider( IOtpTokenProvider otpTokenProvider) { private readonly IOtpTokenProvider _otpTokenProvider = otpTokenProvider; // ... } ``` -------------------------------- ### Build MJML to HTML Source: https://github.com/bitwarden/server/blob/main/src/Core/MailTemplates/Mjml/README.md Compiles MJML files into HTML output in the ./out directory. ```shell npm run build ``` -------------------------------- ### Run Larger Enterprise Preset Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/scenarios/fresh-database.md This command seeds a larger organization with 58 users and 14 groups, suitable for more comprehensive testing scenarios. ```bash dotnet run -- preset --name qa.dunder-mifflin-enterprise-full --mangle ``` -------------------------------- ### Build Minified Handlebars HTML Source: https://github.com/bitwarden/server/blob/main/src/Core/MailTemplates/Mjml/README.md Compiles *.mjml files into minified *.html.hbs format. ```shell npm run build:minify ``` -------------------------------- ### Mocking OtpTokenProvider for Unit Tests Source: https://github.com/bitwarden/server/blob/main/src/Core/Auth/Identity/TokenProviders/OtpTokenProvider/readme.md Mock the IOtpTokenProvider interface using Substitute for unit testing. This allows you to control the behavior of token generation and validation during tests. ```csharp // Mock the interface for unit tests var mockOtpProvider = Substitute.For>(); mockOtpProvider.GenerateTokenAsync("EmailToken", "email_verification", "user_123").Returns("123456"); mockOtpProvider.ValidateTokenAsync("123456", "EmailToken", "email_verification", "user_123").Returns(true); ``` -------------------------------- ### Override Web Frontend Path Source: https://github.com/bitwarden/server/blob/main/AppHost/README.md Use this command to set a custom path for the Bitwarden clients repository if it's not located at the default '../../clients/apps'. ```bash dotnet user-secrets set "ClientsPath" "" ``` -------------------------------- ### Build and Test Commands for Seeder Source: https://github.com/bitwarden/server/blob/main/util/Seeder/CLAUDE.md Commands to build the Seeder project and run integration tests. Use the filter option to run a specific test. ```bash dotnet build util/Seeder/Seeder.csproj ``` ```bash dotnet test test/SeederApi.IntegrationTest/ ``` ```bash dotnet test test/SeederApi.IntegrationTest/ --filter "FullyQualifiedName~TestMethodName" ``` -------------------------------- ### Scaffold EF Models from SQL Server Database Source: https://github.com/bitwarden/server/blob/main/util/SqlServerEFScaffold/README.MD Use this command to generate Entity Framework models from an existing SQL Server database. Ensure the connection string is correct. ```bash dotnet ef dbcontext scaffold "" Microsoft.EntityFrameworkCore.SqlServer -o Model ``` -------------------------------- ### Migrate from IDistributedCache to ExtendedCache Source: https://github.com/bitwarden/server/blob/main/src/Core/Utilities/CACHING.md Shows how to update service registration, constructor injection, and data retrieval logic when moving from IDistributedCache to ExtendedCache. ```csharp // Registration services.AddDistributedCache(globalSettings); // Constructor public MyService(IDistributedCache cache, IRepository repository) { _cache = cache; _repository = repository; } // Usage public async Task GetDataAsync(string key) { var data = await _cache.TryGetValue(key); if (data == null) { data = await _repository.GetAsync(key); await _cache.SetAsync(key, data, new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30) }); } return data; } ``` ```csharp // Registration services.AddDistributedCache(globalSettings); services.AddExtendedCache("MyFeature", globalSettings); // Constructor public MyService( [FromKeyedServices("MyFeature")] IFusionCache cache, IRepository repository) { _cache = cache; _repository = repository; } // Usage public async Task GetDataAsync(string key) { return await _cache.GetOrSetAsync( key, async _ => await _repository.GetAsync(key), options => options.SetDuration(TimeSpan.FromMinutes(30)) ); } ``` -------------------------------- ### Generate QA Presets Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/docs/presets.md Use this command to generate specific QA presets. Replace {name} with the desired preset name from the table. ```bash dotnet run -- preset --name qa.{name} --mangle ``` -------------------------------- ### Run Bitwarden Seeder Preset Source: https://github.com/bitwarden/server/blob/main/util/Seeder/Seeds/README.md Use this command to run a specific preset from the catalog. Replace {name} with the desired preset name. The `--mangle` flag is used for data manipulation. ```bash dotnet run -- preset --name {name} --mangle ``` -------------------------------- ### Format Code with Prettier Source: https://github.com/bitwarden/server/blob/main/src/Core/MailTemplates/Mjml/README.md Applies Prettier formatting to the project files. ```shell npm run prettier ```