Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to disable new user registration via install.sh #486

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
16 changes: 15 additions & 1 deletion docs/installation/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,21 @@ If you encounter any issues, feel free to open an issue on the [GitHub repositor

---

## 4. Troubleshooting
## 4. Configure Account Registration

By default, AliasVault is configured to allow public registration of new accounts. This means that anyone can create a new account on your server.

If you want to disable public registration, you can do so by running the install script with the `configure-registration` option and then choosing option 2.

```bash
./install.sh configure-registration
```

> Note: disabling public registration means the ability to create new accounts in the AliasVault client is disabled for everyone, including administrators. Accounts cannot be created outside of the client because of the end-to-end encryption employed by AliasVault. So make sure you have created your own account(s) before disabling public registration.

---

## 5. Troubleshooting

### Resetting the admin password
If you have lost your admin password, you can reset it by running the install script with the `reset-password` option. This will generate a new random password and update the .env file with it. After that it will restart the AliasVault containers to apply the changes.
Expand Down
136 changes: 115 additions & 21 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash
# @version 0.9.4
# @version 0.10.0

# Repository information used for downloading files and images from GitHub
REPO_OWNER="lanedirt"
Expand Down Expand Up @@ -38,17 +38,18 @@ show_usage() {
printf "Usage: $0 [COMMAND] [OPTIONS]\n"
printf "\n"
printf "Commands:\n"
printf " install Install AliasVault by pulling pre-built images from GitHub Container Registry (recommended)\n"
printf " uninstall Uninstall AliasVault\n"
printf " update Update AliasVault to the latest version\n"
printf " update-installer Check and update install.sh script if newer version available\n"
printf " configure-ssl Configure SSL certificates (Let's Encrypt or self-signed)\n"
printf " configure-email Configure email domains for receiving emails\n"
printf " start Start AliasVault containers\n"
printf " stop Stop AliasVault containers\n"
printf " restart Restart AliasVault containers\n"
printf " reset-password Reset admin password\n"
printf " build Build AliasVault from source (takes longer and requires sufficient specs)\n"
printf " install Install AliasVault by pulling pre-built images from GitHub Container Registry (recommended)\n"
printf " uninstall Uninstall AliasVault\n"
printf " update Update AliasVault to the latest version\n"
printf " update-installer Check and update install.sh script if newer version available\n"
printf " configure-ssl Configure SSL certificates (Let's Encrypt or self-signed)\n"
printf " configure-email Configure email domains for receiving emails\n"
printf " configure-registration Configure new account registration (enable or disable)\n"
printf " start Start AliasVault containers\n"
printf " stop Stop AliasVault containers\n"
printf " restart Restart AliasVault containers\n"
printf " reset-password Reset admin password\n"
printf " build Build AliasVault from source (takes longer and requires sufficient specs)\n"

printf "\n"
printf "Options:\n"
Expand Down Expand Up @@ -101,6 +102,10 @@ parse_args() {
COMMAND="configure-email"
shift
;;
configure-registration|registration)
COMMAND="configure-registration"
shift
;;
start|s)
COMMAND="start"
shift
Expand Down Expand Up @@ -186,6 +191,9 @@ main() {
"configure-email")
handle_email_configuration
;;
"configure-registration")
handle_registration_configuration
;;
"start")
handle_start
;;
Expand Down Expand Up @@ -363,6 +371,15 @@ set_support_email() {
fi
}

set_public_registration() {
printf "${CYAN}> Checking PUBLIC_REGISTRATION_ENABLED...${NC}\n"
if ! grep -q "^PUBLIC_REGISTRATION_ENABLED=" "$ENV_FILE" || [ -z "$(grep "^PUBLIC_REGISTRATION_ENABLED=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
update_env_var "PUBLIC_REGISTRATION_ENABLED" "true"
else
printf " ${GREEN}> PUBLIC_REGISTRATION_ENABLED already exists.${NC}\n"
fi
}

# Function to generate admin password
generate_admin_password() {
printf "${CYAN}> Generating admin password...${NC}\n"
Expand Down Expand Up @@ -533,6 +550,80 @@ get_docker_compose_command() {
echo "$base_command"
}

# Add this new function for handling registration configuration
handle_registration_configuration() {
printf "${YELLOW}+++ Public Registration Configuration +++${NC}\n"
printf "\n"

# Check if AliasVault is installed
if [ ! -f "docker-compose.yml" ]; then
printf "${RED}Error: AliasVault must be installed first.${NC}\n"
exit 1
fi

# Get current registration setting
CURRENT_SETTING=$(grep "^PUBLIC_REGISTRATION=" "$ENV_FILE" | cut -d '=' -f2)

printf "${CYAN}About Public Registration:${NC}\n"
printf "Public registration allows new users to create their own accounts on your AliasVault instance.\n"
printf "When disabled, no new accounts can be created.\n"
printf "\n"
printf "${CYAN}Current Configuration:${NC}\n"
if [ "$CURRENT_SETTING" = "true" ]; then
printf "Public Registration: ${GREEN}Enabled${NC}\n"
else
printf "Public Registration: ${RED}Disabled${NC}\n"
fi

printf "\n"
printf "Options:\n"
printf "1) Enable public registration\n"
printf "2) Disable public registration\n"
printf "3) Cancel\n"
printf "\n"

read -p "Select an option [1-3]: " reg_option

case $reg_option in
1)
update_env_var "PUBLIC_REGISTRATION" "true"
printf "${GREEN}> Public registration has been enabled.${NC}\n"

printf "\n${YELLOW}Warning: Docker containers need to be restarted to apply these changes.${NC}\n"
read -p "Restart now? (y/n): " restart_confirm

if [ "$restart_confirm" != "y" ] && [ "$restart_confirm" != "Y" ]; then
printf "${YELLOW}Please restart manually to apply the changes.${NC}\n"
exit 0
fi

handle_restart
;;
2)
update_env_var "PUBLIC_REGISTRATION" "false"
printf "${YELLOW}> Public registration has been disabled.${NC}\n"

printf "\n${YELLOW}Warning: Docker containers need to be restarted to apply these changes.${NC}\n"
read -p "Restart now? (y/n): " restart_confirm

if [ "$restart_confirm" != "y" ] && [ "$restart_confirm" != "Y" ]; then
printf "${YELLOW}Please restart manually to apply the changes.${NC}\n"
exit 0
fi

handle_restart
;;
3)
printf "${YELLOW}Registration configuration cancelled.${NC}\n"
exit 0
;;
*)
printf "${RED}Invalid option selected.${NC}\n"
exit 1
;;
esac
}

# Function to handle initial installation or reinstallation
handle_install() {
local specified_version="$1"
Expand Down Expand Up @@ -596,6 +687,8 @@ handle_build() {
set_smtp_tls_enabled || { printf "${RED}> Failed to set SMTP TLS${NC}\n"; exit 1; }
set_support_email || { printf "${RED}> Failed to set support email${NC}\n"; exit 1; }
set_default_ports || { printf "${RED}> Failed to set default ports${NC}\n"; exit 1; }
set_public_registration || { printf "${RED}> Failed to set public registration${NC}\n"; exit 1; }


# Only generate admin password if not already set
if ! grep -q "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" || [ -z "$(grep "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
Expand Down Expand Up @@ -785,7 +878,6 @@ handle_ssl_configuration() {
esac
}

# Function to handle email server configuration
# Function to handle email server configuration
handle_email_configuration() {
# Setup trap for Ctrl+C and other interrupts
Expand Down Expand Up @@ -852,21 +944,22 @@ handle_email_configuration() {
fi
done

printf "\n${YELLOW}Warning: Docker containers need to be restarted to apply these changes.${NC}\n"
read -p "Continue with restart? (y/n): " restart_confirm

if [ "$restart_confirm" != "y" ] && [ "$restart_confirm" != "Y" ]; then
printf "${YELLOW}Configuration cancelled.${NC}\n"
exit 0
fi

# Update .env file and restart
if ! update_env_var "PRIVATE_EMAIL_DOMAINS" "$new_domains"; then
printf "${RED}Failed to update configuration.${NC}\n"
exit 1
fi

printf "${GREEN}Email server configuration updated${NC}\n"

printf "\n${YELLOW}Warning: Docker containers need to be restarted to apply these changes.${NC}\n"
read -p "Restart now? (y/n): " restart_confirm

if [ "$restart_confirm" != "y" ] && [ "$restart_confirm" != "Y" ]; then
printf "${YELLOW}Please restart manually to apply the changes.${NC}\n"
exit 0
fi

printf "Restarting AliasVault services...\n"

if ! handle_restart; then
Expand Down Expand Up @@ -1277,6 +1370,7 @@ handle_install_version() {
set_smtp_tls_enabled || { printf "${RED}> Failed to set SMTP TLS${NC}\n"; exit 1; }
set_support_email || { printf "${RED}> Failed to set support email${NC}\n"; exit 1; }
set_default_ports || { printf "${RED}> Failed to set default ports${NC}\n"; exit 1; }
set_public_registration || { printf "${RED}> Failed to set public registration${NC}\n"; exit 1; }

# Only generate admin password if not already set
if ! grep -q "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" || [ -z "$(grep "^ADMIN_PASSWORD_HASH=" "$ENV_FILE" | cut -d '=' -f2)" ]; then
Expand Down
19 changes: 19 additions & 0 deletions src/AliasVault.Api/Config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//-----------------------------------------------------------------------
// <copyright file="Config.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------

namespace AliasVault.Api;

/// <summary>
/// Configuration class for the Client project with values loaded from appsettings.json.
/// </summary>
public class Config
{
/// <summary>
/// Gets or sets a value indicating whether public registration is enabled.
/// </summary>
public bool PublicRegistrationEnabled { get; set; }
}
9 changes: 8 additions & 1 deletion src/AliasVault.Api/Controllers/AuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,11 @@
/// <param name="cache">IMemoryCache instance for persisting SRP values during multistep login process.</param>
/// <param name="timeProvider">ITimeProvider instance. This returns the time which can be mutated for testing.</param>
/// <param name="authLoggingService">AuthLoggingService instance. This is used to log auth attempts to the database.</param>
/// <param name="config">Config instance.</param>
[Route("v{version:apiVersion}/[controller]")]
[ApiController]
[ApiVersion("1")]
public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFactory, UserManager<AliasVaultUser> userManager, SignInManager<AliasVaultUser> signInManager, IConfiguration configuration, IMemoryCache cache, ITimeProvider timeProvider, AuthLoggingService authLoggingService) : ControllerBase
public class AuthController(IDbContextFactory<AliasServerDbContext> dbContextFactory, UserManager<AliasVaultUser> userManager, SignInManager<AliasVaultUser> signInManager, IConfiguration configuration, IMemoryCache cache, ITimeProvider timeProvider, AuthLoggingService authLoggingService, Config config) : ControllerBase

Check warning on line 46 in src/AliasVault.Api/Controllers/AuthController.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

Constructor has 8 parameters, which is greater than the 7 authorized. (https://rules.sonarsource.com/csharp/RSPEC-107)
{
/// <summary>
/// Error message for invalid username or password.
Expand Down Expand Up @@ -331,6 +332,12 @@
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterRequest model)
{
// Check if public registration is disabled in the configuration.
if (!config.PublicRegistrationEnabled)
{
return BadRequest(ServerValidationErrorResponse.Create(["New account registration is currently disabled on this server. Please contact the administrator."], 400));
}

// Validate the username.
var (isValid, errorMessage) = ValidateUsername(model.Username);
if (!isValid)
Expand Down
8 changes: 8 additions & 0 deletions src/AliasVault.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Text;
using AliasServerDb;
using AliasServerDb.Configuration;
using AliasVault.Api;
using AliasVault.Api.Jwt;
using AliasVault.Auth;
using AliasVault.Cryptography.Server;
Expand All @@ -24,6 +25,13 @@
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true, reloadOnChange: true);

var config = new Config();
var publicRegistrationEnabled = Environment.GetEnvironmentVariable("PUBLIC_REGISTRATION_ENABLED") ?? "false";
config.PublicRegistrationEnabled = bool.Parse(publicRegistrationEnabled);

builder.Services.AddSingleton(config);

builder.Services.ConfigureLogging(builder.Configuration, Assembly.GetExecutingAssembly().GetName().Name!, "../../logs");

builder.Services.AddAliasVaultDataProtection("AliasVault.Api");
Expand Down Expand Up @@ -94,7 +102,7 @@
{
options.AddPolicy(
"CorsPolicy",
policy => policy.AllowAnyOrigin()

Check warning on line 105 in src/AliasVault.Api/Program.cs

View workflow job for this annotation

GitHub Actions / Build and analyze

Make sure this permissive CORS policy is safe here. (https://rules.sonarsource.com/csharp/RSPEC-5122)
.AllowAnyMethod()
.AllowAnyHeader());
});
Expand Down
6 changes: 4 additions & 2 deletions src/AliasVault.Api/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"JWT_KEY": "12345678901234567890123456789012",
"DATA_PROTECTION_CERT_PASS": "Development"
"DATA_PROTECTION_CERT_PASS": "Development",
"PUBLIC_REGISTRATION_ENABLED": "true"
},
"dotnetRunMessages": true,
"applicationUrl": "http://0.0.0.0:5092"
Expand All @@ -19,7 +20,8 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"JWT_KEY": "12345678901234567890123456789012",
"DATA_PROTECTION_CERT_PASS": "Development"
"DATA_PROTECTION_CERT_PASS": "Development",
"PUBLIC_REGISTRATION_ENABLED": "true"
},
"dotnetRunMessages": true,
"applicationUrl": "https://0.0.0.0:7223"
Expand Down
10 changes: 7 additions & 3 deletions src/AliasVault.Client/Auth/Pages/Login.razor
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@page "/user/login"
@inherits AliasVault.Client.Auth.Pages.Base.LoginBase
@layout Auth.Layout.MainLayout
@inject Config Config
@attribute [AllowAnonymous]
@using System.Text.Json
@using AliasVault.Shared.Models.WebApi.Auth
Expand Down Expand Up @@ -103,9 +104,12 @@ else
</div>

<button type="submit" class="w-full px-5 py-3 text-base font-medium text-center text-white bg-primary-700 rounded-lg hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 sm:w-auto dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800">Login to your account</button>
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">
No account yet? <a href="/user/setup" class="text-primary-700 hover:underline dark:text-primary-500">Create new vault</a>
</div>
@if (Config.PublicRegistrationEnabled)
{
<div class="text-sm font-medium text-gray-500 dark:text-gray-400">
No account yet? <a href="/user/setup" class="text-primary-700 hover:underline dark:text-primary-500">Create new vault</a>
</div>
}
</EditForm>
}

Expand Down
10 changes: 7 additions & 3 deletions src/AliasVault.Client/Auth/Pages/Start.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
@using AliasVault.Client.Auth.Components
@inherits AliasVault.Client.Auth.Pages.Base.LoginBase
@layout Auth.Layout.EmptyLayout
@inject Config Config
@attribute [AllowAnonymous]

<div class="flex lg:min-h-screen bg-gray-50 dark:bg-gray-900">
Expand All @@ -22,9 +23,12 @@
Your Privacy. Protected.
</p>
<div class="space-y-4">
<a href="/user/setup" class="block w-full py-3 px-4 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition duration-300 ease-in-out text-center">
Create new vault
</a>
@if (Config.PublicRegistrationEnabled)
{
<a href="/user/setup" class="block w-full py-3 px-4 bg-primary-600 hover:bg-primary-700 text-white font-semibold rounded-lg transition duration-300 ease-in-out text-center">
Create new vault
</a>
}
<a href="/user/login" class="block w-full py-3 px-4 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-800 text-gray-800 dark:text-white font-semibold rounded-lg transition duration-300 ease-in-out text-center">
Log in with existing account
</a>
Expand Down
5 changes: 5 additions & 0 deletions src/AliasVault.Client/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@ public class Config
/// Gets or sets the support email address that users can contact for password recovery.
/// </summary>
public string? SupportEmail { get; set; }

/// <summary>
/// Gets or sets a value indicating whether public registration is enabled.
/// </summary>
public bool PublicRegistrationEnabled { get; set; }
}
3 changes: 3 additions & 0 deletions src/AliasVault.Client/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,8 @@ else
sed -i "s|\"SupportEmail\": \".*\"|\"SupportEmail\": \"\"|g" /usr/share/nginx/html/appsettings.json
fi

# Update public registration enabled in appsettings.json
sed -i "s|\"PublicRegistrationEnabled\": \".*\"|\"PublicRegistrationEnabled\": \"$PUBLIC_REGISTRATION_ENABLED\"|g" /usr/share/nginx/html/appsettings.json

# Start the application
nginx -g "daemon off;"
3 changes: 2 additions & 1 deletion src/AliasVault.Client/wwwroot/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"ApiUrl": "http://localhost:5092",
"PrivateEmailDomains": ["example.tld"],
"SupportEmail": "[email protected]"
"SupportEmail": "[email protected]",
"PublicRegistrationEnabled": "true"
}
Loading
Loading