mirror of
https://github.com/bitwarden/server.git
synced 2024-11-22 12:15:36 +01:00
remove scim project
This commit is contained in:
parent
61806cd8ac
commit
fffe92e634
@ -45,11 +45,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Icons", "src\Icons\Icons.cs
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Events", "src\Events\Events.csproj", "{994DD611-F266-4BD3-8072-3B1B57267ED5}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scim", "src\Scim\Scim.csproj", "{B8C5FFEB-186A-46FF-B914-BB3D50AA8D61}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EventsProcessor", "src\EventsProcessor\EventsProcessor.csproj", "{2235D24F-E607-47F4-81AD-BB4504ADF9C6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Admin", "src\Admin\Admin.csproj", "{B131CEF3-89FB-4C90-ADB0-9E9C4246EB56}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Admin", "src\Admin\Admin.csproj", "{B131CEF3-89FB-4C90-ADB0-9E9C4246EB56}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@ -107,10 +105,6 @@ Global
|
||||
{994DD611-F266-4BD3-8072-3B1B57267ED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{994DD611-F266-4BD3-8072-3B1B57267ED5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{994DD611-F266-4BD3-8072-3B1B57267ED5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B8C5FFEB-186A-46FF-B914-BB3D50AA8D61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B8C5FFEB-186A-46FF-B914-BB3D50AA8D61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B8C5FFEB-186A-46FF-B914-BB3D50AA8D61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B8C5FFEB-186A-46FF-B914-BB3D50AA8D61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2235D24F-E607-47F4-81AD-BB4504ADF9C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2235D24F-E607-47F4-81AD-BB4504ADF9C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2235D24F-E607-47F4-81AD-BB4504ADF9C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@ -136,7 +130,6 @@ Global
|
||||
{A6C44A84-8E51-4C64-B9C4-7B7C23253345} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
|
||||
{9CF59342-3912-4B45-A2BA-0F173666586D} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{994DD611-F266-4BD3-8072-3B1B57267ED5} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{B8C5FFEB-186A-46FF-B914-BB3D50AA8D61} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{2235D24F-E607-47F4-81AD-BB4504ADF9C6} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
{B131CEF3-89FB-4C90-ADB0-9E9C4246EB56} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84D}
|
||||
EndGlobalSection
|
||||
|
@ -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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
{
|
||||
"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 @@
|
||||
<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 @@
|
||||
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 @@
|
||||
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 @@
|
||||
{
|
||||
"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 @@
|
||||
{
|
||||
"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
Block a user