13 changed files with 460 additions and 84 deletions
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using Microsoft.AspNetCore.Authorization; |
||||
using Microsoft.AspNetCore.Mvc; |
||||
using Microsoft.AspNetCore.SignalR; |
||||
|
||||
namespace Bit.Hub |
||||
{ |
||||
[Authorize("Application")] |
||||
public class EventsController : Controller |
||||
{ |
||||
private readonly IHubContext<SyncHub> _syncHubContext; |
||||
|
||||
public EventsController(IHubContext<SyncHub> syncHubContext) |
||||
{ |
||||
_syncHubContext = syncHubContext; |
||||
} |
||||
|
||||
[HttpGet("~/events")] |
||||
public async Task GetTest() |
||||
{ |
||||
await _syncHubContext.Clients.All.SendAsync("ReceiveMessage", "From API."); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
||||
<PropertyGroup> |
||||
<Version>1.22.0</Version> |
||||
<TargetFramework>netcoreapp2.1</TargetFramework> |
||||
<RootNamespace>Bit.Hub</RootNamespace> |
||||
<UserSecretsId>bitwarden-Hub</UserSecretsId> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup> |
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" /> |
||||
<PackageReference Include="Microsoft.AspNetCore.App" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<ProjectReference Include="..\Core\Core.csproj" /> |
||||
</ItemGroup> |
||||
|
||||
</Project> |
||||
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
using Microsoft.AspNetCore; |
||||
using Microsoft.AspNetCore.Hosting; |
||||
|
||||
namespace Bit.Hub |
||||
{ |
||||
public class Program |
||||
{ |
||||
public static void Main(string[] args) |
||||
{ |
||||
WebHost |
||||
.CreateDefaultBuilder(args) |
||||
.UseStartup<Startup>() |
||||
.Build() |
||||
.Run(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
{ |
||||
"iisSettings": { |
||||
"windowsAuthentication": false, |
||||
"anonymousAuthentication": true, |
||||
"iisExpress": { |
||||
"applicationUrl": "http://localhost:61840", |
||||
"sslPort": 0 |
||||
} |
||||
}, |
||||
"profiles": { |
||||
"IIS Express": { |
||||
"commandName": "IISExpress", |
||||
"launchBrowser": true, |
||||
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
} |
||||
}, |
||||
"Bit.Hub": { |
||||
"commandName": "Project", |
||||
"launchBrowser": true, |
||||
"applicationUrl": "http://localhost:5000", |
||||
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
using System.Security.Claims; |
||||
using Bit.Core; |
||||
using Bit.Core.IdentityServer; |
||||
using Bit.Core.Services; |
||||
using Bit.Core.Utilities; |
||||
using IdentityModel; |
||||
using IdentityServer4.AccessTokenValidation; |
||||
using Microsoft.AspNetCore.Builder; |
||||
using Microsoft.AspNetCore.Hosting; |
||||
using Microsoft.AspNetCore.SignalR; |
||||
using Microsoft.Extensions.Configuration; |
||||
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.Logging; |
||||
using Microsoft.IdentityModel.Logging; |
||||
using Serilog.Events; |
||||
|
||||
namespace Bit.Hub |
||||
{ |
||||
public class Startup |
||||
{ |
||||
public Startup(IHostingEnvironment env, IConfiguration configuration) |
||||
{ |
||||
Configuration = configuration; |
||||
Environment = env; |
||||
} |
||||
|
||||
public IConfiguration Configuration { get; } |
||||
public IHostingEnvironment Environment { get; set; } |
||||
|
||||
public void ConfigureServices(IServiceCollection services) |
||||
{ |
||||
// Options |
||||
services.AddOptions(); |
||||
|
||||
// Settings |
||||
var globalSettings = services.AddGlobalSettingsServices(Configuration); |
||||
|
||||
// Repositories |
||||
services.AddSqlServerRepositories(globalSettings); |
||||
|
||||
// Context |
||||
services.AddScoped<CurrentContext>(); |
||||
|
||||
// Identity |
||||
services |
||||
.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme) |
||||
.AddIdentityServerAuthentication(options => |
||||
{ |
||||
options.Authority = globalSettings.BaseServiceUri.InternalIdentity; |
||||
options.RequireHttpsMetadata = !Environment.IsDevelopment() && |
||||
globalSettings.BaseServiceUri.InternalIdentity.StartsWith("https"); |
||||
options.TokenRetriever = TokenRetrieval.FromAuthorizationHeaderOrQueryString(); |
||||
options.NameClaimType = ClaimTypes.Email; |
||||
options.SupportedTokens = SupportedTokens.Jwt; |
||||
}); |
||||
|
||||
services.AddAuthorization(config => |
||||
{ |
||||
config.AddPolicy("Application", policy => |
||||
{ |
||||
policy.RequireAuthenticatedUser(); |
||||
policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application"); |
||||
}); |
||||
}); |
||||
|
||||
// SignalR |
||||
services.AddSignalR(); |
||||
services.AddSingleton<IUserIdProvider, SubjectUserIdProvider>(); |
||||
|
||||
// Mvc |
||||
services.AddMvc(); |
||||
|
||||
// Hosted Services |
||||
services.AddHostedService<TimedHostedService>(); |
||||
} |
||||
|
||||
public void Configure( |
||||
IApplicationBuilder app, |
||||
IHostingEnvironment env, |
||||
ILoggerFactory loggerFactory, |
||||
IApplicationLifetime appLifetime, |
||||
GlobalSettings globalSettings) |
||||
{ |
||||
IdentityModelEventSource.ShowPII = true; |
||||
loggerFactory.AddSerilog(app, env, appLifetime, globalSettings, (e) => |
||||
{ |
||||
var context = e.Properties["SourceContext"].ToString(); |
||||
if(context.Contains("IdentityServer4.Validation.TokenValidator") || |
||||
context.Contains("IdentityServer4.Validation.TokenRequestValidator")) |
||||
{ |
||||
return e.Level > LogEventLevel.Error; |
||||
} |
||||
|
||||
return e.Level >= LogEventLevel.Error; |
||||
}); |
||||
|
||||
if(env.IsDevelopment()) |
||||
{ |
||||
app.UseDeveloperExceptionPage(); |
||||
} |
||||
|
||||
// Default Middleware |
||||
app.UseDefaultMiddleware(env); |
||||
|
||||
// Add Cors |
||||
app.UseCors(policy => policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials()); |
||||
|
||||
// Add authentication to the request pipeline. |
||||
app.UseAuthentication(); |
||||
|
||||
// Add SignlarR |
||||
app.UseSignalR(routes => |
||||
{ |
||||
routes.MapHub<SyncHub>("/sync"); |
||||
}); |
||||
|
||||
// Add MVC to the request pipeline. |
||||
app.UseMvc(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
using IdentityModel; |
||||
using Microsoft.AspNetCore.SignalR; |
||||
|
||||
namespace Bit.Hub |
||||
{ |
||||
public class SubjectUserIdProvider : IUserIdProvider |
||||
{ |
||||
public string GetUserId(HubConnectionContext connection) |
||||
{ |
||||
return connection.User?.FindFirst(JwtClaimTypes.Subject)?.Value; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using Bit.Core; |
||||
using Microsoft.AspNetCore.Authorization; |
||||
|
||||
namespace Bit.Hub |
||||
{ |
||||
[Authorize("Application")] |
||||
public class SyncHub : Microsoft.AspNetCore.SignalR.Hub |
||||
{ |
||||
public override async Task OnConnectedAsync() |
||||
{ |
||||
var currentContext = new CurrentContext(); |
||||
currentContext.Build(Context.User); |
||||
foreach(var org in currentContext.Organizations) |
||||
{ |
||||
await Groups.AddToGroupAsync(Context.ConnectionId, $"Organization_{org.Id}"); |
||||
} |
||||
await base.OnConnectedAsync(); |
||||
} |
||||
|
||||
public override async Task OnDisconnectedAsync(Exception exception) |
||||
{ |
||||
var currentContext = new CurrentContext(); |
||||
currentContext.Build(Context.User); |
||||
foreach(var org in currentContext.Organizations) |
||||
{ |
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, $"Organization_{org.Id}"); |
||||
} |
||||
await base.OnDisconnectedAsync(exception); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
using System; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Microsoft.AspNetCore.SignalR; |
||||
using Microsoft.Extensions.Hosting; |
||||
using Microsoft.Extensions.Logging; |
||||
|
||||
namespace Bit.Hub |
||||
{ |
||||
public class TimedHostedService : IHostedService, IDisposable |
||||
{ |
||||
private readonly ILogger _logger; |
||||
private readonly IHubContext<SyncHub> _hubContext; |
||||
private Timer _timer; |
||||
|
||||
public TimedHostedService(ILogger<TimedHostedService> logger, IHubContext<SyncHub> hubContext) |
||||
{ |
||||
_logger = logger; |
||||
_hubContext = hubContext; |
||||
} |
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken) |
||||
{ |
||||
_logger.LogInformation("Timed Background Service is starting."); |
||||
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); |
||||
return Task.CompletedTask; |
||||
} |
||||
|
||||
private void DoWork(object state) |
||||
{ |
||||
_logger.LogInformation("Timed Background Service is working."); |
||||
_hubContext.Clients.All.SendAsync("ReceiveMessage", "From BG!!"); |
||||
} |
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) |
||||
{ |
||||
_logger.LogInformation("Timed Background Service is stopping."); |
||||
_timer?.Change(Timeout.Infinite, 0); |
||||
return Task.CompletedTask; |
||||
} |
||||
|
||||
public void Dispose() |
||||
{ |
||||
_timer?.Dispose(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
{ |
||||
"globalSettings": { |
||||
"baseServiceUri": { |
||||
"vault": "https://vault.bitwarden.com", |
||||
"api": "https://api.bitwarden.com", |
||||
"identity": "https://identity.bitwarden.com", |
||||
"admin": "https://admin.bitwarden.com", |
||||
"internalAdmin": "https://admin.bitwarden.com", |
||||
"internalIdentity": "https://identity.bitwarden.com", |
||||
"internalApi": "https://api.bitwarden.com", |
||||
"internalVault": "https://vault.bitwarden.com" |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
{ |
||||
"globalSettings": { |
||||
"selfHosted": false, |
||||
"projectName": "Hub", |
||||
"baseServiceUri": { |
||||
"vault": "https://localhost:8080", |
||||
"api": "http://localhost:4000", |
||||
"identity": "http://localhost:33656", |
||||
"admin": "http://localhost:62911", |
||||
"internalAdmin": "http://localhost:62911", |
||||
"internalIdentity": "http://localhost:33656", |
||||
"internalApi": "http://localhost:4000", |
||||
"internalVault": "http://localhost:4001" |
||||
}, |
||||
"sqlServer": { |
||||
"connectionString": "SECRET" |
||||
}, |
||||
"identityServer": { |
||||
"certificateThumbprint": "SECRET" |
||||
}, |
||||
"storage": { |
||||
"connectionString": "SECRET" |
||||
}, |
||||
"events": { |
||||
"connectionString": "SECRET" |
||||
}, |
||||
"documentDb": { |
||||
"uri": "SECRET", |
||||
"key": "SECRET" |
||||
}, |
||||
"sentry": { |
||||
"dsn": "SECRET" |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue