Skip to content

Commit

Permalink
Merge pull request #964 from colinin/fix-pre-configured-wrapper
Browse files Browse the repository at this point in the history
Fix pre configured wrapper
  • Loading branch information
colinin committed Jun 5, 2024
2 parents 22fcb3b + d60a57b commit 0d9b8cb
Show file tree
Hide file tree
Showing 55 changed files with 288 additions and 180 deletions.
7 changes: 7 additions & 0 deletions aspnet-core/LINGYUN.MicroService.All.sln
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OpenApi.OpenIdd
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TextTemplating.Scriban", "modules\text-templating\LINGYUN.Abp.TextTemplating.Scriban\LINGYUN.Abp.TextTemplating.Scriban.csproj", "{15482834-9242-4D20-9736-9DA571A9A83A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{8A255A72-50FC-460E-9897-FA53F455580B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1892,6 +1894,10 @@ Global
{15482834-9242-4D20-9736-9DA571A9A83A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15482834-9242-4D20-9736-9DA571A9A83A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15482834-9242-4D20-9736-9DA571A9A83A}.Release|Any CPU.Build.0 = Release|Any CPU
{8A255A72-50FC-460E-9897-FA53F455580B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A255A72-50FC-460E-9897-FA53F455580B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A255A72-50FC-460E-9897-FA53F455580B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -2250,6 +2256,7 @@ Global
{FDAAAD2E-42A7-44EC-8971-B5277FD6D404} = {3C7A8246-DE82-4330-8697-24EF1B1C515D}
{ED3DF100-C5DB-4334-A847-118922B28D95} = {3C7A8246-DE82-4330-8697-24EF1B1C515D}
{15482834-9242-4D20-9736-9DA571A9A83A} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F}
{8A255A72-50FC-460E-9897-FA53F455580B} = {9D1302BE-3886-49F8-B0CD-35D2AC1E5A37}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}
Expand Down
9 changes: 8 additions & 1 deletion aspnet-core/LINGYUN.MicroService.TaskManagement.sln
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{6CC06BD8-FA30-45E0-BD3A-25FF39906EF5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.BackgroundTasks.Activities.Tests", "tests\LINGYUN.Abp.BackgroundTasks.Activities.Tests\LINGYUN.Abp.BackgroundTasks.Activities.Tests.csproj", "{3EBB4CA4-82C2-41C6-94C5-CB0D4D2B6D07}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundTasks.Activities.Tests", "tests\LINGYUN.Abp.BackgroundTasks.Activities.Tests\LINGYUN.Abp.BackgroundTasks.Activities.Tests.csproj", "{3EBB4CA4-82C2-41C6-94C5-CB0D4D2B6D07}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{34042B8E-B896-4E5E-A243-31E2802264CE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -398,6 +400,10 @@ Global
{3EBB4CA4-82C2-41C6-94C5-CB0D4D2B6D07}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3EBB4CA4-82C2-41C6-94C5-CB0D4D2B6D07}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3EBB4CA4-82C2-41C6-94C5-CB0D4D2B6D07}.Release|Any CPU.Build.0 = Release|Any CPU
{34042B8E-B896-4E5E-A243-31E2802264CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{34042B8E-B896-4E5E-A243-31E2802264CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34042B8E-B896-4E5E-A243-31E2802264CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34042B8E-B896-4E5E-A243-31E2802264CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -462,6 +468,7 @@ Global
{A8EFC95D-6700-4840-A7FD-1F5BF4D0C71C} = {77341F31-F54C-436A-AF8D-F78D91303C45}
{6CC06BD8-FA30-45E0-BD3A-25FF39906EF5} = {77341F31-F54C-436A-AF8D-F78D91303C45}
{3EBB4CA4-82C2-41C6-94C5-CB0D4D2B6D07} = {77341F31-F54C-436A-AF8D-F78D91303C45}
{34042B8E-B896-4E5E-A243-31E2802264CE} = {5A41C31A-B966-418B-B446-5BA1D7E61A62}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E1FD1F4C-D344-408B-97CF-B6F1F6D7D293}
Expand Down
7 changes: 7 additions & 0 deletions aspnet-core/LINGYUN.MicroService.WebhooksManagement.sln
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Http
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Security", "framework\security\LINGYUN.Abp.Security\LINGYUN.Abp.Security.csproj", "{8F11DADB-557A-4ECF-BEBB-19AFA71998A1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{047F892F-F8D2-4952-A1E9-93AA2B030F76}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -375,6 +377,10 @@ Global
{8F11DADB-557A-4ECF-BEBB-19AFA71998A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F11DADB-557A-4ECF-BEBB-19AFA71998A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8F11DADB-557A-4ECF-BEBB-19AFA71998A1}.Release|Any CPU.Build.0 = Release|Any CPU
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{047F892F-F8D2-4952-A1E9-93AA2B030F76}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -447,6 +453,7 @@ Global
{004CC7A9-92FF-4E98-8F1D-550D07CB47F0} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
{0DFDAC71-BCB9-44CF-A44A-E8288E75246F} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
{8F11DADB-557A-4ECF-BEBB-19AFA71998A1} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
{047F892F-F8D2-4952-A1E9-93AA2B030F76} = {FB7A9794-06D2-42CF-939E-4626497B97BD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {80ED12A5-C899-459F-A181-ADCC9D680DE5}
Expand Down
7 changes: 7 additions & 0 deletions aspnet-core/LINGYUN.MicroService.Workflow.sln
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Http
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Security", "framework\security\LINGYUN.Abp.Security\LINGYUN.Abp.Security.csproj", "{E4783690-052A-4AB0-837E-BDBC77CC7EEC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Claims.Mapping", "framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj", "{1859E205-88DC-4E08-A0BD-55A045DCC495}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -437,6 +439,10 @@ Global
{E4783690-052A-4AB0-837E-BDBC77CC7EEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E4783690-052A-4AB0-837E-BDBC77CC7EEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E4783690-052A-4AB0-837E-BDBC77CC7EEC}.Release|Any CPU.Build.0 = Release|Any CPU
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1859E205-88DC-4E08-A0BD-55A045DCC495}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -511,6 +517,7 @@ Global
{CAE0492C-11A3-424C-8613-7DAB83E4FB60} = {AD002164-CFB4-4583-BF13-62C815009ADE}
{4D055853-DE80-4145-BB2F-33EB6B379F5E} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
{E4783690-052A-4AB0-837E-BDBC77CC7EEC} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
{1859E205-88DC-4E08-A0BD-55A045DCC495} = {6DA78E72-BA55-4ECF-97DB-6258174D3E2A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6BB7A5DE-DA12-44DC-BC9B-0F6CA524346F}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Volo.Abp.Security" />
<PackageReference Include="IdentityModel" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Volo.Abp.Modularity;
using Volo.Abp.Security;

namespace LINGYUN.Abp.Claims.Mapping;

[DependsOn(typeof(AbpSecurityModule))]
public class AbpClaimsMappingModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
JwtClaimTypesMapping.MapAbpClaimTypes();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using IdentityModel;
using Volo.Abp.Security.Claims;

namespace LINGYUN.Abp.Claims.Mapping;

public static class JwtClaimTypesMapping
{
public static void MapAbpClaimTypes()
{
AbpClaimTypes.UserId = JwtClaimTypes.Subject;
AbpClaimTypes.Role = JwtClaimTypes.Role;
AbpClaimTypes.UserName = JwtClaimTypes.PreferredUserName;
AbpClaimTypes.Name = JwtClaimTypes.GivenName;
AbpClaimTypes.SurName = JwtClaimTypes.FamilyName;
AbpClaimTypes.PhoneNumber = JwtClaimTypes.PhoneNumber;
AbpClaimTypes.PhoneNumberVerified = JwtClaimTypes.PhoneNumberVerified;
AbpClaimTypes.Email = JwtClaimTypes.Email;
AbpClaimTypes.EmailVerified = JwtClaimTypes.EmailVerified;
AbpClaimTypes.ClientId = JwtClaimTypes.ClientId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# LINGYUN.Abp.Claims.Mapping

引入此模块解决*IdentityServer*身份令牌映射,需要配合 *MapInboundClaims* 使用

## 注意

身份认证服务器使用 *OpenIddict* 时无需处理

## 配置使用


```csharp
[DependsOn(typeof(AbpClaimsMappingModule))]
public class YouProjectModule : AbpModule
{
// other
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected async override Task<bool> CanPublishAsync(NotificationInfo notificatio
if (!await FeatureChecker.IsEnabledAsync(PushPlusFeatureNames.Message.Enable))
{
Logger.LogWarning(
"{0} cannot push messages because the feature {0} is not enabled",
"{0} cannot push messages because the feature {1} is not enabled",
Name,
PushPlusFeatureNames.Message.Enable);
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ public WeChatMiniProgramNotificationPublishProvider(

protected async override Task<bool> CanPublishAsync(NotificationInfo notification, CancellationToken cancellationToken = default)
{
if (!await FeatureChecker.IsEnabledAsync(WeChatMiniProgramFeatures.Messages.Enable))
if (!await FeatureChecker.IsEnabledAsync(true,
WeChatMiniProgramFeatures.Enable,
WeChatMiniProgramFeatures.Messages.Enable))
{
Logger.LogWarning(
"{0} cannot push messages because the feature {0} is not enabled",
"{0} cannot push messages because the feature {1} is not enabled",
Name,
WeChatMiniProgramFeatures.Messages.Enable);
return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using LINGYUN.Abp.RealTime.Localization;
using LINGYUN.Abp.WeChat.Work;
using LINGYUN.Abp.WeChat.Work.Authorize;
using LINGYUN.Abp.WeChat.Work.Features;
using LINGYUN.Abp.WeChat.Work.Messages;
using LINGYUN.Abp.WeChat.Work.Messages.Models;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -40,6 +42,21 @@ public WeChatWorkNotificationPublishProvider(
WeChatWorkOptions = weChatWorkOptions.CurrentValue;
}

protected async override Task<bool> CanPublishAsync(NotificationInfo notification, CancellationToken cancellationToken = default)
{
if (!await FeatureChecker.IsEnabledAsync(true,
WeChatWorkFeatureNames.Enable,
WeChatWorkFeatureNames.Message.Enable))
{
Logger.LogWarning(
"{0} cannot push messages because the feature {1} is not enabled",
Name,
WeChatWorkFeatureNames.Message.Enable);
return false;
}
return true;
}

protected async override Task PublishAsync(
NotificationInfo notification,
IEnumerable<UserIdentifier> identifiers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ public WxPusherNotificationPublishProvider(

protected async override Task<bool> CanPublishAsync(NotificationInfo notification, CancellationToken cancellationToken = default)
{
if (!await FeatureChecker.IsEnabledAsync(WxPusherFeatureNames.Message.Enable))
if (!await FeatureChecker.IsEnabledAsync(true,
WxPusherFeatureNames.Enable,
WxPusherFeatureNames.Message.Enable))
{
Logger.LogWarning(
"{0} cannot push messages because the feature {1} is not enabled",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,17 +440,9 @@ private void ConfigureSecurity(IServiceCollection services, IConfiguration confi
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = false;
options.Audience = configuration["AuthServer:ApiName"];
options.MapInboundClaims = false;
configuration.GetSection("AuthServer").Bind(options);
});

if (isDevelopment)
{
// services.AddAlwaysAllowAuthorization();
}

if (!isDevelopment)
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using LINGYUN.Abp.AspNetCore.Mvc.Localization;
using LINGYUN.Abp.AuditLogging.Elasticsearch;
using LINGYUN.Abp.Authorization.OrganizationUnits;
using LINGYUN.Abp.Claims.Mapping;
using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Identity;
Expand Down Expand Up @@ -61,6 +62,7 @@ namespace LY.MicroService.AuthServer;
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpLocalizationCultureMapModule),
typeof(AbpAspNetCoreHttpOverridesModule),
typeof(AbpClaimsMappingModule),
typeof(AbpAutofacModule)
)]
public partial class AuthServerHttpApiHostModule : AbpModule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<ProjectReference Include="..\..\framework\localization\LINGYUN.Abp.Localization.CultureMap\LINGYUN.Abp.Localization.CultureMap.csproj" />
<ProjectReference Include="..\..\framework\logging\LINGYUN.Abp.Serilog.Enrichers.Application\LINGYUN.Abp.Serilog.Enrichers.Application.csproj" />
<ProjectReference Include="..\..\framework\logging\LINGYUN.Abp.Serilog.Enrichers.UniqueId\LINGYUN.Abp.Serilog.Enrichers.UniqueId.csproj" />
<ProjectReference Include="..\..\framework\security\LINGYUN.Abp.Claims.Mapping\LINGYUN.Abp.Claims.Mapping.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,10 @@
"InstanceName": "LINGYUN.Abp.Application"
},
"AuthServer": {
"Authority": "http://127.0.0.1:44385",
"ApiName": "lingyun-abp-application"
"Authority": "http://127.0.0.1:44385/",
"Audience": "lingyun-abp-application",
"MapInboundClaims": false,
"RequireHttpsMetadata": false
},
"AuditLogging": {
"Elasticsearch": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,21 +391,6 @@ private void ConfigureUrls(IConfiguration configuration)
}
private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false)
{
//services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);

//services.AddAuthentication()
// .AddJwtBearer(options =>
// {
// options.Authority = configuration["AuthServer:Authority"];
// options.RequireHttpsMetadata = false;
// options.Audience = configuration["AuthServer:ApiName"];
// });

if (isDevelopment)
{
// services.AddAlwaysAllowAuthorization();
}

if (!isDevelopment)
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
Expand Down
Loading

0 comments on commit 0d9b8cb

Please sign in to comment.