1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 00:22:50 -05:00

more premium licensing

This commit is contained in:
Kyle Spearrin
2017-08-11 22:55:25 -04:00
parent 73029f76d2
commit 9c254a7325
12 changed files with 126 additions and 59 deletions

View File

@ -106,7 +106,7 @@ namespace Bit.Core.Services
throw new InvalidOperationException("No exp in token.");
}
var expiration = CoreHelpers.FromEpocMilliseconds(1000 * exp.Value<long>());
var expiration = CoreHelpers.FromEpocSeconds(exp.Value<long>());
return DateTime.UtcNow < expiration;
}

View File

@ -11,26 +11,23 @@ using System.Text;
namespace Bit.Core.Services
{
public class RsaLicenseVerificationService : ILicenseVerificationService
public class RsaLicensingService : ILicensingService
{
private readonly X509Certificate2 _certificate;
private readonly GlobalSettings _globalSettings;
private IDictionary<string, UserLicense> _userLicenseCache;
private IDictionary<string, OrganizationLicense> _organizationLicenseCache;
public RsaLicenseVerificationService(
public RsaLicensingService(
IHostingEnvironment environment,
GlobalSettings globalSettings)
{
if(!environment.IsDevelopment() && !globalSettings.SelfHosted)
{
throw new Exception($"{nameof(RsaLicenseVerificationService)} can only be used for self hosted instances.");
}
var certThumbprint = "207e64a231e8aa32aaf68a61037c075ebebd553f";
_globalSettings = globalSettings;
_certificate = CoreHelpers.GetEmbeddedCertificate("licensing.cer", null);
if(!_certificate.Thumbprint.Equals(CoreHelpers.CleanCertificateThumbprint(
"207e64a231e8aa32aaf68a61037c075ebebd553f"), StringComparison.InvariantCultureIgnoreCase))
_certificate = !_globalSettings.SelfHosted ? CoreHelpers.GetCertificate(certThumbprint)
: CoreHelpers.GetEmbeddedCertificate("licensing.cer", null);
if(_certificate == null || !_certificate.Thumbprint.Equals(CoreHelpers.CleanCertificateThumbprint(certThumbprint),
StringComparison.InvariantCultureIgnoreCase))
{
throw new Exception("Invalid licensing certificate.");
}
@ -43,7 +40,12 @@ namespace Bit.Core.Services
public bool VerifyOrganizationPlan(Organization organization)
{
if(_globalSettings.SelfHosted && !organization.SelfHost)
if(!_globalSettings.SelfHosted)
{
return true;
}
if(!organization.SelfHost)
{
return false;
}
@ -54,6 +56,11 @@ namespace Bit.Core.Services
public bool VerifyUserPremium(User user)
{
if(!_globalSettings.SelfHosted)
{
return user.Premium;
}
if(!user.Premium)
{
return false;
@ -68,6 +75,16 @@ namespace Bit.Core.Services
return license.VerifySignature(_certificate);
}
public byte[] SignLicense(ILicense license)
{
if(_globalSettings.SelfHosted || !_certificate.HasPrivateKey)
{
throw new InvalidOperationException("Cannot sign licenses.");
}
return license.Sign(_certificate);
}
private UserLicense ReadUserLicense(User user)
{
if(_userLicenseCache != null && _userLicenseCache.ContainsKey(user.LicenseKey))
@ -75,7 +92,7 @@ namespace Bit.Core.Services
return _userLicenseCache[user.LicenseKey];
}
var filePath = $"{_globalSettings.LicenseDirectory}/user/{user.LicenseKey}.json";
var filePath = $"{_globalSettings.LicenseDirectory}/user/{user.Id}.json";
if(!File.Exists(filePath))
{
return null;
@ -98,7 +115,7 @@ namespace Bit.Core.Services
return _organizationLicenseCache[organization.LicenseKey];
}
var filePath = $"{_globalSettings.LicenseDirectory}/organization/{organization.LicenseKey}.json";
var filePath = $"{_globalSettings.LicenseDirectory}/organization/{organization.Id}.json";
if(!File.Exists(filePath))
{
return null;

View File

@ -37,7 +37,7 @@ namespace Bit.Core.Services
private readonly IdentityOptions _identityOptions;
private readonly IPasswordHasher<User> _passwordHasher;
private readonly IEnumerable<IPasswordValidator<User>> _passwordValidators;
private readonly ILicenseVerificationService _licenseVerificationService;
private readonly ILicensingService _licenseService;
private readonly CurrentContext _currentContext;
private readonly GlobalSettings _globalSettings;
@ -57,7 +57,7 @@ namespace Bit.Core.Services
IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<User>> logger,
ILicenseVerificationService licenseVerificationService,
ILicensingService licenseService,
CurrentContext currentContext,
GlobalSettings globalSettings)
: base(
@ -81,7 +81,7 @@ namespace Bit.Core.Services
_identityErrorDescriber = errors;
_passwordHasher = passwordHasher;
_passwordValidators = passwordValidators;
_licenseVerificationService = licenseVerificationService;
_licenseService = licenseService;
_currentContext = currentContext;
_globalSettings = globalSettings;
}
@ -540,13 +540,14 @@ namespace Bit.Core.Services
IPaymentService paymentService = null;
if(_globalSettings.SelfHosted)
{
if(license == null || !_licenseVerificationService.VerifyLicense(license))
if(license == null || !_licenseService.VerifyLicense(license))
{
throw new BadRequestException("Invalid license.");
}
Directory.CreateDirectory(_globalSettings.LicenseDirectory);
File.WriteAllText(_globalSettings.LicenseDirectory, JsonConvert.SerializeObject(license, Formatting.Indented));
var dir = $"{_globalSettings.LicenseDirectory}/user";
Directory.CreateDirectory(dir);
File.WriteAllText($"{dir}/{user.Id}.json", JsonConvert.SerializeObject(license, Formatting.Indented));
}
else if(!string.IsNullOrWhiteSpace(paymentToken))
{
@ -567,20 +568,26 @@ namespace Bit.Core.Services
}
user.Premium = true;
user.MaxStorageGb = _globalSettings.SelfHosted ? (short)10240 : (short)(1 + additionalStorageGb);
user.RevisionDate = DateTime.UtcNow;
if(_globalSettings.SelfHosted)
{
user.MaxStorageGb = 10240;
user.LicenseKey = license.LicenseKey;
}
else
{
user.MaxStorageGb = (short)(1 + additionalStorageGb);
user.LicenseKey = CoreHelpers.SecureRandomString(20, upper: false);
}
try
{
await SaveUserAsync(user);
}
catch
catch when(!_globalSettings.SelfHosted)
{
if(!_globalSettings.SelfHosted)
{
await paymentService.CancelAndRecoverChargesAsync(user);
}
await paymentService.CancelAndRecoverChargesAsync(user);
throw;
}
}