20 changed files with 1 additions and 796 deletions
@ -1,20 +0,0 @@
@@ -1,20 +0,0 @@
|
||||
namespace Bit.Scim |
||||
{ |
||||
public class Constants |
||||
{ |
||||
public static class Schemas |
||||
{ |
||||
public const string User = @"urn:ietf:params:scim:schemas:core:2.0:User"; |
||||
public const string UserEnterprise = @"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"; |
||||
public const string Group = @"urn:ietf:params:scim:schemas:core:2.0:Group"; |
||||
} |
||||
|
||||
public static class Messages |
||||
{ |
||||
public const string Error = @"urn:ietf:params:scim:api:messages:2.0:Error"; |
||||
public const string PatchOp = @"urn:ietf:params:scim:api:messages:2.0:PatchOp"; |
||||
public const string ListResponse = @"urn:ietf:params:scim:api:messages:2.0:ListResponse"; |
||||
public const string SearchRequest = @"urn:ietf:params:scim:api:messages:2.0:SearchRequest"; |
||||
} |
||||
} |
||||
} |
||||
@ -1,36 +0,0 @@
@@ -1,36 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text.RegularExpressions; |
||||
using Bit.Core.Models; |
||||
using Microsoft.AspNetCore.Mvc; |
||||
|
||||
namespace Bit.Scim.Controllers |
||||
{ |
||||
public class BaseController : Controller |
||||
{ |
||||
protected ICollection<T> FilterResources<T>(ICollection<T> resources, string filter) where T : IExternal |
||||
{ |
||||
if(!string.IsNullOrWhiteSpace(filter)) |
||||
{ |
||||
var filterMatch = Regex.Match(filter, "(\\w+) eq \"([^\"]*)\""); |
||||
if(filterMatch.Success && filterMatch.Groups.Count > 2) |
||||
{ |
||||
var searchKey = filterMatch.Groups[1].Value; |
||||
var searchValue = filterMatch.Groups[2].Value; |
||||
|
||||
if(!string.IsNullOrWhiteSpace(searchKey) && !string.IsNullOrWhiteSpace(searchValue)) |
||||
{ |
||||
var searchKeyLower = searchKey.ToLowerInvariant(); |
||||
if(searchKeyLower == "externalid") |
||||
{ |
||||
resources = resources.Where(u => u.ExternalId == searchValue).ToList(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
return resources; |
||||
} |
||||
} |
||||
} |
||||
@ -1,117 +0,0 @@
@@ -1,117 +0,0 @@
|
||||
using System; |
||||
using System.Threading.Tasks; |
||||
using Bit.Core.Repositories; |
||||
using Microsoft.AspNetCore.Mvc; |
||||
using System.Linq; |
||||
using Bit.Scim.Models; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using Bit.Core.Services; |
||||
using Bit.Core.Exceptions; |
||||
|
||||
namespace Bit.Scim.Controllers |
||||
{ |
||||
[Route("groups")] |
||||
[Route("scim/groups")] |
||||
public class GroupsController : BaseController |
||||
{ |
||||
private readonly IGroupRepository _groupRepository; |
||||
private readonly IGroupService _groupService; |
||||
private Guid _orgId = new Guid("2933f760-9c0b-4efb-a437-a82a00ed3fc1"); // TODO: come from context |
||||
|
||||
public GroupsController( |
||||
IGroupRepository groupRepository, |
||||
IGroupService groupService) |
||||
{ |
||||
_groupRepository = groupRepository; |
||||
_groupService = groupService; |
||||
} |
||||
|
||||
[HttpGet] |
||||
public async Task<IActionResult> GetAll([FromQuery]string filter, [FromQuery]string excludedAttributes, |
||||
[FromQuery]string attributes) |
||||
{ |
||||
var groups = await _groupRepository.GetManyByOrganizationIdAsync(_orgId); |
||||
groups = FilterResources(groups, filter); |
||||
var groupsResult = groups.Select(g => new ScimGroup(g)); |
||||
var result = new ScimListResponse(groupsResult); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpGet("{id}")] |
||||
public async Task<IActionResult> Get(string id) |
||||
{ |
||||
var group = await _groupRepository.GetByIdAsync(new Guid(id)); |
||||
if(group == null || group.OrganizationId != _orgId) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
var result = new ScimGroup(group); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpPost] |
||||
public async Task<IActionResult> Post([FromBody]ScimGroup model) |
||||
{ |
||||
var group = model.ToGroup(_orgId); |
||||
await _groupService.SaveAsync(group); |
||||
var result = new ScimGroup(group); |
||||
var getUrl = Url.Action("Get", "Groups", new { id = group.Id.ToString() }, Request.Protocol, Request.Host.Value); |
||||
return new CreatedResult(getUrl, result); |
||||
} |
||||
|
||||
[HttpPut("{id}")] |
||||
public async Task<IActionResult> Put(string id, [FromBody]ScimGroup model) |
||||
{ |
||||
var group = await _groupRepository.GetByIdAsync(new Guid(id)); |
||||
if(group == null || group.OrganizationId != _orgId) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
group = model.ToGroup(group); |
||||
await _groupService.SaveAsync(group); |
||||
|
||||
var result = new ScimGroup(group); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpPatch("{id}")] |
||||
public async Task<IActionResult> Patch(string id) |
||||
{ |
||||
var group = await _groupRepository.GetByIdAsync(new Guid(id)); |
||||
if(group == null || group.OrganizationId != _orgId) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
var memstream = new MemoryStream(); |
||||
Request.Body.CopyTo(memstream); |
||||
memstream.Position = 0; |
||||
using(var reader = new StreamReader(memstream)) |
||||
{ |
||||
var text = reader.ReadToEnd(); |
||||
Debug.WriteLine(text); |
||||
} |
||||
|
||||
// TODO: Do patch |
||||
|
||||
var result = new ScimGroup(group); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpDelete("{id}")] |
||||
public async Task<IActionResult> Delete(string id) |
||||
{ |
||||
var group = await _groupRepository.GetByIdAsync(new Guid(id)); |
||||
if(group == null || group.OrganizationId != _orgId) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
await _groupService.DeleteAsync(group); |
||||
return new OkResult(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,122 +0,0 @@
@@ -1,122 +0,0 @@
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Collections.Generic; |
||||
using System.Threading.Tasks; |
||||
using Bit.Core.Enums; |
||||
using Bit.Core.Repositories; |
||||
using Bit.Core.Services; |
||||
using Bit.Scim.Models; |
||||
using Microsoft.AspNetCore.Mvc; |
||||
using Bit.Core.Models.Data; |
||||
using Bit.Core.Exceptions; |
||||
|
||||
namespace Bit.Scim.Controllers |
||||
{ |
||||
[Route("users")] |
||||
[Route("scim/users")] |
||||
public class UsersController : BaseController |
||||
{ |
||||
private readonly IOrganizationUserRepository _organizationUserRepository; |
||||
private readonly IOrganizationService _organizationService; |
||||
private Guid _orgId = new Guid("2933f760-9c0b-4efb-a437-a82a00ed3fc1"); // TODO: come from context |
||||
|
||||
public UsersController( |
||||
IOrganizationUserRepository organizationUserRepository, |
||||
IOrganizationService organizationService) |
||||
{ |
||||
_organizationUserRepository = organizationUserRepository; |
||||
_organizationService = organizationService; |
||||
} |
||||
|
||||
[HttpGet] |
||||
public async Task<IActionResult> GetAll([FromQuery]string filter, [FromQuery]string excludedAttributes, |
||||
[FromQuery]string attributes) |
||||
{ |
||||
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(_orgId); |
||||
users = FilterResources(users, filter); |
||||
var usersResult = users.Select(u => new ScimUser(u)); |
||||
var result = new ScimListResponse(usersResult); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpGet("{id}")] |
||||
public async Task<IActionResult> Get(string id) |
||||
{ |
||||
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(_orgId); |
||||
var user = users.SingleOrDefault(u => u.Id == new Guid(id)); |
||||
if(user == null) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
var result = new ScimUser(user); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpPost] |
||||
public async Task<IActionResult> Post([FromBody]ScimUser model) |
||||
{ |
||||
var email = model.Emails?.FirstOrDefault(); |
||||
if(email == null) |
||||
{ |
||||
throw new BadRequestException("No email address available."); |
||||
} |
||||
|
||||
var orgUser = await _organizationService.InviteUserAsync(_orgId, null, email.Value, |
||||
OrganizationUserType.User, false, model.ExternalId, new List<SelectionReadOnly>()); |
||||
var result = new ScimUser(orgUser); |
||||
var getUrl = Url.Action("Get", "Users", new { id = orgUser.Id.ToString() }, Request.Protocol, Request.Host.Value); |
||||
return new CreatedResult(getUrl, result); |
||||
} |
||||
|
||||
[HttpPut("{id}")] |
||||
public async Task<IActionResult> Put(string id, [FromBody]ScimUser model) |
||||
{ |
||||
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(_orgId); |
||||
var user = users.SingleOrDefault(u => u.Id == new Guid(id)); |
||||
if(user == null) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
// TODO: update |
||||
|
||||
var result = new ScimUser(user); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpPatch("{id}")] |
||||
public async Task<IActionResult> Patch(string id) |
||||
{ |
||||
var users = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(_orgId); |
||||
var user = users.SingleOrDefault(u => u.Id == new Guid(id)); |
||||
if(user == null) |
||||
{ |
||||
throw new NotFoundException(); |
||||
} |
||||
|
||||
var memstream = new MemoryStream(); |
||||
Request.Body.CopyTo(memstream); |
||||
memstream.Position = 0; |
||||
using(var reader = new StreamReader(memstream)) |
||||
{ |
||||
var text = reader.ReadToEnd(); |
||||
Debug.WriteLine(text); |
||||
} |
||||
|
||||
// TODO: patch |
||||
|
||||
var result = new ScimUser(user); |
||||
return new OkObjectResult(result); |
||||
} |
||||
|
||||
[HttpDelete("{id}")] |
||||
public async Task<IActionResult> Delete(string id) |
||||
{ |
||||
await _organizationService.DeleteUserAsync(_orgId, new Guid(id), null); |
||||
return new OkResult(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,34 +0,0 @@
@@ -1,34 +0,0 @@
|
||||
using System.Collections.Generic; |
||||
using System.Net; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public class ScimError |
||||
{ |
||||
private IEnumerable<string> _schemas; |
||||
|
||||
public ScimError() |
||||
{ |
||||
_schemas = new[] { Constants.Messages.Error }; |
||||
} |
||||
|
||||
public ScimError(HttpStatusCode status, string detail = null) |
||||
: this() |
||||
{ |
||||
Status = (int)status; |
||||
Detail = detail; |
||||
} |
||||
|
||||
[JsonProperty("schemas")] |
||||
public IEnumerable<string> Schemas |
||||
{ |
||||
get => _schemas; |
||||
set { _schemas = value; } |
||||
} |
||||
[JsonProperty("status")] |
||||
public int Status { get; set; } |
||||
[JsonProperty("detail")] |
||||
public string Detail { get; set; } |
||||
} |
||||
} |
||||
@ -1,42 +0,0 @@
@@ -1,42 +0,0 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using Bit.Core.Models.Table; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public class ScimGroup : ScimResource |
||||
{ |
||||
public ScimGroup() { } |
||||
|
||||
public ScimGroup(Group group) |
||||
{ |
||||
Id = group.Id.ToString(); |
||||
ExternalId = group.ExternalId; |
||||
DisplayName = group.Name; |
||||
Meta = new ScimResourceMetadata("Group"); |
||||
} |
||||
|
||||
public override string SchemaIdentifier => Constants.Schemas.Group; |
||||
[JsonProperty("displayName")] |
||||
public string DisplayName { get; set; } |
||||
[JsonProperty("members")] |
||||
public IEnumerable<ScimMultiValuedAttribute> Members { get; set; } |
||||
|
||||
public Group ToGroup(Guid orgId) |
||||
{ |
||||
return new Group |
||||
{ |
||||
ExternalId = ExternalId, |
||||
Name = DisplayName, |
||||
OrganizationId = orgId |
||||
}; |
||||
} |
||||
|
||||
public Group ToGroup(Group group) |
||||
{ |
||||
group.Name = DisplayName; |
||||
return group; |
||||
} |
||||
} |
||||
} |
||||
@ -1,24 +0,0 @@
@@ -1,24 +0,0 @@
|
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public class ScimListResponse : ScimSchemaBase |
||||
{ |
||||
public ScimListResponse(IEnumerable<ScimResource> resources) |
||||
{ |
||||
Resources = resources; |
||||
} |
||||
|
||||
public override string SchemaIdentifier => Constants.Messages.ListResponse; |
||||
[JsonProperty("totalResults", Order = 0)] |
||||
public int TotalResults => Resources == null ? 0 : Resources.Count(); |
||||
[JsonProperty("Resources", Order = 1)] |
||||
public IEnumerable<ScimResource> Resources { get; private set; } |
||||
[JsonProperty("startIndex", Order = 2)] |
||||
public int StartIndex { get; set; } = 0; |
||||
[JsonProperty("itemsPerPage", Order = 3)] |
||||
public int ItemsPerPage => Resources == null ? 0 : Resources.Count(); |
||||
} |
||||
} |
||||
@ -1,19 +0,0 @@
@@ -1,19 +0,0 @@
|
||||
using System; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public class ScimMultiValuedAttribute |
||||
{ |
||||
[JsonProperty("type")] |
||||
public string Type { get; set; } |
||||
[JsonProperty("primary")] |
||||
public bool Primary { get; set; } |
||||
[JsonProperty("display")] |
||||
public string Display { get; set; } |
||||
[JsonProperty("value")] |
||||
public string Value { get; set; } |
||||
[JsonProperty("$ref")] |
||||
public Uri Ref { get; set; } |
||||
} |
||||
} |
||||
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public abstract class ScimResource : ScimSchemaBase |
||||
{ |
||||
[JsonProperty(Order = -5, PropertyName = "id")] |
||||
public string Id { get; set; } |
||||
[JsonProperty(PropertyName = "externalId")] |
||||
public string ExternalId { get; set; } |
||||
[JsonProperty(Order = 9999, PropertyName = "meta")] |
||||
public ScimResourceMetadata Meta { get; set; } |
||||
} |
||||
} |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public class ScimResourceMetadata |
||||
{ |
||||
private ScimResourceMetadata() { } |
||||
|
||||
public ScimResourceMetadata(string resourceType) |
||||
{ |
||||
ResourceType = resourceType; |
||||
} |
||||
|
||||
[JsonProperty("resourceType")] |
||||
public string ResourceType { get; set; } |
||||
} |
||||
} |
||||
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
using System.Collections.Generic; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public abstract class ScimSchemaBase |
||||
{ |
||||
[JsonProperty("schemas", Order = -10)] |
||||
public virtual ISet<string> Schemas => new HashSet<string>(new[] { SchemaIdentifier }); |
||||
[JsonIgnore] |
||||
public abstract string SchemaIdentifier { get; } |
||||
} |
||||
} |
||||
@ -1,63 +0,0 @@
@@ -1,63 +0,0 @@
|
||||
using System.Collections.Generic; |
||||
using Bit.Core.Models.Data; |
||||
using Bit.Core.Models.Table; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace Bit.Scim.Models |
||||
{ |
||||
public class ScimUser : ScimResource |
||||
{ |
||||
public ScimUser() { } |
||||
|
||||
public ScimUser(OrganizationUserUserDetails userDetails) |
||||
{ |
||||
Id = userDetails.Id.ToString(); |
||||
ExternalId = userDetails.ExternalId; |
||||
UserName = userDetails.Email; |
||||
Name = new ScimName |
||||
{ |
||||
Formatted = userDetails.Name |
||||
}; |
||||
DisplayName = userDetails.Name; |
||||
Active = true; |
||||
Emails = new List<ScimMultiValuedAttribute> { |
||||
new ScimMultiValuedAttribute { Type = "work", Value = userDetails.Email } }; |
||||
Meta = new ScimResourceMetadata("User"); |
||||
} |
||||
|
||||
public ScimUser(OrganizationUser orgUser) |
||||
{ |
||||
Id = orgUser.Id.ToString(); |
||||
ExternalId = orgUser.ExternalId; |
||||
UserName = orgUser.Email; |
||||
Active = true; |
||||
Emails = new List<ScimMultiValuedAttribute> { |
||||
new ScimMultiValuedAttribute { Type = "work", Value = orgUser.Email } }; |
||||
Meta = new ScimResourceMetadata("User"); |
||||
} |
||||
|
||||
public override string SchemaIdentifier => Constants.Schemas.User; |
||||
[JsonProperty("userName")] |
||||
public string UserName { get; set; } |
||||
[JsonProperty("name")] |
||||
public ScimName Name { get; set; } |
||||
[JsonProperty("displayName")] |
||||
public string DisplayName { get; set; } |
||||
[JsonProperty("active")] |
||||
public bool Active { get; set; } |
||||
[JsonProperty("emails")] |
||||
public IEnumerable<ScimMultiValuedAttribute> Emails { get; set; } |
||||
[JsonProperty("groups")] |
||||
public IEnumerable<ScimMultiValuedAttribute> Groups { get; set; } |
||||
|
||||
public class ScimName |
||||
{ |
||||
[JsonProperty("formatted")] |
||||
public string Formatted { get; set; } |
||||
[JsonProperty("familyName")] |
||||
public string FamilyName { get; set; } |
||||
[JsonProperty("givenName")] |
||||
public string GivenName { get; set; } |
||||
} |
||||
} |
||||
} |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
using Microsoft.AspNetCore; |
||||
using Microsoft.AspNetCore.Hosting; |
||||
|
||||
namespace Bit.Scim |
||||
{ |
||||
public class Program |
||||
{ |
||||
public static void Main(string[] args) |
||||
{ |
||||
WebHost |
||||
.CreateDefaultBuilder(args) |
||||
.UseStartup<Startup>() |
||||
.Build() |
||||
.Run(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,27 +0,0 @@
@@ -1,27 +0,0 @@
|
||||
{ |
||||
"iisSettings": { |
||||
"windowsAuthentication": false, |
||||
"anonymousAuthentication": true, |
||||
"iisExpress": { |
||||
"applicationUrl": "http://localhost:9000/", |
||||
"sslPort": 0 |
||||
} |
||||
}, |
||||
"profiles": { |
||||
"IIS Express": { |
||||
"commandName": "IISExpress", |
||||
"launchBrowser": false, |
||||
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
} |
||||
}, |
||||
"Scim": { |
||||
"commandName": "Project", |
||||
"launchBrowser": false, |
||||
"environmentVariables": { |
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
}, |
||||
"applicationUrl": "http://localhost:9000/" |
||||
} |
||||
} |
||||
} |
||||
@ -1,25 +0,0 @@
@@ -1,25 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
||||
<PropertyGroup> |
||||
<Version>1.20.0</Version> |
||||
<TargetFramework>netcoreapp2.0</TargetFramework> |
||||
<RootNamespace>Bit.Scim</RootNamespace> |
||||
<UserSecretsId>bitwarden-Scim</UserSecretsId> |
||||
<MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish> |
||||
<MvcRazorExcludeRefAssembliesFromPublish>false</MvcRazorExcludeRefAssembliesFromPublish> |
||||
</PropertyGroup> |
||||
|
||||
<ItemGroup> |
||||
<ProjectReference Include="..\Core\Core.csproj" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" /> |
||||
</ItemGroup> |
||||
|
||||
<ItemGroup> |
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" /> |
||||
<DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="2.0.0" /> |
||||
</ItemGroup> |
||||
|
||||
</Project> |
||||
@ -1,79 +0,0 @@
@@ -1,79 +0,0 @@
|
||||
using Bit.Core; |
||||
using Bit.Core.Utilities; |
||||
using Bit.Scim.Utilities; |
||||
using Microsoft.ApplicationInsights.Extensibility; |
||||
using Microsoft.AspNetCore.Builder; |
||||
using Microsoft.AspNetCore.Hosting; |
||||
using Microsoft.AspNetCore.Http; |
||||
using Microsoft.Extensions.Configuration; |
||||
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
using Microsoft.Extensions.Logging; |
||||
using Serilog.Events; |
||||
|
||||
namespace Bit.Scim |
||||
{ |
||||
public class Startup |
||||
{ |
||||
public Startup(IConfiguration configuration) |
||||
{ |
||||
Configuration = configuration; |
||||
} |
||||
|
||||
public IConfiguration Configuration { get; } |
||||
|
||||
public void ConfigureServices(IServiceCollection services) |
||||
{ |
||||
// Options |
||||
services.AddOptions(); |
||||
|
||||
// Settings |
||||
var globalSettings = services.AddGlobalSettingsServices(Configuration); |
||||
|
||||
// Repositories |
||||
services.AddSqlServerRepositories(globalSettings); |
||||
|
||||
// Context |
||||
services.AddScoped<CurrentContext>(); |
||||
|
||||
// Identity |
||||
services.AddCustomIdentityServices(globalSettings); |
||||
|
||||
// Services |
||||
services.AddBaseServices(); |
||||
services.AddDefaultServices(globalSettings); |
||||
|
||||
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |
||||
|
||||
// Mvc |
||||
services.AddMvc(config => |
||||
{ |
||||
config.Filters.Add(new ExceptionHandlerFilterAttribute()); |
||||
}); |
||||
} |
||||
|
||||
public void Configure( |
||||
IApplicationBuilder app, |
||||
IHostingEnvironment env, |
||||
IApplicationLifetime appLifetime, |
||||
GlobalSettings globalSettings, |
||||
ILoggerFactory loggerFactory) |
||||
{ |
||||
// Disable app insights |
||||
var telConfig = app.ApplicationServices.GetService<TelemetryConfiguration>(); |
||||
telConfig.DisableTelemetry = true; |
||||
|
||||
loggerFactory.AddSerilog(app, env, appLifetime, globalSettings, (e) => e.Level >= LogEventLevel.Error); |
||||
|
||||
if(env.IsDevelopment()) |
||||
{ |
||||
app.UseDeveloperExceptionPage(); |
||||
} |
||||
|
||||
// Default Middleware |
||||
app.UseDefaultMiddleware(env); |
||||
|
||||
app.UseMvc(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,43 +0,0 @@
@@ -1,43 +0,0 @@
|
||||
using Bit.Core.Exceptions; |
||||
using Bit.Scim.Models; |
||||
using Microsoft.AspNetCore.Mvc; |
||||
using Microsoft.AspNetCore.Mvc.Filters; |
||||
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.Logging; |
||||
|
||||
namespace Bit.Scim.Utilities |
||||
{ |
||||
public class ExceptionHandlerFilterAttribute : ExceptionFilterAttribute |
||||
{ |
||||
public override void OnException(ExceptionContext context) |
||||
{ |
||||
var exception = context.Exception; |
||||
if(exception == null) |
||||
{ |
||||
// Should never happen. |
||||
return; |
||||
} |
||||
|
||||
var error = new ScimError(); |
||||
if(exception is BadRequestException) |
||||
{ |
||||
context.HttpContext.Response.StatusCode = error.Status = 400; |
||||
error.Detail = exception.Message; |
||||
} |
||||
else if(exception is NotFoundException) |
||||
{ |
||||
context.HttpContext.Response.StatusCode = error.Status = 404; |
||||
error.Detail = "Resource not found."; |
||||
} |
||||
else |
||||
{ |
||||
context.HttpContext.Response.StatusCode = error.Status = 500; |
||||
error.Detail = "An unhandled server error has occurred."; |
||||
var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<ExceptionHandlerFilterAttribute>>(); |
||||
logger.LogError(0, exception, exception.Message); |
||||
} |
||||
|
||||
context.Result = new ObjectResult(error); |
||||
} |
||||
} |
||||
} |
||||
@ -1,17 +0,0 @@
@@ -1,17 +0,0 @@
|
||||
{ |
||||
"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" |
||||
}, |
||||
"braintree": { |
||||
"production": true |
||||
} |
||||
} |
||||
} |
||||
@ -1,59 +0,0 @@
@@ -1,59 +0,0 @@
|
||||
{ |
||||
"globalSettings": { |
||||
"selfHosted": false, |
||||
"siteName": "Bitwarden", |
||||
"projectName": "Billing", |
||||
"stripeApiKey": "SECRET", |
||||
"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" |
||||
}, |
||||
"mail": { |
||||
"sendGridApiKey": "SECRET", |
||||
"replyToEmail": "hello@bitwarden.com" |
||||
}, |
||||
"identityServer": { |
||||
"certificateThumbprint": "SECRET" |
||||
}, |
||||
"dataProtection": { |
||||
"certificateThumbprint": "SECRET" |
||||
}, |
||||
"storage": { |
||||
"connectionString": "SECRET" |
||||
}, |
||||
"events": { |
||||
"connectionString": "SECRET" |
||||
}, |
||||
"documentDb": { |
||||
"uri": "SECRET", |
||||
"key": "SECRET" |
||||
}, |
||||
"sentry": { |
||||
"dsn": "SECRET" |
||||
}, |
||||
"notificationHub": { |
||||
"connectionString": "SECRET", |
||||
"hubName": "SECRET" |
||||
} |
||||
}, |
||||
"billingSettings": { |
||||
"stripeWebhookKey": "SECRET", |
||||
"stripeWebhookSecret": "SECRET", |
||||
"braintreeWebhookKey": "SECRET" |
||||
}, |
||||
"braintree": { |
||||
"production": false, |
||||
"merchantId": "SECRET", |
||||
"publicKey": "SECRET", |
||||
"privateKey": "SECRET" |
||||
} |
||||
} |
||||
Loading…
Reference in new issue