Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dev/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ signingkey.jwk
# Reverse Proxy Conifg
reverse-proxy.conf
*.crt

seeds.local.json
Comment thread
theMickster marked this conversation as resolved.
77 changes: 77 additions & 0 deletions dev/seed.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env pwsh
# Runs SeederUtility for each entry defined in seeds.json (and optionally seeds.local.json).
# Usage: ./seed.ps1 [-DryRun]

param(
[switch]$DryRun
)

$ErrorActionPreference = "Stop"

$globalSeedsPath = Join-Path $PSScriptRoot "seeds.json"
$localSeedsPath = Join-Path $PSScriptRoot "seeds.local.json"
$seederProject = Join-Path $PSScriptRoot ".." "util" "SeederUtility"

$seeds = @(Get-Content $globalSeedsPath -Raw | ConvertFrom-Json)

if (Test-Path $localSeedsPath) {
$seeds += @(Get-Content $localSeedsPath -Raw | ConvertFrom-Json)
}

function ConvertTo-KebabCase {
param([string]$Name)
return ($Name -creplace '(?<=[a-z])([A-Z])', '-$1').ToLower()
}

function Build-CliArgs {
param($ArgsObject)
$parts = @()
foreach ($prop in $ArgsObject.PSObject.Properties) {
$flag = ConvertTo-KebabCase $prop.Name
$value = $prop.Value
if ($null -eq $value) {
continue
} elseif ($value -is [bool]) {
if ($value) {
$parts += "--$flag"
}
} else {
$parts += "--$flag"
$parts += "$value"
}
}
return ,$parts
}

$total = $seeds.Count

if ($total -eq 0) {
Write-Host "No seeds configured." -ForegroundColor Yellow
exit 0
}

for ($i = 0; $i -lt $total; $i++) {
$seed = $seeds[$i]
$label = if ($seed.label) { $seed.label } else { "$($seed.command) #$($i + 1)" }
$command = $seed.command
$cliArgs = Build-CliArgs $seed.args

Write-Host ""
Write-Host "[$($i + 1)/$total] $label" -ForegroundColor Cyan
Write-Host " dotnet run --project $seederProject -- $command $($cliArgs -join ' ')" -ForegroundColor DarkGray

if (-not $DryRun) {
dotnet run --project $seederProject -- $command @cliArgs
if ($LASTEXITCODE -ne 0) {
Comment thread
Hinton marked this conversation as resolved.
Write-Error "Seed '$label' failed with exit code $LASTEXITCODE."
exit $LASTEXITCODE
}
}
}

Write-Host ""
if ($DryRun) {
Write-Host "Dry run complete. $total seed(s) would be executed." -ForegroundColor Yellow
} else {
Write-Host "All $total seed(s) completed successfully." -ForegroundColor Green
}
29 changes: 29 additions & 0 deletions dev/seeds.json
Comment thread
Hinton marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
[
{
"label": "Jane Doe Free (individual, free)",
"command": "individual",
"args": {
"subscription": "free",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane@bitwarden.pw"
}
},
{
"label": "John Doe (individual, premium)",
"command": "individual",
"args": {
"subscription": "premium",
"firstName": "John",
"lastName": "Doe",
"email": "john@bitwarden.pw"
}
},
{
"label": "Enterprise Basic (qa.enterprise-basic preset)",
"command": "preset",
"args": {
"name": "qa.enterprise-basic"
}
}
]
5 changes: 5 additions & 0 deletions util/Seeder/Options/IndividualUserOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public record IndividualUserOptions
/// </summary>
public string? LastName { get; init; }

/// <summary>
/// Optional email.
/// </summary>
public string? Email { get; init; }

/// <summary>
/// Whether the user has a premium subscription (enables 1 GB storage).
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion util/Seeder/Pipeline/RecipeOrchestrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ internal PipelineExecutionResult Execute(IndividualUserOptions options)
{
var firstName = options.FirstName ?? new Bogus.Faker().Name.FirstName();
var lastName = options.LastName ?? new Bogus.Faker().Name.LastName();
var email = $"{firstName}.{lastName}@individual.example".ToLowerInvariant();
var email = options.Email ?? $"{firstName}.{lastName}@individual.example".ToLowerInvariant();

var premium = options.Premium;
var maxStorageGb = premium ? (short)1 : (short)0;
Expand Down
4 changes: 4 additions & 0 deletions util/SeederUtility/Commands/IndividualArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public class IndividualArgs : IArgumentModel
[Option("last-name", Description = "Last name for the user (generates predictable email)")]
public string? LastName { get; set; }

[Option("email", Description = "Email for the user")]
public string? Email { get; set; }

[Option("vault", Description = "Generate ~75 personal ciphers and folders")]
public bool Vault { get; set; } = false;

Expand Down Expand Up @@ -62,6 +65,7 @@ public void Validate()
{
FirstName = FirstName,
LastName = LastName,
Email = Email,
Premium = string.Equals(Subscription, "premium", StringComparison.OrdinalIgnoreCase),
GenerateVault = Vault,
Password = Password,
Expand Down
Loading