committed by
GitHub
665 changed files with 129365 additions and 1058 deletions
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\cloud-tencent\LINGYUN.Abp.Tencent.QQ\LINGYUN.Abp.Tencent.QQ.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace LINGYUN.Abp.Authentication.QQ; |
||||
|
|
||||
|
public static class AbpAuthenticationQQConsts |
||||
|
{ |
||||
|
public static string AuthenticationScheme { get; set; } = "QQ Connect"; |
||||
|
public static string DisplayName { get; set; } = "QQ Connect"; |
||||
|
public static string CallbackPath { get; set; } = "/signin-callback"; |
||||
|
} |
||||
@ -1,14 +1,12 @@ |
|||||
using LINGYUN.Abp.Tencent.QQ; |
using LINGYUN.Abp.Tencent.QQ; |
||||
using Microsoft.AspNetCore.Authentication; |
using Microsoft.AspNetCore.Authentication; |
||||
using Microsoft.Extensions.DependencyInjection; |
using Microsoft.Extensions.DependencyInjection; |
||||
using Volo.Abp.IdentityServer; |
|
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Modularity; |
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.QQ; |
namespace LINGYUN.Abp.Authentication.QQ; |
||||
|
|
||||
[DependsOn(typeof(AbpTencentQQModule))] |
[DependsOn(typeof(AbpTencentQQModule))] |
||||
[DependsOn(typeof(AbpIdentityServerDomainModule))] |
public class AbpAuthenticationQQModule : AbpModule |
||||
public class AbpIdentityServerQQModule : AbpModule |
|
||||
{ |
{ |
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
{ |
{ |
||||
@ -1,4 +1,4 @@ |
|||||
namespace LINGYUN.Abp.WeChat.Security.Claims |
namespace LINGYUN.Abp.Authentication.QQ |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// QQ互联身份类型,可以像 <see cref="Volo.Abp.Security.Claims.AbpClaimTypes"/> 自行配置
|
/// QQ互联身份类型,可以像 <see cref="Volo.Abp.Security.Claims.AbpClaimTypes"/> 自行配置
|
||||
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="$(MicrosoftPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,67 @@ |
|||||
|
using LINGYUN.Abp.WeChat; |
||||
|
using LINGYUN.Abp.WeChat.Official; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Authentication.WeChat; |
||||
|
|
||||
|
public static class AbpAuthenticationWeChatConsts |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 微信个人信息标识
|
||||
|
/// </summary>
|
||||
|
public static string ProfileKey => AbpWeChatGlobalConsts.ProfileKey; |
||||
|
/// <summary>
|
||||
|
/// 微信提供者标识
|
||||
|
/// </summary>
|
||||
|
public static string ProviderKey => AbpWeChatOfficialConsts.ProviderName; |
||||
|
/// <summary>
|
||||
|
/// 微信提供者显示名称
|
||||
|
/// </summary>
|
||||
|
public static string DisplayName => AbpWeChatGlobalConsts.DisplayName; |
||||
|
/// <summary>
|
||||
|
/// 回调地址
|
||||
|
/// </summary>
|
||||
|
public static string CallbackPath { get; set; } = "/signin-callback"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 微信客户端外的网页登录
|
||||
|
/// </summary>
|
||||
|
public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 微信客户端内的网页登录
|
||||
|
/// </summary>
|
||||
|
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 用户允许授权后通过返回的code换取access_token地址
|
||||
|
/// </summary>
|
||||
|
public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token"; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 使用access_token获取用户个人信息地址
|
||||
|
/// </summary>
|
||||
|
public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; |
||||
|
/// <summary>
|
||||
|
/// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
|
||||
|
/// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
|
||||
|
/// <br />
|
||||
|
/// <br />
|
||||
|
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
|
||||
|
/// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
|
||||
|
/// </remarks>
|
||||
|
public const string UserInfoScope = "snsapi_userinfo"; |
||||
|
/// <summary>
|
||||
|
/// 不弹出授权页面,直接跳转,只能获取用户openid
|
||||
|
/// <br />
|
||||
|
/// <br />
|
||||
|
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
||||
|
/// </summary>
|
||||
|
/// <remarks>
|
||||
|
/// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
|
||||
|
/// 用户感知的就是直接进入了回调页(往往是业务页面)
|
||||
|
/// </remarks>
|
||||
|
public const string LoginScope = "snsapi_login"; |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using LINGYUN.Abp.WeChat.Official; |
||||
|
using Microsoft.AspNetCore.Authentication; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Authentication.WeChat; |
||||
|
|
||||
|
[DependsOn(typeof(AbpWeChatOfficialModule))] |
||||
|
public class AbpAuthenticationWeChatModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services |
||||
|
.AddAuthentication() |
||||
|
.AddWeChat(); |
||||
|
} |
||||
|
} |
||||
6
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs → aspnet-core/modules/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs
6
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs → aspnet-core/modules/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthHandler.cs
16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs → aspnet-core/modules/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs
16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs → aspnet-core/modules/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialOAuthOptions.cs
0
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs → aspnet-core/modules/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs
0
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs → aspnet-core/modules/authentication/LINGYUN.Abp.Authentication.WeChat/Microsoft/AspNetCore/Authentication/WeChat/Official/WeChatOfficialStateCacheItem.cs
@ -1,5 +1,5 @@ |
|||||
using LINGYUN.Abp.IdentityServer.WeChat.Official; |
using Microsoft.AspNetCore.Http; |
||||
|
|
||||
namespace Microsoft.AspNetCore.Builder |
namespace Microsoft.AspNetCore.Builder |
||||
{ |
{ |
||||
public static class IdentityServerApplicationBuilderExtensions |
public static class IdentityServerApplicationBuilderExtensions |
||||
@ -1,12 +1,11 @@ |
|||||
using LINGYUN.Abp.WeChat.Official; |
using LINGYUN.Abp.WeChat.Official; |
||||
using Microsoft.AspNetCore.Http; |
|
||||
using System; |
using System; |
||||
using System.Collections; |
using System.Collections; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
using Volo.Abp; |
using Volo.Abp; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
namespace Microsoft.AspNetCore.Http |
||||
{ |
{ |
||||
public class WeChatOfficialSignatureMiddleware : IMiddleware, ITransientDependency |
public class WeChatOfficialSignatureMiddleware : IMiddleware, ITransientDependency |
||||
{ |
{ |
||||
@ -1,10 +1,11 @@ |
|||||
using System.Threading.Tasks; |
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
using Volo.Abp.BackgroundWorkers; |
using Volo.Abp.BackgroundWorkers; |
||||
|
|
||||
namespace LINGYUN.Abp.BackgroundWorkers.Hangfire |
namespace LINGYUN.Abp.BackgroundWorkers.Hangfire |
||||
{ |
{ |
||||
public interface IHangfireBackgroundWorkerAdapter : IBackgroundWorker |
public interface IHangfireBackgroundWorkerAdapter : IBackgroundWorker |
||||
{ |
{ |
||||
Task ExecuteAsync(); |
Task ExecuteAsync(CancellationToken cancellationToken = default); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,40 @@ |
|||||
|
# LINGYUN.Abp.Wrapper |
||||
|
|
||||
|
包装器模块 |
||||
|
|
||||
|
## 配置使用 |
||||
|
|
||||
|
```csharp |
||||
|
[DependsOn(typeof(AbpWrapperModule))] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpWrapperOptions>(options => |
||||
|
{ |
||||
|
// 启用包装器 |
||||
|
options.IsEnabled = true; |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
``` |
||||
|
## 配置项说明 |
||||
|
|
||||
|
* AbpWrapperOptions.IsEnabled 是否包装返回结果,默认: false |
||||
|
* AbpWrapperOptions.CodeWithUnhandled 出现未处理异常时的返回错误代码,默认500 |
||||
|
* AbpWrapperOptions.CodeWithSuccess 处理成功返回代码,默认0 |
||||
|
* AbpWrapperOptions.ErrorWithEmptyResult 请求资源时,如果资源为空是否返回错误消息,默认false |
||||
|
* AbpWrapperOptions.HttpStatusCode 包装后的Http响应代码, 默认: 200 |
||||
|
* AbpWrapperOptions.CodeWithEmptyResult 当返回空对象时返回错误代码,默认: 404 |
||||
|
* AbpWrapperOptions.MessageWithEmptyResult 当返回空对象时返回错误消息, 默认: Not Found |
||||
|
|
||||
|
* AbpWrapperOptions.IgnorePrefixUrls 指定哪些Url开头的地址不需要处理 |
||||
|
* AbpWrapperOptions.IgnoreNamespaces 指定哪些命名空间开头不需要处理 |
||||
|
* AbpWrapperOptions.IgnoreControllers 指定哪些控制器不需要处理 |
||||
|
* AbpWrapperOptions.IgnoreReturnTypes 指定哪些返回结果类型不需要处理 |
||||
|
* AbpWrapperOptions.IgnoreExceptions 指定哪些异常类型不需要处理 |
||||
|
* AbpWrapperOptions.IgnoredInterfaces 指定哪些接口不需要处理(默认实现**IWrapDisabled**接口不进行处理) |
||||
|
|
||||
|
|
||||
|
## 其他 |
||||
|
|
||||
@ -1,8 +0,0 @@ |
|||||
namespace LINGYUN.Abp.IdentityServer.QQ; |
|
||||
|
|
||||
public static class AbpIdentityServerQQConsts |
|
||||
{ |
|
||||
public static string AuthenticationScheme { get; set; } = "QQ Connect"; |
|
||||
public static string DisplayName { get; set; } = "QQ Connect"; |
|
||||
public static string CallbackPath { get; set; } = "/signin-qq"; |
|
||||
} |
|
||||
@ -1,26 +0,0 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
|
||||
|
|
||||
<Import Project="..\..\..\common.props" /> |
|
||||
<Import Project="..\..\..\configureawait.props" /> |
|
||||
|
|
||||
<PropertyGroup> |
|
||||
<TargetFramework>net6.0</TargetFramework> |
|
||||
<RootNamespace /> |
|
||||
</PropertyGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\WeChat\Localization\en.json" /> |
|
||||
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\WeChat\Localization\zh-Hans.json" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="$(VoloAbpPackageVersion)" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj" /> |
|
||||
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj" /> |
|
||||
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
</Project> |
|
||||
@ -1,56 +0,0 @@ |
|||||
using LINGYUN.Abp.Identity.WeChat; |
|
||||
using LINGYUN.Abp.IdentityServer.WeChat.MiniProgram; |
|
||||
using LINGYUN.Abp.IdentityServer.WeChat.Official; |
|
||||
using LINGYUN.Abp.WeChat.MiniProgram; |
|
||||
using LINGYUN.Abp.WeChat.Official; |
|
||||
using Microsoft.AspNetCore.Authentication; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Volo.Abp.IdentityServer; |
|
||||
using Volo.Abp.IdentityServer.Localization; |
|
||||
using Volo.Abp.Localization; |
|
||||
using Volo.Abp.Modularity; |
|
||||
using Volo.Abp.VirtualFileSystem; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat |
|
||||
{ |
|
||||
[DependsOn( |
|
||||
typeof(AbpWeChatOfficialModule), |
|
||||
typeof(AbpWeChatMiniProgramModule), |
|
||||
typeof(AbpIdentityWeChatModule), |
|
||||
typeof(AbpIdentityServerDomainModule))] |
|
||||
public class AbpIdentityServerWeChatModule : AbpModule |
|
||||
{ |
|
||||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|
||||
{ |
|
||||
var configuration = context.Services.GetConfiguration(); |
|
||||
|
|
||||
PreConfigure<IIdentityServerBuilder>(builder => |
|
||||
{ |
|
||||
builder.AddProfileService<WeChatMiniProgramProfileService>(); |
|
||||
|
|
||||
// TODO: 两个类型不通用配置项,不然只需要一个
|
|
||||
builder.AddExtensionGrantValidator<WeChatMiniProgramGrantValidator>(); |
|
||||
builder.AddExtensionGrantValidator<WeChatOfficialGrantValidator>(); |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
public override void ConfigureServices(ServiceConfigurationContext context) |
|
||||
{ |
|
||||
Configure<AbpVirtualFileSystemOptions>(options => |
|
||||
{ |
|
||||
options.FileSets.AddEmbedded<AbpIdentityServerWeChatModule>(); |
|
||||
}); |
|
||||
|
|
||||
Configure<AbpLocalizationOptions>(options => |
|
||||
{ |
|
||||
options.Resources |
|
||||
.Get<AbpIdentityServerResource>() |
|
||||
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/WeChat/Localization"); |
|
||||
}); |
|
||||
|
|
||||
context.Services |
|
||||
.AddAuthentication() |
|
||||
.AddWeChat(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,75 +0,0 @@ |
|||||
using IdentityServer4.Models; |
|
||||
using IdentityServer4.Services; |
|
||||
using IdentityServer4.Validation; |
|
||||
using LINGYUN.Abp.WeChat.Localization; |
|
||||
using LINGYUN.Abp.WeChat.MiniProgram; |
|
||||
using LINGYUN.Abp.WeChat.MiniProgram.Features; |
|
||||
using LINGYUN.Abp.WeChat.OpenId; |
|
||||
using Microsoft.AspNetCore.Identity; |
|
||||
using Microsoft.Extensions.Localization; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Features; |
|
||||
using Volo.Abp.Identity; |
|
||||
using Volo.Abp.IdentityServer.Localization; |
|
||||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 对于小程序绑定用户的扩展授权验证器
|
|
||||
/// </summary>
|
|
||||
public class WeChatMiniProgramGrantValidator : WeChatGrantValidator |
|
||||
{ |
|
||||
public override string GrantType => AbpWeChatMiniProgramConsts.GrantType; |
|
||||
|
|
||||
public override string LoginProvider => AbpWeChatMiniProgramConsts.ProviderName; |
|
||||
|
|
||||
public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod; |
|
||||
|
|
||||
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } |
|
||||
|
|
||||
protected IFeatureChecker FeatureChecker => ServiceProvider.LazyGetRequiredService<IFeatureChecker>(); |
|
||||
|
|
||||
public WeChatMiniProgramGrantValidator( |
|
||||
IEventService eventService, |
|
||||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|
||||
UserManager<IdentityUser> userManager, |
|
||||
IIdentityUserRepository userRepository, |
|
||||
IdentitySecurityLogManager identitySecurityLogManager, |
|
||||
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, |
|
||||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, |
|
||||
IStringLocalizer<WeChatResource> wechatLocalizer, |
|
||||
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) |
|
||||
: base( |
|
||||
eventService, |
|
||||
weChatOpenIdFinder, |
|
||||
userManager, |
|
||||
userRepository, |
|
||||
identitySecurityLogManager, |
|
||||
wechatLocalizer, |
|
||||
identityLocalizer, |
|
||||
identityServerLocalizer) |
|
||||
{ |
|
||||
MiniProgramOptionsFactory = miniProgramOptionsFactory; |
|
||||
} |
|
||||
|
|
||||
protected override async Task<bool> CheckFeatureAsync(ExtensionGrantValidationContext context) |
|
||||
{ |
|
||||
if (!await FeatureChecker.IsEnabledAsync(WeChatMiniProgramFeatures.EnableAuthorization)) |
|
||||
{ |
|
||||
context.Result = new GrantValidationResult( |
|
||||
TokenRequestErrors.InvalidGrant, |
|
||||
WeChatLocalizer["MiniProgramAuthorizationDisabledMessage"]); |
|
||||
return false; |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) |
|
||||
{ |
|
||||
var options = await MiniProgramOptionsFactory.CreateAsync(); |
|
||||
|
|
||||
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,67 +0,0 @@ |
|||||
using IdentityServer4.AspNetIdentity; |
|
||||
using IdentityServer4.Models; |
|
||||
using LINGYUN.Abp.WeChat.Security.Claims; |
|
||||
using Microsoft.AspNetCore.Identity; |
|
||||
using System.Linq; |
|
||||
using System.Security.Principal; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Identity; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
using Volo.Abp.Uow; |
|
||||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram |
|
||||
{ |
|
||||
public class WeChatMiniProgramProfileService : ProfileService<IdentityUser> |
|
||||
{ |
|
||||
protected ICurrentTenant CurrentTenant { get; } |
|
||||
public WeChatMiniProgramProfileService( |
|
||||
IdentityUserManager userManager, |
|
||||
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory, |
|
||||
ICurrentTenant currentTenant) |
|
||||
: base(userManager, claimsFactory) |
|
||||
{ |
|
||||
CurrentTenant = currentTenant; |
|
||||
} |
|
||||
|
|
||||
[UnitOfWork] |
|
||||
public override async Task GetProfileDataAsync(ProfileDataRequestContext context) |
|
||||
{ |
|
||||
using (CurrentTenant.Change(context.Subject.FindTenantId())) |
|
||||
{ |
|
||||
await base.GetProfileDataAsync(context); |
|
||||
|
|
||||
// TODO: 可以从令牌获取openid, 安全性呢?
|
|
||||
TryAddWeChatClaim(context, AbpWeChatClaimTypes.OpenId); |
|
||||
TryAddWeChatClaim(context, AbpWeChatClaimTypes.UnionId); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[UnitOfWork] |
|
||||
public override async Task IsActiveAsync(IsActiveContext context) |
|
||||
{ |
|
||||
using (CurrentTenant.Change(context.Subject.FindTenantId())) |
|
||||
{ |
|
||||
await base.IsActiveAsync(context); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[UnitOfWork] |
|
||||
public override Task<bool> IsUserActiveAsync(IdentityUser user) |
|
||||
{ |
|
||||
return Task.FromResult(user.IsActive); |
|
||||
} |
|
||||
|
|
||||
protected virtual void TryAddWeChatClaim(ProfileDataRequestContext context, string weChatClaimType) |
|
||||
{ |
|
||||
if (context.RequestedClaimTypes.Any(rc => rc.Contains(weChatClaimType))) |
|
||||
{ |
|
||||
var weChatClaim = context.Subject.FindFirst(weChatClaimType); |
|
||||
if (weChatClaim != null) |
|
||||
{ |
|
||||
context.IssuedClaims.Add(weChatClaim); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,75 +0,0 @@ |
|||||
using IdentityServer4.Models; |
|
||||
using IdentityServer4.Services; |
|
||||
using IdentityServer4.Validation; |
|
||||
using LINGYUN.Abp.WeChat.Localization; |
|
||||
using LINGYUN.Abp.WeChat.Official; |
|
||||
using LINGYUN.Abp.WeChat.Official.Features; |
|
||||
using LINGYUN.Abp.WeChat.OpenId; |
|
||||
using Microsoft.AspNetCore.Identity; |
|
||||
using Microsoft.Extensions.Localization; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Features; |
|
||||
using Volo.Abp.Identity; |
|
||||
using Volo.Abp.IdentityServer.Localization; |
|
||||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 对于公众平台绑定用户的扩展授权验证器
|
|
||||
/// </summary>
|
|
||||
public class WeChatOfficialGrantValidator : WeChatGrantValidator |
|
||||
{ |
|
||||
public override string GrantType => AbpWeChatOfficialConsts.GrantType; |
|
||||
|
|
||||
public override string LoginProvider => AbpWeChatOfficialConsts.ProviderName; |
|
||||
|
|
||||
public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod; |
|
||||
|
|
||||
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; } |
|
||||
|
|
||||
protected IFeatureChecker FeatureChecker => ServiceProvider.LazyGetRequiredService<IFeatureChecker>(); |
|
||||
|
|
||||
public WeChatOfficialGrantValidator( |
|
||||
IEventService eventService, |
|
||||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|
||||
UserManager<IdentityUser> userManager, |
|
||||
IIdentityUserRepository userRepository, |
|
||||
IdentitySecurityLogManager identitySecurityLogManager, |
|
||||
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, |
|
||||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, |
|
||||
IStringLocalizer<WeChatResource> wechatLocalizer, |
|
||||
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory) |
|
||||
: base( |
|
||||
eventService, |
|
||||
weChatOpenIdFinder, |
|
||||
userManager, |
|
||||
userRepository, |
|
||||
identitySecurityLogManager, |
|
||||
wechatLocalizer, |
|
||||
identityLocalizer, |
|
||||
identityServerLocalizer) |
|
||||
{ |
|
||||
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory; |
|
||||
} |
|
||||
|
|
||||
protected override async Task<bool> CheckFeatureAsync(ExtensionGrantValidationContext context) |
|
||||
{ |
|
||||
if (!await FeatureChecker.IsEnabledAsync(WeChatOfficialFeatures.EnableAuthorization)) |
|
||||
{ |
|
||||
context.Result = new GrantValidationResult( |
|
||||
TokenRequestErrors.InvalidGrant, |
|
||||
WeChatLocalizer["OfficialAuthorizationDisabledMessage"]); |
|
||||
return false; |
|
||||
} |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) |
|
||||
{ |
|
||||
var options = await WeChatOfficialOptionsFactory.CreateAsync(); |
|
||||
|
|
||||
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,71 +0,0 @@ |
|||||
using LINGYUN.Abp.WeChat; |
|
||||
using LINGYUN.Abp.WeChat.Official; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 与微信公众号认证相关的静态(可变)常量
|
|
||||
/// </summary>
|
|
||||
public static class WeChatOfficialOAuthConsts |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 微信个人信息标识
|
|
||||
/// </summary>
|
|
||||
public static string ProfileKey { get; set; } = "wechat.profile"; |
|
||||
/// <summary>
|
|
||||
/// 微信提供者标识
|
|
||||
/// </summary>
|
|
||||
public static string ProviderKey => AbpWeChatOfficialConsts.ProviderName; |
|
||||
/// <summary>
|
|
||||
/// 微信提供者显示名称
|
|
||||
/// </summary>
|
|
||||
public static string DisplayName => AbpWeChatGlobalConsts.DisplayName; |
|
||||
/// <summary>
|
|
||||
/// 回调地址
|
|
||||
/// </summary>
|
|
||||
public static string CallbackPath { get; set; } = "/signin-wechat"; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// 微信客户端外的网页登录
|
|
||||
/// </summary>
|
|
||||
public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect"; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// 微信客户端内的网页登录
|
|
||||
/// </summary>
|
|
||||
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// 用户允许授权后通过返回的code换取access_token地址
|
|
||||
/// </summary>
|
|
||||
public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token"; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// 使用access_token获取用户个人信息地址
|
|
||||
/// </summary>
|
|
||||
public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; |
|
||||
/// <summary>
|
|
||||
/// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
|
|
||||
/// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
|
|
||||
/// <br />
|
|
||||
/// <br />
|
|
||||
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
|
|
||||
/// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
|
|
||||
/// </remarks>
|
|
||||
public const string UserInfoScope = "snsapi_userinfo"; |
|
||||
/// <summary>
|
|
||||
/// 不弹出授权页面,直接跳转,只能获取用户openid
|
|
||||
/// <br />
|
|
||||
/// <br />
|
|
||||
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
|
|
||||
/// 用户感知的就是直接进入了回调页(往往是业务页面)
|
|
||||
/// </remarks>
|
|
||||
public const string LoginScope = "snsapi_login"; |
|
||||
} |
|
||||
} |
|
||||
@ -1,242 +0,0 @@ |
|||||
using IdentityModel; |
|
||||
using IdentityServer4.Events; |
|
||||
using IdentityServer4.Models; |
|
||||
using IdentityServer4.Services; |
|
||||
using IdentityServer4.Validation; |
|
||||
using LINGYUN.Abp.WeChat; |
|
||||
using LINGYUN.Abp.WeChat.Localization; |
|
||||
using LINGYUN.Abp.WeChat.OpenId; |
|
||||
using LINGYUN.Abp.WeChat.Security.Claims; |
|
||||
using LINGYUN.Abp.WeChat.Settings; |
|
||||
using Microsoft.AspNetCore.Identity; |
|
||||
using Microsoft.Extensions.Localization; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
using Microsoft.Extensions.Logging.Abstractions; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Security.Claims; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Guids; |
|
||||
using Volo.Abp.Identity; |
|
||||
using Volo.Abp.IdentityServer; |
|
||||
using Volo.Abp.IdentityServer.Localization; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
using Volo.Abp.Security.Claims; |
|
||||
using Volo.Abp.Settings; |
|
||||
using Volo.Abp.Uow; |
|
||||
|
|
||||
using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource; |
|
||||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IdentityServer.WeChat |
|
||||
{ |
|
||||
public abstract class WeChatGrantValidator : IExtensionGrantValidator |
|
||||
{ |
|
||||
public abstract string GrantType { get; } |
|
||||
public abstract string LoginProvider { get; } |
|
||||
public abstract string AuthenticationMethod { get; } |
|
||||
|
|
||||
public ILogger Logger { protected get; set; } |
|
||||
public IAbpLazyServiceProvider ServiceProvider { protected get; set; } |
|
||||
|
|
||||
protected IEventService EventService { get; } |
|
||||
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } |
|
||||
protected IIdentityUserRepository UserRepository { get; } |
|
||||
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } |
|
||||
protected UserManager<IdentityUser> UserManager { get; } |
|
||||
protected IStringLocalizer<WeChatResource> WeChatLocalizer { get; } |
|
||||
protected IStringLocalizer<IdentityResource> IdentityLocalizer { get; } |
|
||||
protected IStringLocalizer<AbpIdentityServerResource> IdentityServerLocalizer { get; } |
|
||||
|
|
||||
public WeChatGrantValidator( |
|
||||
IEventService eventService, |
|
||||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|
||||
UserManager<IdentityUser> userManager, |
|
||||
IIdentityUserRepository userRepository, |
|
||||
IdentitySecurityLogManager identitySecurityLogManager, |
|
||||
IStringLocalizer<WeChatResource> wechatLocalizer, |
|
||||
IStringLocalizer<IdentityResource> identityLocalizer, |
|
||||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer) |
|
||||
{ |
|
||||
EventService = eventService; |
|
||||
UserManager = userManager; |
|
||||
UserRepository = userRepository; |
|
||||
IdentitySecurityLogManager = identitySecurityLogManager; |
|
||||
WeChatOpenIdFinder = weChatOpenIdFinder; |
|
||||
WeChatLocalizer = wechatLocalizer; |
|
||||
IdentityLocalizer = identityLocalizer; |
|
||||
IdentityServerLocalizer = identityServerLocalizer; |
|
||||
|
|
||||
Logger = NullLogger<WeChatGrantValidator>.Instance; |
|
||||
} |
|
||||
|
|
||||
protected abstract Task<WeChatOpenId> FindOpenIdAsync(string code); |
|
||||
|
|
||||
[UnitOfWork] |
|
||||
public async Task ValidateAsync(ExtensionGrantValidationContext context) |
|
||||
{ |
|
||||
if (!await CheckFeatureAsync(context)) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var raw = context.Request.Raw; |
|
||||
var credential = raw.Get(OidcConstants.TokenRequest.GrantType); |
|
||||
if (credential == null || !credential.Equals(GrantType)) |
|
||||
{ |
|
||||
Logger.LogWarning("Invalid grant type: not allowed"); |
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:GrantTypeInvalid"]); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); |
|
||||
if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
Logger.LogWarning("Invalid grant type: wechat code not found"); |
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatCodeNotFound"]); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
WeChatOpenId wechatOpenId; |
|
||||
try |
|
||||
{ |
|
||||
wechatOpenId = await FindOpenIdAsync(wechatCode); |
|
||||
} |
|
||||
catch(AbpWeChatException e) |
|
||||
{ |
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, e.Message); |
|
||||
return; |
|
||||
} |
|
||||
var currentUser = await UserManager.FindByLoginAsync(LoginProvider, wechatOpenId.OpenId); |
|
||||
if (currentUser == null) |
|
||||
{ |
|
||||
// 检查是否允许自注册
|
|
||||
var settingProvider = ServiceProvider.LazyGetRequiredService<ISettingProvider>(); |
|
||||
// TODO 检查启用用户注册是否有必要引用账户模块
|
|
||||
if (!await settingProvider.IsTrueAsync("Abp.Account.IsSelfRegistrationEnabled") || |
|
||||
!await settingProvider.IsTrueAsync(WeChatSettingNames.EnabledQuickLogin)) |
|
||||
{ |
|
||||
Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId); |
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]); |
|
||||
return; |
|
||||
} |
|
||||
var guiGenerator = ServiceProvider.LazyGetRequiredService<IGuidGenerator>(); |
|
||||
var currentTenant = ServiceProvider.LazyGetRequiredService<ICurrentTenant>(); |
|
||||
var userName = "wxid-" + wechatOpenId.OpenId.ToMd5().ToLower(); |
|
||||
var userEmail = $"{userName}@{currentTenant.Name ?? "default"}.io"; |
|
||||
currentUser = new IdentityUser(guiGenerator.Create(), userName, userEmail, currentTenant.Id); |
|
||||
(await UserManager.CreateAsync(currentUser)).CheckErrors(); |
|
||||
(await UserManager.AddLoginAsync( |
|
||||
currentUser, |
|
||||
new UserLoginInfo( |
|
||||
LoginProvider, |
|
||||
wechatOpenId.OpenId, |
|
||||
AbpWeChatGlobalConsts.DisplayName))).CheckErrors(); |
|
||||
} |
|
||||
|
|
||||
// 检查是否已锁定
|
|
||||
if (await UserManager.IsLockedOutAsync(currentUser)) |
|
||||
{ |
|
||||
Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", currentUser.UserName); |
|
||||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityLocalizer["Volo.Abp.Identity:UserLockedOut"]); |
|
||||
|
|
||||
await SaveSecurityLogAsync(context, currentUser, wechatOpenId, IdentityServerSecurityLogActionConsts.LoginLockedout); |
|
||||
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null)); |
|
||||
|
|
||||
// 登录之后需要更新安全令牌
|
|
||||
(await UserManager.UpdateSecurityStampAsync(currentUser)).CheckErrors(); |
|
||||
|
|
||||
await SetSuccessResultAsync(context, currentUser, wechatOpenId); |
|
||||
} |
|
||||
|
|
||||
protected virtual Task<bool> CheckFeatureAsync(ExtensionGrantValidationContext context) |
|
||||
{ |
|
||||
return Task.FromResult(true); |
|
||||
} |
|
||||
|
|
||||
protected async virtual Task SetSuccessResultAsync(ExtensionGrantValidationContext context, IdentityUser user, WeChatOpenId wechatOpenId) |
|
||||
{ |
|
||||
var sub = await UserManager.GetUserIdAsync(user); |
|
||||
|
|
||||
Logger.LogInformation("Credentials validated for username: {username}", user.UserName); |
|
||||
|
|
||||
var additionalClaims = new List<Claim>(); |
|
||||
|
|
||||
await AddCustomClaimsAsync(additionalClaims, user, wechatOpenId, context); |
|
||||
|
|
||||
context.Result = new GrantValidationResult( |
|
||||
sub, |
|
||||
AuthenticationMethod, |
|
||||
additionalClaims.ToArray() |
|
||||
); |
|
||||
|
|
||||
await SaveSecurityLogAsync( |
|
||||
context, |
|
||||
user, |
|
||||
wechatOpenId, |
|
||||
IdentityServerSecurityLogActionConsts.LoginSucceeded); |
|
||||
} |
|
||||
|
|
||||
protected async virtual Task SaveSecurityLogAsync( |
|
||||
ExtensionGrantValidationContext context, |
|
||||
IdentityUser user, |
|
||||
WeChatOpenId wechatOpenId, |
|
||||
string action) |
|
||||
{ |
|
||||
var logContext = new IdentitySecurityLogContext |
|
||||
{ |
|
||||
Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer, |
|
||||
Action = action, |
|
||||
UserName = user.UserName, |
|
||||
ClientId = await FindClientIdAsync(context) |
|
||||
}; |
|
||||
logContext.WithProperty("GrantType", GrantType); |
|
||||
logContext.WithProperty("Provider", LoginProvider); |
|
||||
logContext.WithProperty("Method", AuthenticationMethod); |
|
||||
|
|
||||
await IdentitySecurityLogManager.SaveAsync(logContext); |
|
||||
} |
|
||||
|
|
||||
protected virtual Task<string> FindClientIdAsync(ExtensionGrantValidationContext context) |
|
||||
{ |
|
||||
return Task.FromResult(context.Request?.Client?.ClientId); |
|
||||
} |
|
||||
|
|
||||
protected virtual Task AddCustomClaimsAsync( |
|
||||
List<Claim> customClaims, |
|
||||
IdentityUser user, |
|
||||
WeChatOpenId wechatOpenId, |
|
||||
ExtensionGrantValidationContext context) |
|
||||
{ |
|
||||
if (user.TenantId.HasValue) |
|
||||
{ |
|
||||
customClaims.Add( |
|
||||
new Claim( |
|
||||
AbpClaimTypes.TenantId, |
|
||||
user.TenantId?.ToString() |
|
||||
) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
customClaims.Add( |
|
||||
new Claim( |
|
||||
AbpWeChatClaimTypes.OpenId, |
|
||||
wechatOpenId.OpenId)); |
|
||||
|
|
||||
if (!wechatOpenId.UnionId.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
customClaims.Add( |
|
||||
new Claim( |
|
||||
AbpWeChatClaimTypes.UnionId, |
|
||||
wechatOpenId.UnionId)); |
|
||||
} |
|
||||
|
|
||||
return Task.CompletedTask; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,25 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Remove="LINGYUN\Abp\OpenIddict\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\OpenIddict\Localization\Resources\*.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Authorization.Abstractions" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.OpenIddict.Domain.Shared" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,29 @@ |
|||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.OpenIddict; |
||||
|
using Volo.Abp.OpenIddict.Localization; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAuthorizationAbstractionsModule), |
||||
|
typeof(AbpOpenIddictDomainSharedModule))] |
||||
|
public class AbpOpenIddictApplicationContractsModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpOpenIddictApplicationContractsModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<AbpOpenIddictResource>() |
||||
|
.AddVirtualJson("/LINGYUN/Abp/OpenIddict/Localization/Resources"); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
public interface IOpenIddictApplicationAppService : |
||||
|
ICrudAppService< |
||||
|
OpenIddictApplicationDto, |
||||
|
Guid, |
||||
|
OpenIddictApplicationGetListInput, |
||||
|
OpenIddictApplicationCreateDto, |
||||
|
OpenIddictApplicationUpdateDto> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictApplicationCreateDto : OpenIddictApplicationCreateOrUpdateDto |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
using Volo.Abp.OpenIddict.Applications; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
public abstract class OpenIddictApplicationCreateOrUpdateDto : ExtensibleObject |
||||
|
{ |
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(OpenIddictApplicationConsts), nameof(OpenIddictApplicationConsts.ClientIdMaxLength))] |
||||
|
public string ClientId { get; set; } |
||||
|
|
||||
|
public string ClientSecret { get; set; } |
||||
|
|
||||
|
[DynamicStringLength(typeof(OpenIddictApplicationConsts), nameof(OpenIddictApplicationConsts.ConsentTypeMaxLength))] |
||||
|
public string ConsentType { get; set; } |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> DisplayNames { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
public List<string> Endpoints { get; set; } = new List<string>(); |
||||
|
public List<string> GrantTypes { get; set; } = new List<string>(); |
||||
|
public List<string> ResponseTypes { get; set; } = new List<string>(); |
||||
|
public List<string> Scopes { get; set; } = new List<string>(); |
||||
|
|
||||
|
public List<string> PostLogoutRedirectUris { get; set; } = new List<string>(); |
||||
|
|
||||
|
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
public List<string> RedirectUris { get; set; } = new List<string>(); |
||||
|
|
||||
|
public List<string> Requirements { get; set; } = new List<string>(); |
||||
|
|
||||
|
[DynamicStringLength(typeof(OpenIddictApplicationConsts), nameof(OpenIddictApplicationConsts.TypeMaxLength))] |
||||
|
public string Type { get; set; } |
||||
|
|
||||
|
public string ClientUri { get; set; } |
||||
|
|
||||
|
public string LogoUri { get; set; } |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictApplicationDto : ExtensibleAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
public string ClientId { get; set; } |
||||
|
public string ClientSecret { get; set; } |
||||
|
public string ConsentType { get; set; } |
||||
|
public string DisplayName { get; set; } |
||||
|
public Dictionary<string, string> DisplayNames { get; set; } = new Dictionary<string, string>(); |
||||
|
public List<string> Endpoints { get; set; } = new List<string>(); |
||||
|
public List<string> GrantTypes { get; set; } = new List<string>(); |
||||
|
public List<string> ResponseTypes { get; set; } = new List<string>(); |
||||
|
public List<string> Scopes { get; set; } = new List<string>(); |
||||
|
public List<string> PostLogoutRedirectUris { get; set; } = new List<string>(); |
||||
|
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>(); |
||||
|
public List<string> RedirectUris { get; set; } = new List<string>(); |
||||
|
public List<string> Requirements { get; set; } = new List<string>(); |
||||
|
public string Type { get; set; } |
||||
|
public string ClientUri { get; set; } |
||||
|
public string LogoUri { get; set; } |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictApplicationGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictApplicationUpdateDto : OpenIddictApplicationCreateOrUpdateDto |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
public interface IOpenIddictAuthorizationAppService : |
||||
|
IReadOnlyAppService< |
||||
|
OpenIddictAuthorizationDto, |
||||
|
Guid, |
||||
|
OpenIddictAuthorizationGetListInput>, |
||||
|
IDeleteAppService<Guid> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictAuthorizationDto : ExtensibleAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
public Guid? ApplicationId { get; set; } |
||||
|
public DateTime? CreationDate { get; set; } |
||||
|
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>(); |
||||
|
public List<string> Scopes { get; set; } = new List<string>(); |
||||
|
public string Status { get; set; } |
||||
|
public string Subject { get; set; } |
||||
|
public string Type { get; set; } |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictAuthorizationGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
public string Subject { get; set; } |
||||
|
public Guid? ClientId { get; set; } |
||||
|
public string Status { get; set; } |
||||
|
public string Type { get; set; } |
||||
|
public DateTime? BeginCreationTime { get; set; } |
||||
|
public DateTime? EndCreationTime { get; set; } |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Permissions:OpenIddict": "OpenIddict", |
||||
|
"Permissions:Applications": "Applications", |
||||
|
"Permissions:Scopes": "Scopes", |
||||
|
"Permissions:Tokens": "Tokens", |
||||
|
"Permissions:Create": "Create", |
||||
|
"Permissions:Update": "Update", |
||||
|
"Permissions:Delete": "Delete", |
||||
|
"Permissions:ManagePermissions": "Manage Permissions", |
||||
|
"OpenIddict:Applications:0001": "The application client id {ClientId} already exists!", |
||||
|
"OpenIddict:Scopes:0001": "The scope name {Name} already exists!", |
||||
|
"DisplayName:ClientId": "Client Id", |
||||
|
"DisplayName:ClientSecret": "Client Secret", |
||||
|
"DisplayName:ConsentType": "Consent Type", |
||||
|
"DisplayName:DisplayName": "Display Name", |
||||
|
"DisplayName:DisplayNames": "Display Names", |
||||
|
"DisplayName:Permissions": "Permissions", |
||||
|
"DisplayName:PostLogoutRedirectUris": "Post Logout Redirect Uris", |
||||
|
"DisplayName:Properties": "Properties", |
||||
|
"DisplayName:RedirectUris": "Redirect Uris", |
||||
|
"DisplayName:Requirements": "Requirements", |
||||
|
"DisplayName:Type": "Type", |
||||
|
"DisplayName:ClientUri": "Client Uri", |
||||
|
"DisplayName:LogoUri": "Logo", |
||||
|
"DisplayName:ApplicationId": "Application Id", |
||||
|
"DisplayName:CreationDate": "Creation Date", |
||||
|
"DisplayName:Scopes": "Scopes", |
||||
|
"DisplayName:Status": "Status", |
||||
|
"DisplayName:Subject": "Subject", |
||||
|
"DisplayName:Description": "Description", |
||||
|
"DisplayName:Descriptions": "Descriptions", |
||||
|
"DisplayName:Name": "Name", |
||||
|
"DisplayName:Resources": "Resources", |
||||
|
"DisplayName:AuthorizationId": "Authorization Id", |
||||
|
"DisplayName:ExpirationDate": "Expiration Date", |
||||
|
"DisplayName:Payload": "Payload", |
||||
|
"DisplayName:RedemptionDate": "Redemption Date", |
||||
|
"DisplayName:ReferenceId": "Reference Id", |
||||
|
"DisplayName:LastModificationTime": "Modify time", |
||||
|
"DisplayName:CreationTime": "Creation time" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Permissions:OpenIddict": "OpenIddict", |
||||
|
"Permissions:Applications": "应用", |
||||
|
"Permissions:Scopes": "范围", |
||||
|
"Permissions:Tokens": "令牌", |
||||
|
"Permissions:Create": "创建", |
||||
|
"Permissions:Update": "编辑", |
||||
|
"Permissions:Delete": "删除", |
||||
|
"Permissions:ManagePermissions": "管理权限", |
||||
|
"OpenIddict:Applications:0001": "应用标识 {ClientId} 已经存在!", |
||||
|
"OpenIddict:Scopes:0001": "范围名称 {Name} 已经存在!", |
||||
|
"DisplayName:ClientId": "客户端标识", |
||||
|
"DisplayName:ClientSecret": "客户端密钥", |
||||
|
"DisplayName:ConsentType": "同意类型", |
||||
|
"DisplayName:DisplayName": "显示名称", |
||||
|
"DisplayName:DisplayNames": "显示名称", |
||||
|
"DisplayName:Permissions": "权限", |
||||
|
"DisplayName:PostLogoutRedirectUris": "注销后重定向Uri", |
||||
|
"DisplayName:Properties": "属性", |
||||
|
"DisplayName:RedirectUris": "重定向Uri", |
||||
|
"DisplayName:Requirements": "需求", |
||||
|
"DisplayName:Type": "类型", |
||||
|
"DisplayName:ClientUri": "客户端Uri", |
||||
|
"DisplayName:LogoUri": "客户端Logo", |
||||
|
"DisplayName:ApplicationId": "应用标识", |
||||
|
"DisplayName:CreationDate": "创建日期", |
||||
|
"DisplayName:Scopes": "范围", |
||||
|
"DisplayName:Status": "状态", |
||||
|
"DisplayName:Subject": "主体", |
||||
|
"DisplayName:Description": "描述", |
||||
|
"DisplayName:Descriptions": "描述", |
||||
|
"DisplayName:Name": "名称", |
||||
|
"DisplayName:Resources": "资源", |
||||
|
"DisplayName:AuthorizationId": "授权标识", |
||||
|
"DisplayName:ExpirationDate": "过期时间", |
||||
|
"DisplayName:Payload": "有效载荷", |
||||
|
"DisplayName:RedemptionDate": "偿还时间", |
||||
|
"DisplayName:ReferenceId": "引用标识", |
||||
|
"DisplayName:LastModificationTime": "修改时间", |
||||
|
"DisplayName:CreationTime": "创建时间" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
public static class OpenIddictApplicationErrorCodes |
||||
|
{ |
||||
|
private const string Namespace = "OpenIddict:"; |
||||
|
|
||||
|
public static class Applications |
||||
|
{ |
||||
|
public const string ClientIdExisted = Namespace + "Applications:0001"; |
||||
|
} |
||||
|
|
||||
|
public static class Authorizations |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public static class Scopes |
||||
|
{ |
||||
|
public const string NameExisted = Namespace + "Scopes:0001"; |
||||
|
} |
||||
|
|
||||
|
public static class Tokens |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
public class OpenIddictRemoteServiceConsts |
||||
|
{ |
||||
|
public const string RemoteServiceName = "AbpOpenIddict"; |
||||
|
|
||||
|
public const string ModuleName = "openiddict"; |
||||
|
} |
||||
@ -0,0 +1,84 @@ |
|||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.OpenIddict.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Permissions |
||||
|
{ |
||||
|
public class AbpIdentityServerPermissionDefinitionProvider : PermissionDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IPermissionDefinitionContext context) |
||||
|
{ |
||||
|
var openIddictGroup = context.GetGroupOrNull(AbpOpenIddictPermissions.GroupName); |
||||
|
if (openIddictGroup == null) |
||||
|
{ |
||||
|
openIddictGroup = context |
||||
|
.AddGroup( |
||||
|
name: AbpOpenIddictPermissions.GroupName, |
||||
|
displayName: L("Permissions:OpenIddict"), |
||||
|
multiTenancySide: MultiTenancySides.Host); |
||||
|
} |
||||
|
|
||||
|
var applications = openIddictGroup.AddPermission( |
||||
|
AbpOpenIddictPermissions.Applications.Default, |
||||
|
L("Permissions:Applications"), |
||||
|
MultiTenancySides.Host); |
||||
|
applications.AddChild( |
||||
|
AbpOpenIddictPermissions.Applications.Create, |
||||
|
L("Permissions:Create"), |
||||
|
MultiTenancySides.Host); |
||||
|
applications.AddChild( |
||||
|
AbpOpenIddictPermissions.Applications.Update, |
||||
|
L("Permissions:Update"), |
||||
|
MultiTenancySides.Host); |
||||
|
applications.AddChild( |
||||
|
AbpOpenIddictPermissions.Applications.Delete, |
||||
|
L("Permissions:Delete"), |
||||
|
MultiTenancySides.Host); |
||||
|
applications.AddChild( |
||||
|
AbpOpenIddictPermissions.Applications.ManagePermissions, |
||||
|
L("Permissions:ManagePermissions"), |
||||
|
MultiTenancySides.Host); |
||||
|
|
||||
|
var authorizations = openIddictGroup.AddPermission( |
||||
|
AbpOpenIddictPermissions.Authorizations.Default, |
||||
|
L("Permissions:Authorizations"), |
||||
|
MultiTenancySides.Host); |
||||
|
authorizations.AddChild( |
||||
|
AbpOpenIddictPermissions.Authorizations.Delete, |
||||
|
L("Permissions:Delete"), |
||||
|
MultiTenancySides.Host); |
||||
|
|
||||
|
var scopes = openIddictGroup.AddPermission( |
||||
|
AbpOpenIddictPermissions.Scopes.Default, |
||||
|
L("Permissions:Scopes"), |
||||
|
MultiTenancySides.Host); |
||||
|
scopes.AddChild( |
||||
|
AbpOpenIddictPermissions.Scopes.Create, |
||||
|
L("Permissions:Create"), |
||||
|
MultiTenancySides.Host); |
||||
|
scopes.AddChild( |
||||
|
AbpOpenIddictPermissions.Scopes.Update, |
||||
|
L("Permissions:Update"), |
||||
|
MultiTenancySides.Host); |
||||
|
scopes.AddChild( |
||||
|
AbpOpenIddictPermissions.Scopes.Delete, |
||||
|
L("Permissions:Delete"), |
||||
|
MultiTenancySides.Host); |
||||
|
|
||||
|
var tokens = openIddictGroup.AddPermission( |
||||
|
AbpOpenIddictPermissions.Tokens.Default, |
||||
|
L("Permissions:Tokens"), |
||||
|
MultiTenancySides.Host); |
||||
|
tokens.AddChild( |
||||
|
AbpOpenIddictPermissions.Tokens.Delete, |
||||
|
L("Permissions:Delete"), |
||||
|
MultiTenancySides.Host); |
||||
|
} |
||||
|
|
||||
|
protected virtual LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<AbpOpenIddictResource>(name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
namespace LINGYUN.Abp.OpenIddict.Permissions |
||||
|
{ |
||||
|
public class AbpOpenIddictPermissions |
||||
|
{ |
||||
|
public const string GroupName = "AbpOpenIddict"; |
||||
|
|
||||
|
public static class Applications |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Applications"; |
||||
|
public const string Create = Default + ".Create"; |
||||
|
public const string Update = Default + ".Update"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
public const string ManagePermissions = Default + ".ManagePermissions"; |
||||
|
} |
||||
|
|
||||
|
public static class Authorizations |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Authorizations"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
} |
||||
|
|
||||
|
public static class Scopes |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Scopes"; |
||||
|
public const string Create = Default + ".Create"; |
||||
|
public const string Update = Default + ".Update"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
} |
||||
|
|
||||
|
public static class Tokens |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Tokens"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
public interface IOpenIddictScopeAppService : |
||||
|
ICrudAppService< |
||||
|
OpenIddictScopeDto, |
||||
|
Guid, |
||||
|
OpenIddictScopeGetListInput, |
||||
|
OpenIddictScopeCreateDto, |
||||
|
OpenIddictScopeUpdateDto> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictScopeCreateDto : OpenIddictScopeCreateOrUpdateDto |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
using Volo.Abp.OpenIddict.Scopes; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
public abstract class OpenIddictScopeCreateOrUpdateDto : ExtensibleObject |
||||
|
{ |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> Descriptions { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> DisplayNames { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
[Required] |
||||
|
[DynamicStringLength(typeof(OpenIddictScopeConsts), nameof(OpenIddictScopeConsts.NameMaxLength))] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
public List<string> Resources { get; set; } |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictScopeDto : ExtensibleAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
public string Description { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> Descriptions { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> DisplayNames { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>(); |
||||
|
|
||||
|
public List<string> Resources { get; set; } |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictScopeGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictScopeUpdateDto : OpenIddictScopeCreateOrUpdateDto |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
public interface IOpenIddictTokenAppService : |
||||
|
IReadOnlyAppService< |
||||
|
OpenIddictTokenDto, |
||||
|
Guid, |
||||
|
OpenIddictTokenGetListInput>, |
||||
|
IDeleteAppService<Guid> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictTokenDto : ExtensibleAuditedEntityDto<Guid> |
||||
|
{ |
||||
|
public Guid? ApplicationId { get; set; } |
||||
|
|
||||
|
public Guid? AuthorizationId { get; set; } |
||||
|
|
||||
|
public DateTime? CreationDate { get; set; } |
||||
|
|
||||
|
public DateTime? ExpirationDate { get; set; } |
||||
|
|
||||
|
public string Payload { get; set; } |
||||
|
|
||||
|
public string Properties { get; set; } |
||||
|
|
||||
|
public DateTime? RedemptionDate { get; set; } |
||||
|
|
||||
|
public string ReferenceId { get; set; } |
||||
|
|
||||
|
public string Status { get; set; } |
||||
|
|
||||
|
public string Subject { get; set; } |
||||
|
|
||||
|
public string Type { get; set; } |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
[Serializable] |
||||
|
public class OpenIddictTokenGetListInput : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string Filter { get; set; } |
||||
|
public Guid? ClientId { get; set; } |
||||
|
public Guid? AuthorizationId { get; set; } |
||||
|
public string Subject { get; set; } |
||||
|
public string Status { get; set; } |
||||
|
public string Type { get; set; } |
||||
|
public string ReferenceId { get; set; } |
||||
|
public DateTime? BeginExpirationDate { get; set; } |
||||
|
public DateTime? EndExpirationDate { get; set; } |
||||
|
public DateTime? BeginCreationTime { get; set; } |
||||
|
public DateTime? EndCreationTime { get; set; } |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.1</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.OpenIddict.Domain" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.OpenIddict.Application.Contracts\LINGYUN.Abp.OpenIddict.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.OpenIddict; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpOpenIddictApplicationContractsModule), |
||||
|
typeof(AbpOpenIddictDomainModule), |
||||
|
typeof(AbpDddApplicationModule))] |
||||
|
public class AbpOpenIddictApplicationModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
using LINGYUN.Abp.OpenIddict.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Default)] |
||||
|
public class OpenIddictApplicationAppService : OpenIddictApplicationServiceBase, IOpenIddictApplicationAppService |
||||
|
{ |
||||
|
protected IOpenIddictApplicationRepository Repository { get; } |
||||
|
|
||||
|
public OpenIddictApplicationAppService( |
||||
|
IOpenIddictApplicationRepository repository) |
||||
|
{ |
||||
|
Repository = repository; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<OpenIddictApplicationDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var application = await Repository.GetAsync(id); |
||||
|
|
||||
|
return application.ToDto(JsonSerializer); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<PagedResultDto<OpenIddictApplicationDto>> GetListAsync(OpenIddictApplicationGetListInput input) |
||||
|
{ |
||||
|
var totalCount = await Repository.GetCountAsync(input.Filter); |
||||
|
var entites = await Repository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Filter); |
||||
|
|
||||
|
return new PagedResultDto<OpenIddictApplicationDto>(totalCount, |
||||
|
entites.Select(entity => entity.ToDto(JsonSerializer)).ToList()); |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Create)] |
||||
|
public async virtual Task<OpenIddictApplicationDto> CreateAsync(OpenIddictApplicationCreateDto input) |
||||
|
{ |
||||
|
if (await Repository.FindByClientIdAsync(input.ClientId) != null) |
||||
|
{ |
||||
|
throw new BusinessException(OpenIddictApplicationErrorCodes.Applications.ClientIdExisted) |
||||
|
.WithData(nameof(OpenIddictApplication.ClientId), input.ClientId); |
||||
|
} |
||||
|
|
||||
|
var application = new OpenIddictApplication(GuidGenerator.Create()); |
||||
|
application = input.ToEntity(application, JsonSerializer); |
||||
|
|
||||
|
application = await Repository.InsertAsync(application); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
|
||||
|
return application.ToDto(JsonSerializer); |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Update)] |
||||
|
public async virtual Task<OpenIddictApplicationDto> UpdateAsync(Guid id, OpenIddictApplicationUpdateDto input) |
||||
|
{ |
||||
|
var application = await Repository.GetAsync(id); |
||||
|
|
||||
|
if (!string.Equals(application.ClientId, input.ClientId) && |
||||
|
await Repository.FindByClientIdAsync(input.ClientId) != null) |
||||
|
{ |
||||
|
throw new BusinessException(OpenIddictApplicationErrorCodes.Applications.ClientIdExisted) |
||||
|
.WithData(nameof(OpenIddictApplicationCreateDto.ClientId), input.ClientId); |
||||
|
} |
||||
|
|
||||
|
application = input.ToEntity(application, JsonSerializer); |
||||
|
|
||||
|
application = await Repository.UpdateAsync(application); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
|
||||
|
return application.ToDto(JsonSerializer); |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Delete)] |
||||
|
public async virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await Repository.DeleteAsync(id); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,162 @@ |
|||||
|
using OpenIddict.Abstractions; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
internal static class OpenIddictApplicationExtensions |
||||
|
{ |
||||
|
public static OpenIddictApplication ToEntity(this OpenIddictApplicationCreateOrUpdateDto dto, OpenIddictApplication entity, IJsonSerializer jsonSerializer) |
||||
|
{ |
||||
|
Check.NotNull(dto, nameof(dto)); |
||||
|
Check.NotNull(entity, nameof(entity)); |
||||
|
|
||||
|
entity.ClientId = dto.ClientId; |
||||
|
entity.ClientSecret = dto.ClientSecret; |
||||
|
entity.ConsentType = dto.ConsentType; |
||||
|
entity.DisplayName = dto.DisplayName; |
||||
|
entity.DisplayNames = jsonSerializer.Serialize(dto.DisplayNames); |
||||
|
entity.PostLogoutRedirectUris = jsonSerializer.Serialize(dto.PostLogoutRedirectUris); |
||||
|
entity.Properties = jsonSerializer.Serialize(dto.Properties); |
||||
|
entity.RedirectUris = jsonSerializer.Serialize(dto.RedirectUris); |
||||
|
entity.Type = dto.Type; |
||||
|
entity.ClientUri = dto.ClientUri; |
||||
|
entity.LogoUri = dto.LogoUri; |
||||
|
|
||||
|
var requirements = new List<string>(); |
||||
|
requirements.AddRange( |
||||
|
dto.Requirements.Select(requirement => |
||||
|
{ |
||||
|
if (!requirement.StartsWith(OpenIddictConstants.Requirements.Prefixes.Feature)) |
||||
|
{ |
||||
|
return OpenIddictConstants.Requirements.Prefixes.Feature + requirement; |
||||
|
} |
||||
|
return requirement; |
||||
|
})); |
||||
|
entity.Requirements = jsonSerializer.Serialize(requirements); |
||||
|
|
||||
|
var permissions = new List<string>(); |
||||
|
permissions.AddRange( |
||||
|
dto.Endpoints.Select(endpoint => |
||||
|
{ |
||||
|
if (!endpoint.StartsWith(OpenIddictConstants.Permissions.Prefixes.Endpoint)) |
||||
|
{ |
||||
|
return OpenIddictConstants.Permissions.Prefixes.Endpoint + endpoint; |
||||
|
} |
||||
|
return endpoint; |
||||
|
})); |
||||
|
permissions.AddRange( |
||||
|
dto.GrantTypes.Select(grantType => |
||||
|
{ |
||||
|
if (!grantType.StartsWith(OpenIddictConstants.Permissions.Prefixes.GrantType)) |
||||
|
{ |
||||
|
return OpenIddictConstants.Permissions.Prefixes.GrantType + grantType; |
||||
|
} |
||||
|
return grantType; |
||||
|
})); |
||||
|
permissions.AddRange( |
||||
|
dto.ResponseTypes.Select(responseType => |
||||
|
{ |
||||
|
if (!responseType.StartsWith(OpenIddictConstants.Permissions.Prefixes.ResponseType)) |
||||
|
{ |
||||
|
return OpenIddictConstants.Permissions.Prefixes.ResponseType + responseType; |
||||
|
} |
||||
|
return responseType; |
||||
|
})); |
||||
|
permissions.AddRange( |
||||
|
dto.Scopes.Select(scope => |
||||
|
{ |
||||
|
if (!scope.StartsWith(OpenIddictConstants.Permissions.Prefixes.Scope)) |
||||
|
{ |
||||
|
return OpenIddictConstants.Permissions.Prefixes.Scope + scope; |
||||
|
} |
||||
|
return scope; |
||||
|
})); |
||||
|
entity.Permissions = jsonSerializer.Serialize(permissions); |
||||
|
|
||||
|
foreach (var extraProperty in dto.ExtraProperties) |
||||
|
{ |
||||
|
entity.ExtraProperties.Remove(extraProperty.Key); |
||||
|
entity.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return entity; |
||||
|
} |
||||
|
|
||||
|
public static OpenIddictApplicationDto ToDto(this OpenIddictApplication entity, IJsonSerializer jsonSerializer) |
||||
|
{ |
||||
|
if (entity == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var dto = new OpenIddictApplicationDto |
||||
|
{ |
||||
|
Id = entity.Id, |
||||
|
ClientId = entity.ClientId, |
||||
|
ClientSecret = entity.ClientSecret, |
||||
|
ConsentType = entity.ConsentType, |
||||
|
DisplayName = entity.DisplayName, |
||||
|
CreationTime = entity.CreationTime, |
||||
|
CreatorId = entity.CreatorId, |
||||
|
LastModificationTime = entity.LastModificationTime, |
||||
|
LastModifierId = entity.LastModifierId, |
||||
|
DisplayNames = jsonSerializer.DeserializeToDictionary<string, string>(entity.DisplayNames), |
||||
|
PostLogoutRedirectUris = jsonSerializer.DeserializeToList<string>(entity.PostLogoutRedirectUris), |
||||
|
Properties = jsonSerializer.DeserializeToDictionary<string, string>(entity.Properties), |
||||
|
RedirectUris = jsonSerializer.DeserializeToList<string>(entity.RedirectUris), |
||||
|
Type = entity.Type, |
||||
|
ClientUri = entity.ClientUri, |
||||
|
LogoUri = entity.LogoUri |
||||
|
}; |
||||
|
|
||||
|
var requirements = jsonSerializer.DeserializeToList<string>(entity.Requirements); |
||||
|
dto.Requirements = requirements |
||||
|
.Where(HasPrefixKey(OpenIddictConstants.Requirements.Prefixes.Feature)) |
||||
|
.Select(GetPrefixKey(OpenIddictConstants.Requirements.Prefixes.Feature)) |
||||
|
.ToList(); |
||||
|
|
||||
|
var permissions = jsonSerializer.DeserializeToList<string>(entity.Permissions); |
||||
|
|
||||
|
dto.Endpoints = permissions |
||||
|
.Where(HasPrefixKey(OpenIddictConstants.Permissions.Prefixes.Endpoint)) |
||||
|
.Select(GetPrefixKey(OpenIddictConstants.Permissions.Prefixes.Endpoint)) |
||||
|
.ToList(); |
||||
|
|
||||
|
dto.GrantTypes = permissions |
||||
|
.Where(HasPrefixKey(OpenIddictConstants.Permissions.Prefixes.GrantType)) |
||||
|
.Select(GetPrefixKey(OpenIddictConstants.Permissions.Prefixes.GrantType)) |
||||
|
.ToList(); |
||||
|
|
||||
|
dto.ResponseTypes = permissions |
||||
|
.Where(HasPrefixKey(OpenIddictConstants.Permissions.Prefixes.ResponseType)) |
||||
|
.Select(GetPrefixKey(OpenIddictConstants.Permissions.Prefixes.ResponseType)) |
||||
|
.ToList(); |
||||
|
|
||||
|
dto.Scopes = permissions |
||||
|
.Where(HasPrefixKey(OpenIddictConstants.Permissions.Prefixes.Scope)) |
||||
|
.Select(GetPrefixKey(OpenIddictConstants.Permissions.Prefixes.Scope)) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var extraProperty in entity.ExtraProperties) |
||||
|
{ |
||||
|
dto.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return dto; |
||||
|
} |
||||
|
|
||||
|
private static Func<string, bool> HasPrefixKey(string prefix) |
||||
|
{ |
||||
|
return p => p.StartsWith(prefix); |
||||
|
} |
||||
|
|
||||
|
private static Func<string, string> GetPrefixKey(string prefix) |
||||
|
{ |
||||
|
return p => p.RemovePreFix(prefix); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
using LINGYUN.Abp.OpenIddict.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Authorizations.Default)] |
||||
|
public class OpenIddictAuthorizationAppService : OpenIddictApplicationServiceBase, IOpenIddictAuthorizationAppService |
||||
|
{ |
||||
|
protected IRepository<OpenIddictAuthorization, Guid> Repository { get; } |
||||
|
|
||||
|
public OpenIddictAuthorizationAppService( |
||||
|
IRepository<OpenIddictAuthorization, Guid> repository) |
||||
|
{ |
||||
|
Repository = repository; |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Authorizations.Delete)] |
||||
|
public async virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await Repository.DeleteAsync(id); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<OpenIddictAuthorizationDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var authorization = await Repository.GetAsync(id); |
||||
|
|
||||
|
return authorization.ToDto(JsonSerializer); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<PagedResultDto<OpenIddictAuthorizationDto>> GetListAsync(OpenIddictAuthorizationGetListInput input) |
||||
|
{ |
||||
|
var queryable = await Repository.GetQueryableAsync(); |
||||
|
if (input.ClientId.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.ApplicationId == input.ClientId); |
||||
|
} |
||||
|
if (input.BeginCreationTime.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.CreationTime >= input.BeginCreationTime); |
||||
|
} |
||||
|
if (input.EndCreationTime.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.CreationTime <= input.BeginCreationTime); |
||||
|
} |
||||
|
if (!input.Status.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Status == input.Status); |
||||
|
} |
||||
|
if (!input.Type.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Type == input.Type); |
||||
|
} |
||||
|
if (!input.Subject.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Subject == input.Subject); |
||||
|
} |
||||
|
if (!input.Filter.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Subject.Contains(input.Filter) || |
||||
|
x.Status.Contains(input.Filter) || x.Type.Contains(input.Filter) || |
||||
|
x.Scopes.Contains(input.Filter) || x.Properties.Contains(input.Filter)); |
||||
|
} |
||||
|
queryable = queryable |
||||
|
.OrderBy(input.Sorting ?? $"{nameof(OpenIddictAuthorization.CreationTime)} DESC") |
||||
|
.PageBy(input.SkipCount, input.MaxResultCount); |
||||
|
|
||||
|
var totalCount = await AsyncExecuter.CountAsync(queryable); |
||||
|
var entites = await AsyncExecuter.ToListAsync(queryable); |
||||
|
|
||||
|
return new PagedResultDto<OpenIddictAuthorizationDto>(totalCount, |
||||
|
entites.Select(entity => entity.ToDto(JsonSerializer)).ToList()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
internal static class OpenIddictAuthorizationExtensions |
||||
|
{ |
||||
|
public static OpenIddictAuthorizationDto ToDto(this OpenIddictAuthorization entity, IJsonSerializer jsonSerializer) |
||||
|
{ |
||||
|
if (entity == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var dto = new OpenIddictAuthorizationDto |
||||
|
{ |
||||
|
Id = entity.Id, |
||||
|
ApplicationId = entity.ApplicationId, |
||||
|
CreationDate = entity.CreationDate, |
||||
|
CreationTime = entity.CreationTime, |
||||
|
CreatorId = entity.CreatorId, |
||||
|
LastModificationTime = entity.LastModificationTime, |
||||
|
LastModifierId = entity.LastModifierId, |
||||
|
Properties = jsonSerializer.DeserializeToDictionary<string, string>(entity.Properties), |
||||
|
Scopes = jsonSerializer.DeserializeToList<string>(entity.Scopes), |
||||
|
Status = entity.Status, |
||||
|
Subject = entity.Subject, |
||||
|
Type = entity.Type |
||||
|
}; |
||||
|
|
||||
|
foreach (var extraProperty in entity.ExtraProperties) |
||||
|
{ |
||||
|
dto.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return dto; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System.Threading; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.OpenIddict.Localization; |
||||
|
using Volo.Abp.Threading; |
||||
|
using Volo.Abp.Json; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
public abstract class OpenIddictApplicationServiceBase : ApplicationService |
||||
|
{ |
||||
|
protected IJsonSerializer JsonSerializer => LazyServiceProvider.LazyGetRequiredService<IJsonSerializer>(); |
||||
|
protected ICancellationTokenProvider CancellationTokenProvider => LazyServiceProvider.LazyGetRequiredService<ICancellationTokenProvider>(); |
||||
|
protected OpenIddictApplicationServiceBase() |
||||
|
{ |
||||
|
LocalizationResource = typeof(AbpOpenIddictResource); |
||||
|
} |
||||
|
|
||||
|
protected virtual CancellationToken GetCancellationToken() |
||||
|
{ |
||||
|
return CancellationTokenProvider.FallbackToProvider(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,85 @@ |
|||||
|
using LINGYUN.Abp.OpenIddict.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Scopes.Default)] |
||||
|
public class OpenIddictScopeAppService : OpenIddictApplicationServiceBase, IOpenIddictScopeAppService |
||||
|
{ |
||||
|
protected IOpenIddictScopeRepository Repository { get; } |
||||
|
|
||||
|
public OpenIddictScopeAppService(IOpenIddictScopeRepository repository) |
||||
|
{ |
||||
|
Repository = repository; |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Scopes.Create)] |
||||
|
public async virtual Task<OpenIddictScopeDto> CreateAsync(OpenIddictScopeCreateDto input) |
||||
|
{ |
||||
|
if (await Repository.FindByNameAsync(input.Name) != null) |
||||
|
{ |
||||
|
throw new BusinessException(OpenIddictApplicationErrorCodes.Scopes.NameExisted) |
||||
|
.WithData(nameof(OpenIddictScope.Name), input.Name); |
||||
|
} |
||||
|
|
||||
|
var scope = new OpenIddictScope(GuidGenerator.Create()); |
||||
|
scope = input.ToEntity(scope, JsonSerializer); |
||||
|
|
||||
|
scope = await Repository.InsertAsync(scope); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
|
||||
|
return scope.ToDto(JsonSerializer); |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Scopes.Delete)] |
||||
|
public async virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await Repository.DeleteAsync(id); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<OpenIddictScopeDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var scope = await Repository.GetAsync(id); |
||||
|
|
||||
|
return scope.ToDto(JsonSerializer); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<PagedResultDto<OpenIddictScopeDto>> GetListAsync(OpenIddictScopeGetListInput input) |
||||
|
{ |
||||
|
var totalCount = await Repository.GetCountAsync(input.Filter); |
||||
|
var entites = await Repository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Filter); |
||||
|
|
||||
|
return new PagedResultDto<OpenIddictScopeDto>(totalCount, |
||||
|
entites.Select(entity => entity.ToDto(JsonSerializer)).ToList()); |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Scopes.Update)] |
||||
|
public async virtual Task<OpenIddictScopeDto> UpdateAsync(Guid id, OpenIddictScopeUpdateDto input) |
||||
|
{ |
||||
|
var scope = await Repository.GetAsync(id); |
||||
|
|
||||
|
if (!string.Equals(scope.Name, input.Name) && |
||||
|
await Repository.FindByNameAsync(input.Name) != null) |
||||
|
{ |
||||
|
throw new BusinessException(OpenIddictApplicationErrorCodes.Scopes.NameExisted) |
||||
|
.WithData(nameof(OpenIddictScope.Name), input.Name); |
||||
|
} |
||||
|
|
||||
|
scope = input.ToEntity(scope, JsonSerializer); |
||||
|
|
||||
|
scope = await Repository.UpdateAsync(scope); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
|
||||
|
return scope.ToDto(JsonSerializer); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,62 @@ |
|||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Scopes; |
||||
|
|
||||
|
internal static class OpenIddictScopeExtensions |
||||
|
{ |
||||
|
public static OpenIddictScope ToEntity(this OpenIddictScopeCreateOrUpdateDto dto, OpenIddictScope entity, IJsonSerializer jsonSerializer) |
||||
|
{ |
||||
|
Check.NotNull(dto, nameof(dto)); |
||||
|
Check.NotNull(entity, nameof(entity)); |
||||
|
|
||||
|
entity.Description = dto.Description; |
||||
|
entity.Descriptions = jsonSerializer.Serialize(dto.Descriptions); |
||||
|
entity.DisplayName = dto.DisplayName; |
||||
|
entity.DisplayNames = jsonSerializer.Serialize(dto.DisplayNames); |
||||
|
entity.Name = dto.Name; |
||||
|
entity.Properties = jsonSerializer.Serialize(dto.Properties); |
||||
|
entity.Resources = jsonSerializer.Serialize(dto.Resources); |
||||
|
|
||||
|
foreach (var extraProperty in dto.ExtraProperties) |
||||
|
{ |
||||
|
entity.ExtraProperties.Remove(extraProperty.Key); |
||||
|
entity.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return entity; |
||||
|
} |
||||
|
|
||||
|
public static OpenIddictScopeDto ToDto(this OpenIddictScope entity, IJsonSerializer jsonSerializer) |
||||
|
{ |
||||
|
if (entity == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var dto = new OpenIddictScopeDto |
||||
|
{ |
||||
|
Id = entity.Id, |
||||
|
CreationTime = entity.CreationTime, |
||||
|
CreatorId = entity.CreatorId, |
||||
|
LastModificationTime = entity.LastModificationTime, |
||||
|
LastModifierId = entity.LastModifierId, |
||||
|
Description = entity.Description, |
||||
|
Descriptions = jsonSerializer.DeserializeToDictionary<string, string>(entity.Descriptions), |
||||
|
DisplayName = entity.DisplayName, |
||||
|
DisplayNames = jsonSerializer.DeserializeToDictionary<string, string>(entity.DisplayNames), |
||||
|
Name = entity.Name, |
||||
|
Properties = jsonSerializer.DeserializeToDictionary<string, string>(entity.Properties), |
||||
|
Resources = jsonSerializer.DeserializeToList<string>(entity.Resources) |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
foreach (var extraProperty in entity.ExtraProperties) |
||||
|
{ |
||||
|
dto.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return dto; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,94 @@ |
|||||
|
using LINGYUN.Abp.OpenIddict.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Tokens.Default)] |
||||
|
public class OpenIddictTokenAppService : OpenIddictApplicationServiceBase, IOpenIddictTokenAppService |
||||
|
{ |
||||
|
protected IRepository<OpenIddictToken, Guid> Repository { get; } |
||||
|
|
||||
|
public OpenIddictTokenAppService(IRepository<OpenIddictToken, Guid> repository) |
||||
|
{ |
||||
|
Repository = repository; |
||||
|
} |
||||
|
|
||||
|
[Authorize(AbpOpenIddictPermissions.Tokens.Delete)] |
||||
|
public async virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await Repository.DeleteAsync(id); |
||||
|
|
||||
|
await CurrentUnitOfWork.SaveChangesAsync(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<OpenIddictTokenDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var scope = await Repository.GetAsync(id); |
||||
|
|
||||
|
return scope.ToDto(); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<PagedResultDto<OpenIddictTokenDto>> GetListAsync(OpenIddictTokenGetListInput input) |
||||
|
{ |
||||
|
var queryable = await Repository.GetQueryableAsync(); |
||||
|
if (input.ClientId.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.ApplicationId == input.ClientId); |
||||
|
} |
||||
|
if (input.BeginCreationTime.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.CreationTime >= input.BeginCreationTime); |
||||
|
} |
||||
|
if (input.EndCreationTime.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.CreationTime <= input.BeginCreationTime); |
||||
|
} |
||||
|
if (input.BeginExpirationDate.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.ExpirationDate >= input.BeginCreationTime); |
||||
|
} |
||||
|
if (input.EndExpirationDate.HasValue) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.ExpirationDate <= input.BeginCreationTime); |
||||
|
} |
||||
|
if (!input.Status.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Status == input.Status); |
||||
|
} |
||||
|
if (!input.Type.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Type == input.Type); |
||||
|
} |
||||
|
if (!input.Subject.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Subject == input.Subject); |
||||
|
} |
||||
|
if (!input.ReferenceId.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.ReferenceId == input.ReferenceId); |
||||
|
} |
||||
|
if (!input.Filter.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
queryable = queryable.Where(x => x.Subject.Contains(input.Filter) || |
||||
|
x.Status.Contains(input.Filter) || x.Type.Contains(input.Filter) || |
||||
|
x.Payload.Contains(input.Filter) || x.Properties.Contains(input.Filter) || |
||||
|
x.ReferenceId.Contains(input.ReferenceId)); |
||||
|
} |
||||
|
queryable = queryable |
||||
|
.OrderBy(input.Sorting ?? $"{nameof(OpenIddictToken.CreationTime)} DESC") |
||||
|
.PageBy(input.SkipCount, input.MaxResultCount); |
||||
|
|
||||
|
var totalCount = await AsyncExecuter.CountAsync(queryable); |
||||
|
var entites = await AsyncExecuter.ToListAsync(queryable); |
||||
|
|
||||
|
return new PagedResultDto<OpenIddictTokenDto>(totalCount, |
||||
|
entites.Select(entity => entity.ToDto()).ToList()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Tokens; |
||||
|
|
||||
|
internal static class OpenIddictTokenExtensions |
||||
|
{ |
||||
|
public static OpenIddictToken ToEntity(this OpenIddictTokenDto dto, OpenIddictToken entity) |
||||
|
{ |
||||
|
Check.NotNull(dto, nameof(dto)); |
||||
|
Check.NotNull(entity, nameof(entity)); |
||||
|
|
||||
|
entity.ApplicationId = dto.ApplicationId; |
||||
|
entity.AuthorizationId = dto.AuthorizationId; |
||||
|
entity.CreationDate = dto.CreationDate; |
||||
|
entity.ExpirationDate = dto.ExpirationDate; |
||||
|
entity.Payload = dto.Payload; |
||||
|
entity.Properties = dto.Properties; |
||||
|
entity.RedemptionDate = dto.RedemptionDate; |
||||
|
entity.ReferenceId = dto.ReferenceId; |
||||
|
entity.Status = dto.Status; |
||||
|
entity.Subject = dto.Subject; |
||||
|
entity.Type = dto.Type; |
||||
|
|
||||
|
foreach (var extraProperty in dto.ExtraProperties) |
||||
|
{ |
||||
|
entity.ExtraProperties.Remove(extraProperty.Key); |
||||
|
entity.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return entity; |
||||
|
} |
||||
|
|
||||
|
public static OpenIddictTokenDto ToDto(this OpenIddictToken entity) |
||||
|
{ |
||||
|
if (entity == null) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var model = new OpenIddictTokenDto |
||||
|
{ |
||||
|
Id = entity.Id, |
||||
|
ApplicationId = entity.ApplicationId, |
||||
|
AuthorizationId = entity.AuthorizationId, |
||||
|
CreationDate = entity.CreationDate, |
||||
|
CreationTime = entity.CreationTime, |
||||
|
CreatorId = entity.CreatorId, |
||||
|
LastModificationTime = entity.LastModificationTime, |
||||
|
LastModifierId = entity.LastModifierId, |
||||
|
ExpirationDate = entity.ExpirationDate, |
||||
|
Payload = entity.Payload, |
||||
|
Properties = entity.Properties, |
||||
|
RedemptionDate = entity.RedemptionDate, |
||||
|
ReferenceId = entity.ReferenceId, |
||||
|
Status = entity.Status, |
||||
|
Subject = entity.Subject, |
||||
|
Type = entity.Type |
||||
|
}; |
||||
|
|
||||
|
foreach (var extraProperty in entity.ExtraProperties) |
||||
|
{ |
||||
|
model.ExtraProperties.Add(extraProperty.Key, extraProperty.Value); |
||||
|
} |
||||
|
|
||||
|
return model; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Json; |
||||
|
internal static class IJsonSerializerExtensions |
||||
|
{ |
||||
|
public static List<TResult> DeserializeToList<TResult>(this IJsonSerializer serializer, string source) |
||||
|
{ |
||||
|
if (source.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return new List<TResult>(); |
||||
|
} |
||||
|
|
||||
|
return serializer.Deserialize<List<TResult>>(source); |
||||
|
} |
||||
|
|
||||
|
public static Dictionary<TKey, TValue> DeserializeToDictionary<TKey, TValue>(this IJsonSerializer serializer, string source) |
||||
|
{ |
||||
|
if (source.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return new Dictionary<TKey, TValue>(); |
||||
|
} |
||||
|
|
||||
|
return serializer.Deserialize<Dictionary<TKey, TValue>>(source); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,16 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\dapr\LINGYUN.Abp.Dapr.Client\LINGYUN.Abp.Dapr.Client.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.OpenIddict.Application.Contracts\LINGYUN.Abp.OpenIddict.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using LINGYUN.Abp.Dapr.Client; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpOpenIddictApplicationContractsModule), |
||||
|
typeof(AbpDaprClientModule))] |
||||
|
public class AbpOpenIddictDaprClientModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddStaticDaprClientProxies( |
||||
|
typeof(AbpOpenIddictApplicationContractsModule).Assembly, |
||||
|
OpenIddictRemoteServiceConsts.RemoteServiceName); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Http.Client" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.OpenIddict.Application.Contracts\LINGYUN.Abp.OpenIddict.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Http.Client; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpOpenIddictApplicationContractsModule), |
||||
|
typeof(AbpHttpClientModule))] |
||||
|
public class AbpOpenIddictHttpApiClientModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddStaticHttpClientProxies( |
||||
|
typeof(AbpOpenIddictApplicationContractsModule).Assembly, |
||||
|
OpenIddictRemoteServiceConsts.RemoteServiceName); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,19 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.OpenIddict.Application.Contracts\LINGYUN.Abp.OpenIddict.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,38 @@ |
|||||
|
using Localization.Resources.AbpUi; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Localization; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.OpenIddict.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpOpenIddictApplicationContractsModule), |
||||
|
typeof(AbpAspNetCoreMvcModule))] |
||||
|
public class AbpOpenIddictHttpApiModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.AddAssemblyResource(typeof(AbpOpenIddictResource), typeof(AbpOpenIddictApplicationContractsModule).Assembly); |
||||
|
}); |
||||
|
|
||||
|
PreConfigure<IMvcBuilder>(mvcBuilder => |
||||
|
{ |
||||
|
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpOpenIddictHttpApiModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Get<AbpOpenIddictResource>() |
||||
|
.AddBaseTypes(typeof(AbpUiResource)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
using LINGYUN.Abp.OpenIddict.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Applications; |
||||
|
|
||||
|
[Controller] |
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Default)] |
||||
|
[RemoteService(Name = OpenIddictRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(OpenIddictRemoteServiceConsts.ModuleName)] |
||||
|
[Route("api/openiddict/applications")] |
||||
|
public class OpenIddictApplicationController : OpenIddictControllerBase, IOpenIddictApplicationAppService |
||||
|
{ |
||||
|
protected IOpenIddictApplicationAppService Service { get; } |
||||
|
|
||||
|
public OpenIddictApplicationController(IOpenIddictApplicationAppService service) |
||||
|
{ |
||||
|
Service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task<OpenIddictApplicationDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return Service.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public virtual Task<PagedResultDto<OpenIddictApplicationDto>> GetListAsync(OpenIddictApplicationGetListInput input) |
||||
|
{ |
||||
|
return Service.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Create)] |
||||
|
public virtual Task<OpenIddictApplicationDto> CreateAsync(OpenIddictApplicationCreateDto input) |
||||
|
{ |
||||
|
return Service.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Update)] |
||||
|
public virtual Task<OpenIddictApplicationDto> UpdateAsync(Guid id, OpenIddictApplicationUpdateDto input) |
||||
|
{ |
||||
|
return Service.UpdateAsync(id, input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(AbpOpenIddictPermissions.Applications.Delete)] |
||||
|
public virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return Service.DeleteAsync(id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using LINGYUN.Abp.OpenIddict.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.OpenIddict.Authorizations; |
||||
|
|
||||
|
[Controller] |
||||
|
[Authorize(AbpOpenIddictPermissions.Authorizations.Default)] |
||||
|
[RemoteService(Name = OpenIddictRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(OpenIddictRemoteServiceConsts.ModuleName)] |
||||
|
[Route("api/openiddict/authorizations")] |
||||
|
public class OpenIddictAuthorizationController : OpenIddictControllerBase, IOpenIddictAuthorizationAppService |
||||
|
{ |
||||
|
protected IOpenIddictAuthorizationAppService Service { get; } |
||||
|
|
||||
|
public OpenIddictAuthorizationController(IOpenIddictAuthorizationAppService service) |
||||
|
{ |
||||
|
Service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(AbpOpenIddictPermissions.Authorizations.Delete)] |
||||
|
public virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return Service.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task<OpenIddictAuthorizationDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return Service.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public virtual Task<PagedResultDto<OpenIddictAuthorizationDto>> GetListAsync(OpenIddictAuthorizationGetListInput input) |
||||
|
{ |
||||
|
return Service.GetListAsync(input); |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue