Unverified Commit ec9d48c3 authored by Alevtina Brown's avatar Alevtina Brown Committed by GitHub
Browse files

Merge pull request #2 from skoruba/dev

Create Dev Branch 
parents 78ea032c 54dc6706
......@@ -7,13 +7,17 @@
## Project Status
[![Build status](https://ci.appveyor.com/api/projects/status/5yg59bn70399hn6s/branch/master?svg=true)](https://ci.appveyor.com/project/JanSkoruba/identityserver4-admin/branch/master)
[![Build Status](https://dev.azure.com/skoruba/IdentityServer4.Admin/_apis/build/status/IdentityServer4.Admin-CI?branchName=master)](https://dev.azure.com/skoruba/IdentityServer4.Admin/_build/latest?definitionId=2?branchName=master)
[![Join the chat at https://gitter.im/skoruba/IdentityServer4.Admin](https://badges.gitter.im/skoruba/IdentityServer4.Admin.svg)](https://gitter.im/skoruba/IdentityServer4.Admin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
This is currently in **beta version**
The application is written in the **Asp.Net Core MVC - using .NET Core 2.1** - works only with **IdentityServer4 version 2.0+**
The application is written in the **Asp.Net Core MVC - using .NET Core 2.2**
**NOTE:** Works only with **IdentityServer4 version => 2.3.0** 🚀
## Requirements
- [Install](https://www.microsoft.com/net/download/windows#/current) the latest .NET Core 2.x SDK (using older versions may lead to 502.5 errors when hosted on IIS or application exiting immediately after starting when self-hosted)
## Installation via dotnet new template
......@@ -21,7 +25,7 @@ The application is written in the **Asp.Net Core MVC - using .NET Core 2.1** - w
- Install the dotnet new template:
```sh
dotnet new -i Skoruba.IdentityServer4.Admin.Templates::1.0.0-beta4-update1
dotnet new -i Skoruba.IdentityServer4.Admin.Templates::1.0.0-beta5-update1
```
- Create new project:
......@@ -133,18 +137,20 @@ Migrations are not a part of the repository - they are ignored in `.gitignore`.
## Localizations - labels, messages
- All labels and messages are stored in the resources `.resx` - locatated in `/Resources`
- Client label descriptions from - http://docs.identityserver.io/en/release/reference/client.html
- Api Resource label descriptions from - http://docs.identityserver.io/en/release/reference/api_resource.html
- Identity Resource label descriptions from - http://docs.identityserver.io/en/release/reference/identity_resource.html
## Tests
- The solution contains unit and integration tests.
- The solution contains unit and integration tests.
- **Stage environment is used for integration tests**:
- `DbContext` contains setup for InMemory database
- `Authentication` is setup for `CookieAuthentication` - with fake login url only for testing purpose
- `AuthenticatedTestRequestMiddleware` - middleware for testing of authentication.
- If you want to use `Stage environment` for deploying - it is necessary to change these settings in `StartupHelpers.cs`.
## Overview
......@@ -153,7 +159,7 @@ Migrations are not a part of the repository - they are ignored in `.gitignore`.
- STS:
- `Skoruba.IdentityServer4.STS.Identity` - [Quickstart UI for the IdentityServer4 with Asp.Net Core Identity and EF Core storage](https://github.com/IdentityServer/IdentityServer4.Samples/tree/release/Quickstarts/Combined_AspNetIdentity_and_EntityFrameworkStorage)
- `Skoruba.IdentityServer4.STS.Identity` - [Quickstart UI for the IdentityServer4 with Asp.Net Core Identity and EF Core storage](https://github.com/IdentityServer/IdentityServer4.Samples/tree/master/Quickstarts/Combined_AspId_and_EFStorage)
- Admin UI:
......@@ -193,6 +199,7 @@ It is possible to define the configuration according the client type - by defaul
- Single Page Application - Javascript - Implicit flow
- Native Application - Mobile/Desktop - Hybrid flow
- Machine/Robot - Resource Owner Password and Client Credentials flow
- TV and Limited-Input Device Application - Device flow
- Actions: Add, Update, Clone, Remove
- Entities:
......@@ -247,16 +254,17 @@ It is possible to define the configuration according the client type - by defaul
- [x] Create the Business Logic & EF layers - available as a nuget package
- [x] Create a project template using dotnet CLI - `dotnet new template`
- [x] First template: The administration of the IdentityServer4 and Asp.Net Core Identity
- [ ] Add audit logs to track changes ([#61](https://github.com/skoruba/IdentityServer4.Admin/issues/61))
- [ ] Add logging into
- [x] Add logging into
- [x] Database
- [ ] File
- [x] File
- [x] Add localization for other languages
- [x] English
- [x] Chinese
- [x] Russian
### 1.1.0:
- [ ] Add audit logs to track changes ([#61](https://github.com/skoruba/IdentityServer4.Admin/issues/61))
- [ ] Create a project template using dotnet CLI - `dotnet new template`
- [ ] Second template: The administration of the IdentityServer4 (without Asp.Net Core Identity) ([#79](https://github.com/skoruba/IdentityServer4.Admin/issues/79))
- [ ] User registration / Password reset
......@@ -264,6 +272,7 @@ It is possible to define the configuration according the client type - by defaul
- [ ] Manage profile
### 2.0.0:
- [ ] Add API:
- [ ] IdentityServer4
- [ ] Asp.Net Core Identity
......@@ -280,6 +289,9 @@ It is possible to define the configuration according the client type - by defaul
This repository is licensed under the terms of the [**MIT license**](LICENSE.md).
**NOTE**: This repository uses the source code from https://github.com/IdentityServer/IdentityServer4.Quickstart.UI which is under the terms of the
[**Apache License 2.0**](https://github.com/IdentityServer/IdentityServer4.Quickstart.UI/blob/master/LICENSE).
## Acknowledgements
This web application is based on these projects:
......@@ -304,7 +316,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
<!-- prettier-ignore-start -->
| [<img src="https://avatars3.githubusercontent.com/u/35664089?s=460&v=3" width="100px;"/><br /><sub> Jan Škoruba</sub>](https://github.com/skoruba) <br /> 💻 💬 📖 💡 🤔 | [<img src="https://avatars0.githubusercontent.com/u/6831144?s=460&v=3" width="100px;"/><br /><sub> Tomáš Hübelbauer</sub>](https://github.com/TomasHubelbauer) <br /> 💻 👀 📖 🤔 | [<img src="https://avatars0.githubusercontent.com/u/1004852?s=460&v=3" width="100px;"/><br /><sub>Michał Drzał </sub>](https://github.com/xmichaelx) <br />💻 👀 📖 💡 🤔 | [<img src="https://avatars0.githubusercontent.com/u/2261603?s=460&v=3" width="100px;"/><br /><sub>cerginio </sub>](https://github.com/cerginio) <br /> 💻 🐛 💡 🤔 | [<img src="https://avatars3.githubusercontent.com/u/13407080?s=460&v=3" width="100px;"/><br /><sub>Sven Dummis </sub>](https://github.com/svendu) <br /> 📖| [<img src="https://avatars1.githubusercontent.com/u/1687087?s=460&v=3" width="100px;"/><br /><sub>Seaear</sub>](https://github.com/Seaear) <br />🌍|
| :---: | :---: | :---: | :---: | :---: | :---: |
|[<img src="https://avatars1.githubusercontent.com/u/1150473?s=460&v=3" width="118px;"/><br /><sub>Rune Antonsen </sub>](https://github.com/ruant) <br />🐛|[<img src="https://avatars1.githubusercontent.com/u/5537607?s=460&v=3" width="118px;"/><br /><sub>Sindre Njøsen </sub>](https://github.com/Sindrenj) <br />💻|
|[<img src="https://avatars1.githubusercontent.com/u/1150473?s=460&v=3" width="118px;"/><br /><sub>Rune Antonsen </sub>](https://github.com/ruant) <br />🐛|[<img src="https://avatars1.githubusercontent.com/u/5537607?s=460&v=3" width="118px;"/><br /><sub>Sindre Njøsen </sub>](https://github.com/Sindrenj) <br />💻|[<img src="https://avatars1.githubusercontent.com/u/40323674?s=460&v=3" width="118px;"/><br /><sub>Alevtina Brown </sub>](https://github.com/alev7ina) <br />🌍|
<!-- prettier-ignore-end -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification.
......
Skoruba IdentityServer4 Admin
###############################
.. image:: https://raw.githubusercontent.com/skoruba/IdentityServer4.Admin/master/docs/Images/Skoruba.IdentityServer4.Admin-Logo-ReadMe.png
:align: center
The administration for the IdentityServer4 and Asp.Net Core Identity.
......@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>1.0.0-beta3</Version>
<Version>1.0.0-beta5</Version>
<Authors>Jan Škoruba</Authors>
<Description>Business Logic layer for the administration of the Asp.Net Core Identity and IdentityServer4</Description>
<PackageTags>IdentityServer4 Admin OpenIDConnect OAuth2 Identity</PackageTags>
......@@ -12,8 +12,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.1.3" />
<PackageReference Include="IdentityServer4.EntityFramework" Version="2.3.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
......
......@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>1.0.0-beta3</Version>
<Version>1.0.0-beta5</Version>
<Authors>Jan Škoruba</Authors>
<PackageTags>IdentityServer4 Admin OpenIDConnect OAuth2 Identity</PackageTags>
<Description>Shared Business Logic layer for the administration of the IdentityServer4 and Asp.Net Core Identity</Description>
......
......@@ -51,7 +51,8 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Constants
"client_credentials",
"authorization_code",
"hybrid",
"password"
"password",
"urn:ietf:params:oauth:grant-type:device_code"
};
return allowedGrantypes;
......
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
{
public class ApiResourcePropertiesDto
{
public int ApiResourcePropertyId { get; set; }
public int ApiResourceId { get; set; }
public string ApiResourceName { get; set; }
[Required]
public string Key { get; set; }
[Required]
public string Value { get; set; }
public List<ApiResourcePropertyDto> ApiResourceProperties { get; set; } = new List<ApiResourcePropertyDto>();
public int TotalCount { get; set; }
public int PageSize { get; set; }
}
}
namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
{
public class ApiResourcePropertyDto
{
public int Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
}
\ No newline at end of file
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Enums;
using Skoruba.IdentityServer4.Admin.BusinessLogic.Shared.Dtos.Common;
namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
{
public class ClientDto
{
public ClientDto()
{
AllowedScopes = new List<string>();
PostLogoutRedirectUris = new List<string>();
RedirectUris = new List<string>();
IdentityProviderRestrictions = new List<string>();
AllowedCorsOrigins = new List<string>();
AllowedGrantTypes = new List<string>();
Claims = new List<ClientClaimDto>();
ClientSecrets = new List<ClientSecretDto>();
public class ClientDto
{
public ClientDto()
{
AllowedScopes = new List<string>();
PostLogoutRedirectUris = new List<string>();
RedirectUris = new List<string>();
IdentityProviderRestrictions = new List<string>();
AllowedCorsOrigins = new List<string>();
AllowedGrantTypes = new List<string>();
Claims = new List<ClientClaimDto>();
ClientSecrets = new List<ClientSecretDto>();
Properties = new List<ClientPropertyDto>();
}
}
public ClientType ClientType { get; set; }
public int AbsoluteRefreshTokenLifetime { get; set; } = 2592000;
public int AccessTokenLifetime { get; set; } = 3600;
public int AbsoluteRefreshTokenLifetime { get; set; } = 2592000;
public int AccessTokenLifetime { get; set; } = 3600;
public int? ConsentLifetime { get; set; }
public int? ConsentLifetime { get; set; }
public int AccessTokenType { get; set; }
public List<SelectItem> AccessTokenTypes { get; set; }
public List<SelectItem> AccessTokenTypes { get; set; }
public bool AllowAccessTokensViaBrowser { get; set; }
public bool AllowOfflineAccess { get; set; }
public bool AllowPlainTextPkce { get; set; }
public bool AllowRememberConsent { get; set; } = true;
public bool AlwaysIncludeUserClaimsInIdToken { get; set; }
public bool AlwaysSendClientClaims { get; set; }
public int AuthorizationCodeLifetime { get; set; } = 300;
public bool AllowAccessTokensViaBrowser { get; set; }
public bool AllowOfflineAccess { get; set; }
public bool AllowPlainTextPkce { get; set; }
public bool AllowRememberConsent { get; set; } = true;
public bool AlwaysIncludeUserClaimsInIdToken { get; set; }
public bool AlwaysSendClientClaims { get; set; }
public int AuthorizationCodeLifetime { get; set; } = 300;
public string FrontChannelLogoutUri { get; set; }
public string FrontChannelLogoutUri { get; set; }
public bool FrontChannelLogoutSessionRequired { get; set; } = true;
public string BackChannelLogoutUri { get; set; }
public bool BackChannelLogoutSessionRequired { get; set; } = true;
......@@ -51,16 +52,16 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
public string ClientUri { get; set; }
public string Description { get; set; }
public string Description { get; set; }
public bool Enabled { get; set; } = true;
public bool EnableLocalLogin { get; set; } = true;
public int Id { get; set; }
public int IdentityTokenLifetime { get; set; } = 300;
public bool IncludeJwtId { get; set; }
public string LogoUri { get; set; }
public string ClientClaimsPrefix { get; set; } = "client_";
public string LogoUri { get; set; }
public string ClientClaimsPrefix { get; set; } = "client_";
public string PairWiseSubjectSalt { get; set; }
......@@ -69,38 +70,47 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
public List<SelectItem> ProtocolTypes { get; set; }
public int RefreshTokenExpiration { get; set; } = 1;
public List<SelectItem> RefreshTokenExpirations { get; set; }
public List<SelectItem> RefreshTokenExpirations { get; set; }
public int RefreshTokenUsage { get; set; } = 1;
public List<SelectItem> RefreshTokenUsages { get; set; }
public int RefreshTokenUsage { get; set; } = 1;
public List<SelectItem> RefreshTokenUsages { get; set; }
public int SlidingRefreshTokenLifetime { get; set; } = 1296000;
public int SlidingRefreshTokenLifetime { get; set; } = 1296000;
public bool RequireClientSecret { get; set; } = true;
public bool RequireConsent { get; set; } = true;
public bool RequirePkce { get; set; }
public bool UpdateAccessTokenClaimsOnRefresh { get; set; }
public bool RequireClientSecret { get; set; } = true;
public bool RequireConsent { get; set; } = true;
public bool RequirePkce { get; set; }
public bool UpdateAccessTokenClaimsOnRefresh { get; set; }
public List<string> PostLogoutRedirectUris { get; set; }
public string PostLogoutRedirectUrisItems { get; set; }
public List<string> PostLogoutRedirectUris { get; set; }
public string PostLogoutRedirectUrisItems { get; set; }
public List<string> IdentityProviderRestrictions { get; set; }
public string IdentityProviderRestrictionsItems { get; set; }
public List<string> IdentityProviderRestrictions { get; set; }
public string IdentityProviderRestrictionsItems { get; set; }
public List<string> RedirectUris { get; set; }
public string RedirectUrisItems { get; set; }
public List<string> RedirectUris { get; set; }
public string RedirectUrisItems { get; set; }
public List<string> AllowedCorsOrigins { get; set; }
public string AllowedCorsOriginsItems { get; set; }
public List<string> AllowedCorsOrigins { get; set; }
public string AllowedCorsOriginsItems { get; set; }
public List<string> AllowedGrantTypes { get; set; }
public string AllowedGrantTypesItems { get; set; }
public List<string> AllowedGrantTypes { get; set; }
public string AllowedGrantTypesItems { get; set; }
public List<string> AllowedScopes { get; set; }
public string AllowedScopesItems { get; set; }
public List<string> AllowedScopes { get; set; }
public string AllowedScopesItems { get; set; }
public List<ClientClaimDto> Claims { get; set; }
public List<ClientSecretDto> ClientSecrets { get; set; }
public List<ClientClaimDto> Claims { get; set; }
public List<ClientSecretDto> ClientSecrets { get; set; }
public List<ClientPropertyDto> Properties { get; set; }
}
public DateTime? Updated { get; set; }
public DateTime? LastAccessed { get; set; }
public int? UserSsoLifetime { get; set; }
public string UserCodeType { get; set; }
public int DeviceCodeLifetime { get; set; } = 300;
public bool NonEditable { get; set; }
}
}
\ No newline at end of file
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
{
public class IdentityResourcePropertiesDto
{
public int IdentityResourcePropertyId { get; set; }
public int IdentityResourceId { get; set; }
public string IdentityResourceName { get; set; }
[Required]
public string Key { get; set; }
[Required]
public string Value { get; set; }
public List<IdentityResourcePropertyDto> IdentityResourceProperties { get; set; } = new List<IdentityResourcePropertyDto>();
public int TotalCount { get; set; }
public int PageSize { get; set; }
}
}
namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Dtos.Configuration
{
public class IdentityResourcePropertyDto
{
public int Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
}
\ No newline at end of file
......@@ -7,6 +7,7 @@
WebHybrid = 2,
Spa = 3,
Native = 4,
Machine = 5
Machine = 5,
Device = 6
}
}
\ No newline at end of file
......@@ -35,6 +35,14 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
CreateMap<ApiSecret, ApiSecretDto>(MemberList.Destination)
.ForMember(dest => dest.Type, opt => opt.Condition(srs => srs != null));
CreateMap<ApiResourceProperty, ApiResourcePropertyDto>(MemberList.Destination)
.ReverseMap();
CreateMap<ApiResourceProperty, ApiResourcePropertiesDto>(MemberList.Destination)
.ForMember(dest => dest.Key, opt => opt.Condition(srs => srs != null))
.ForMember(x => x.ApiResourcePropertyId, opt => opt.MapFrom(x => x.Id))
.ForMember(x => x.ApiResourceId, opt => opt.MapFrom(x => x.ApiResource.Id));
//PagedLists
CreateMap<PagedList<ApiResource>, ApiResourcesDto>(MemberList.Destination)
.ForMember(x => x.ApiResources, opt => opt.MapFrom(src => src.Data));
......@@ -45,13 +53,16 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
CreateMap<PagedList<ApiSecret>, ApiSecretsDto>(MemberList.Destination)
.ForMember(x => x.ApiSecrets, opt => opt.MapFrom(src => src.Data));
CreateMap<PagedList<ApiResourceProperty>, ApiResourcePropertiesDto>(MemberList.Destination)
.ForMember(x => x.ApiResourceProperties, opt => opt.MapFrom(src => src.Data));
// model to entity
CreateMap<ApiResourceDto, ApiResource>(MemberList.Source)
.ForMember(x => x.UserClaims, opts => opts.MapFrom(src => src.UserClaims.Select(x => new ApiResourceClaim { Type = x })));
CreateMap<ApiSecretsDto, ApiSecret>(MemberList.Source)
.ForMember(x => x.ApiResource, opts => opts.MapFrom(src => new ApiResource() {Id = src.ApiResourceId}))
.ForMember(x=> x.Id, opt => opt.MapFrom(src => src.ApiSecretId));
.ForMember(x => x.ApiResource, opts => opts.MapFrom(src => new ApiResource() { Id = src.ApiResourceId }))
.ForMember(x => x.Id, opt => opt.MapFrom(src => src.ApiSecretId));
CreateMap<ApiScopesDto, ApiScope>(MemberList.Source)
.ForMember(x => x.UserClaims, opts => opts.MapFrom(src => src.UserClaims.Select(x => new ApiScopeClaim { Type = x })))
......@@ -59,6 +70,10 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
CreateMap<ApiScopeDto, ApiScope>(MemberList.Source)
.ForMember(x => x.UserClaims, opts => opts.MapFrom(src => src.UserClaims.Select(x => new ApiScopeClaim { Type = x })));
CreateMap<ApiResourcePropertiesDto, ApiResourceProperty>(MemberList.Source)
.ForMember(x => x.ApiResource, dto => dto.MapFrom(src => new ApiResource() { Id = src.ApiResourceId }))
.ForMember(x => x.Id, opt => opt.MapFrom(src => src.ApiResourcePropertyId));
}
}
}
......@@ -5,59 +5,74 @@ using Skoruba.IdentityServer4.Admin.BusinessLogic.Shared.Dtos.Common;
namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
{
public static class ApiResourceMappers
{
static ApiResourceMappers()
{
Mapper = new MapperConfiguration(cfg => cfg.AddProfile<ApiResourceMapperProfile>())
.CreateMapper();
}
internal static IMapper Mapper { get; }
public static ApiResourceDto ToModel(this ApiResource resource)
{
return resource == null ? null : Mapper.Map<ApiResourceDto>(resource);
}
public static ApiResourcesDto ToModel(this PagedList<ApiResource> resources)
{
return resources == null ? null : Mapper.Map<ApiResourcesDto>(resources);
}
public static ApiSecretsDto ToModel(this PagedList<ApiSecret> secrets)
{
return secrets == null ? null : Mapper.Map<ApiSecretsDto>(secrets);
}
public static class ApiResourceMappers
{
static ApiResourceMappers()
{
Mapper = new MapperConfiguration(cfg => cfg.AddProfile<ApiResourceMapperProfile>())
.CreateMapper();
}
internal static IMapper Mapper { get; }
public static ApiResourceDto ToModel(this ApiResource resource)
{
return resource == null ? null : Mapper.Map<ApiResourceDto>(resource);
}
public static ApiResourcesDto ToModel(this PagedList<ApiResource> resources)
{
return resources == null ? null : Mapper.Map<ApiResourcesDto>(resources);
}
public static ApiResourcePropertiesDto ToModel(this PagedList<ApiResourceProperty> apiResourceProperties)
{
return Mapper.Map<ApiResourcePropertiesDto>(apiResourceProperties);
}
public static ApiResourcePropertiesDto ToModel(this ApiResourceProperty apiResourceProperty)
{
return Mapper.Map<ApiResourcePropertiesDto>(apiResourceProperty);
}
public static ApiSecretsDto ToModel(this PagedList<ApiSecret> secrets)
{
return secrets == null ? null : Mapper.Map<ApiSecretsDto>(secrets);
}
public static ApiScopesDto ToModel(this PagedList<ApiScope> scopes)
{
return scopes == null ? null : Mapper.Map<ApiScopesDto>(scopes);
}
public static ApiScopesDto ToModel(this ApiScope resource)
{
return resource == null ? null : Mapper.Map<ApiScopesDto>(resource);
}
public static ApiSecretsDto ToModel(this ApiSecret resource)
{
return resource == null ? null : Mapper.Map<ApiSecretsDto>(resource);
}
public static ApiResource ToEntity(this ApiResourceDto resource)
{
return resource == null ? null : Mapper.Map<ApiResource>(resource);
}
public static ApiSecret ToEntity(this ApiSecretsDto resource)
{
return resource == null ? null : Mapper.Map<ApiSecret>(resource);
}
public static ApiScope ToEntity(this ApiScopesDto resource)
{
return resource == null ? null : Mapper.Map<ApiScope>(resource);
}
}
{
return scopes == null ? null : Mapper.Map<ApiScopesDto>(scopes);
}
public static ApiScopesDto ToModel(this ApiScope resource)
{
return resource == null ? null : Mapper.Map<ApiScopesDto>(resource);
}
public static ApiSecretsDto ToModel(this ApiSecret resource)
{
return resource == null ? null : Mapper.Map<ApiSecretsDto>(resource);
}
public static ApiResource ToEntity(this ApiResourceDto resource)
{
return resource == null ? null : Mapper.Map<ApiResource>(resource);
}
public static ApiSecret ToEntity(this ApiSecretsDto resource)
{
return resource == null ? null : Mapper.Map<ApiSecret>(resource);
}
public static ApiScope ToEntity(this ApiScopesDto resource)
{
return resource == null ? null : Mapper.Map<ApiScope>(resource);
}
public static ApiResourceProperty ToEntity(this ApiResourcePropertiesDto apiResourceProperties)
{
return Mapper.Map<ApiResourceProperty>(apiResourceProperties);
}
}
}
\ No newline at end of file
......@@ -19,13 +19,28 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
CreateMap<IdentityResource, IdentityResourceDto>(MemberList.Destination)
.ForMember(x => x.UserClaims, opt => opt.MapFrom(src => src.UserClaims.Select(x => x.Type)));
CreateMap<IdentityResourceProperty, IdentityResourcePropertyDto>(MemberList.Destination)
.ReverseMap();
CreateMap<IdentityResourceProperty, IdentityResourcePropertiesDto>(MemberList.Destination)
.ForMember(dest => dest.Key, opt => opt.Condition(srs => srs != null))
.ForMember(x => x.IdentityResourcePropertyId, opt => opt.MapFrom(x => x.Id))
.ForMember(x => x.IdentityResourceId, opt => opt.MapFrom(x => x.IdentityResource.Id));
CreateMap<PagedList<IdentityResource>, IdentityResourcesDto>(MemberList.Destination)
.ForMember(x => x.IdentityResources,
opt => opt.MapFrom(src => src.Data));
CreateMap<PagedList<IdentityResourceProperty>, IdentityResourcePropertiesDto>(MemberList.Destination)
.ForMember(x => x.IdentityResourceProperties, opt => opt.MapFrom(src => src.Data));
// model to entity
CreateMap<IdentityResourceDto, IdentityResource>(MemberList.Source)
.ForMember(x => x.UserClaims, opts => opts.MapFrom(src => src.UserClaims.Select(x => new IdentityClaim { Type = x })));
CreateMap<IdentityResourcePropertiesDto, IdentityResourceProperty>(MemberList.Source)
.ForMember(x => x.IdentityResource, dto => dto.MapFrom(src => new IdentityResource() { Id = src.IdentityResourceId }))
.ForMember(x => x.Id, opt => opt.MapFrom(src => src.IdentityResourcePropertyId));
}
}
}
\ No newline at end of file
......@@ -17,10 +17,10 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
internal static IMapper Mapper { get; }
public static IdentityResourceDto ToModel(this IdentityResource resource)
{
return resource == null ? null : Mapper.Map<IdentityResourceDto>(resource);
}
public static IdentityResourceDto ToModel(this IdentityResource resource)
{
return resource == null ? null : Mapper.Map<IdentityResourceDto>(resource);
}
public static IdentityResourcesDto ToModel(this PagedList<IdentityResource> resource)
{
......@@ -28,18 +28,33 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Mappers
}
public static List<IdentityResourceDto> ToModel(this List<IdentityResource> resource)
{
return resource == null ? null : Mapper.Map<List<IdentityResourceDto>>(resource);
}
public static IdentityResource ToEntity(this IdentityResourceDto resource)
{
return resource == null ? null : Mapper.Map<IdentityResource>(resource);
}
public static List<IdentityResource> ToEntity(this List<IdentityResourceDto> resource)
{
return resource == null ? null : Mapper.Map< List<IdentityResource>>(resource);
}
}
{
return resource == null ? null : Mapper.Map<List<IdentityResourceDto>>(resource);
}
public static IdentityResource ToEntity(this IdentityResourceDto resource)
{
return resource == null ? null : Mapper.Map<IdentityResource>(resource);
}
public static IdentityResourcePropertiesDto ToModel(this PagedList<IdentityResourceProperty> identityResourceProperties)
{
return Mapper.Map<IdentityResourcePropertiesDto>(identityResourceProperties);
}
public static IdentityResourcePropertiesDto ToModel(this IdentityResourceProperty identityResourceProperty)
{
return Mapper.Map<IdentityResourcePropertiesDto>(identityResourceProperty);
}
public static List<IdentityResource> ToEntity(this List<IdentityResourceDto> resource)
{
return resource == null ? null : Mapper.Map<List<IdentityResource>>(resource);
}
public static IdentityResourceProperty ToEntity(this IdentityResourcePropertiesDto identityResourceProperties)
{
return Mapper.Map<IdentityResourceProperty>(identityResourceProperties);
}
}
}
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
......@@ -47,6 +48,46 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Repositories
.SingleOrDefaultAsync();
}
public async Task<PagedList<ApiResourceProperty>> GetApiResourcePropertiesAsync(int apiResourceId, int page = 1, int pageSize = 10)
{
var pagedList = new PagedList<ApiResourceProperty>();
var properties = await _dbContext.ApiResourceProperties.Where(x => x.ApiResource.Id == apiResourceId).PageBy(x => x.Id, page, pageSize)
.ToListAsync();
pagedList.Data.AddRange(properties);
pagedList.TotalCount = await _dbContext.ApiResourceProperties.Where(x => x.ApiResource.Id == apiResourceId).CountAsync();
pagedList.PageSize = pageSize;
return pagedList;
}
public Task<ApiResourceProperty> GetApiResourcePropertyAsync(int apiResourcePropertyId)
{
return _dbContext.ApiResourceProperties
.Include(x => x.ApiResource)
.Where(x => x.Id == apiResourcePropertyId)
.SingleOrDefaultAsync();
}
public async Task<int> AddApiResourcePropertyAsync(int apiResourceId, ApiResourceProperty apiResourceProperty)
{
var apiResource = await _dbContext.ApiResources.Where(x => x.Id == apiResourceId).SingleOrDefaultAsync();
apiResourceProperty.ApiResource = apiResource;
await _dbContext.ApiResourceProperties.AddAsync(apiResourceProperty);
return await AutoSaveChangesAsync();
}
public async Task<int> DeleteApiResourcePropertyAsync(ApiResourceProperty apiResourceProperty)
{
var propertyToDelete = await _dbContext.ApiResourceProperties.Where(x => x.Id == apiResourceProperty.Id).SingleOrDefaultAsync();
_dbContext.ApiResourceProperties.Remove(propertyToDelete);
return await AutoSaveChangesAsync();
}
public async Task<bool> CanInsertApiResourceAsync(ApiResource apiResource)
{
if (apiResource.Id == 0)
......@@ -61,6 +102,13 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Repositories
}
}
public async Task<bool> CanInsertApiResourcePropertyAsync(ApiResourceProperty apiResourceProperty)
{
var existsWithSameName = await _dbContext.ApiResourceProperties.Where(x => x.Key == apiResourceProperty.Key
&& x.ApiResource.Id == apiResourceProperty.ApiResourceId).SingleOrDefaultAsync();
return existsWithSameName == null;
}
public async Task<bool> CanInsertApiScopeAsync(ApiScope apiScope)
{
if (apiScope.Id == 0)
......
......@@ -30,7 +30,7 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Repositories
Expression<Func<IdentityResource, bool>> searchCondition = x => x.Name.Contains(search);
var identityResources = await _dbContext.IdentityResources.WhereIf(!string.IsNullOrEmpty(search), searchCondition).PageBy(x=> x.Name, page, pageSize).ToListAsync();
var identityResources = await _dbContext.IdentityResources.WhereIf(!string.IsNullOrEmpty(search), searchCondition).PageBy(x => x.Name, page, pageSize).ToListAsync();
pagedList.Data.AddRange(identityResources);
pagedList.TotalCount = await _dbContext.IdentityResources.WhereIf(!string.IsNullOrEmpty(search), searchCondition).CountAsync();
......@@ -47,6 +47,53 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Repositories
.SingleOrDefaultAsync();
}
public async Task<PagedList<IdentityResourceProperty>> GetIdentityResourcePropertiesAsync(int identityResourceId, int page = 1, int pageSize = 10)
{
var pagedList = new PagedList<IdentityResourceProperty>();
var properties = await _dbContext.IdentityResourceProperties.Where(x => x.IdentityResource.Id == identityResourceId).PageBy(x => x.Id, page, pageSize)
.ToListAsync();
pagedList.Data.AddRange(properties);
pagedList.TotalCount = await _dbContext.IdentityResourceProperties.Where(x => x.IdentityResource.Id == identityResourceId).CountAsync();
pagedList.PageSize = pageSize;
return pagedList;
}
public Task<IdentityResourceProperty> GetIdentityResourcePropertyAsync(int identityResourcePropertyId)
{
return _dbContext.IdentityResourceProperties
.Include(x => x.IdentityResource)
.Where(x => x.Id == identityResourcePropertyId)
.SingleOrDefaultAsync();
}
public async Task<int> AddIdentityResourcePropertyAsync(int identityResourceId, IdentityResourceProperty identityResourceProperty)
{
var identityResource = await _dbContext.IdentityResources.Where(x => x.Id == identityResourceId).SingleOrDefaultAsync();
identityResourceProperty.IdentityResource = identityResource;
await _dbContext.IdentityResourceProperties.AddAsync(identityResourceProperty);
return await AutoSaveChangesAsync();
}
public async Task<int> DeleteIdentityResourcePropertyAsync(IdentityResourceProperty identityResourceProperty)
{
var propertyToDelete = await _dbContext.IdentityResourceProperties.Where(x => x.Id == identityResourceProperty.Id).SingleOrDefaultAsync();
_dbContext.IdentityResourceProperties.Remove(propertyToDelete);
return await AutoSaveChangesAsync();
}
public async Task<bool> CanInsertIdentityResourcePropertyAsync(IdentityResourceProperty identityResourceProperty)
{
var existsWithSameName = await _dbContext.IdentityResourceProperties.Where(x => x.Key == identityResourceProperty.Key
&& x.IdentityResource.Id == identityResourceProperty.IdentityResourceId).SingleOrDefaultAsync();
return existsWithSameName == null;
}
/// <summary>
/// Add new identity resource
/// </summary>
......
......@@ -13,6 +13,16 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Repositories.Interfaces
Task<ApiResource> GetApiResourceAsync(int apiResourceId);
Task<PagedList<ApiResourceProperty>> GetApiResourcePropertiesAsync(int apiResourceId, int page = 1, int pageSize = 10);
Task<ApiResourceProperty> GetApiResourcePropertyAsync(int apiResourcePropertyId);
Task<int> AddApiResourcePropertyAsync(int apiResourceId, ApiResourceProperty apiResourceProperty);
Task<int> DeleteApiResourcePropertyAsync(ApiResourceProperty apiResourceProperty);
Task<bool> CanInsertApiResourcePropertyAsync(ApiResourceProperty apiResourceProperty);
Task<int> AddApiResourceAsync(ApiResource apiResource);
Task<int> UpdateApiResourceAsync(ApiResource apiResource);
......
......@@ -21,6 +21,18 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Repositories.Interfaces
Task<int> DeleteIdentityResourceAsync(IdentityResource identityResource);
Task<bool> CanInsertIdentityResourcePropertyAsync(IdentityResourceProperty identityResourceProperty);
Task<PagedList<IdentityResourceProperty>> GetIdentityResourcePropertiesAsync(int identityResourceId,
int page = 1, int pageSize = 10);
Task<IdentityResourceProperty> GetIdentityResourcePropertyAsync(int identityResourcePropertyId);
Task<int> AddIdentityResourcePropertyAsync(int identityResourceId,
IdentityResourceProperty identityResourceProperty);
Task<int> DeleteIdentityResourcePropertyAsync(IdentityResourceProperty identityResourceProperty);
Task<int> SaveAllChangesAsync();
}
}
\ No newline at end of file
......@@ -87,6 +87,33 @@ namespace Skoruba.IdentityServer4.Admin.BusinessLogic.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Api Resource Property with id {0} doesn&apos;t exist.
/// </summary>
internal static string ApiResourcePropertyDoesNotExist {
get {
return ResourceManager.GetString("ApiResourcePropertyDoesNotExist", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Api Resource Property already exists.
/// </summary>
internal static string ApiResourcePropertyExistsKey {
get {
return ResourceManager.GetString("ApiResourcePropertyExistsKey", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Api Resource Property with key ({0}) already exists.
/// </summary>
internal static string ApiResourcePropertyExistsValue {
get {
return ResourceManager.GetString("ApiResourcePropertyExistsValue", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Api Scope with id {0} doesn&apos;t exist.
/// </summary>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment