diff --git a/docs/en/Getting-Started-Console-Application.md b/docs/en/Getting-Started-Console-Application.md index 006e447f0f..00c3d1e0a2 100644 --- a/docs/en/Getting-Started-Console-Application.md +++ b/docs/en/Getting-Started-Console-Application.md @@ -66,7 +66,7 @@ namespace AbpConsoleDemo ### Hello World! -The application above does nothing. Let's create a service does something: +The application above does nothing. Let's create a service that does something: ````C# using System; diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 9c8944176b..fa4e348f4b 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -34,6 +34,7 @@ "PagerPrevious": "Previous", "PagerInfo": "Showing {0} to {1} of {2} entries.", "DatatableActionDropdownDefaultText": "Actions", - "ChangePassword": "Change password" + "ChangePassword": "Change password", + "PersonalInfo": "Personal info" } } \ No newline at end of file diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index f85e255058..0215dfd071 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -34,6 +34,7 @@ "PagerPrevious": "Önceki", "PagerInfo": "{2} kayıttan {0} ile {1} arası gösteriliyor.", "DatatableActionDropdownDefaultText": "İşlemler", - "ChangePassword": "Şifre değiştir" + "ChangePassword": "Şifre değiştir", + "PersonalInfo": "Kişisel Bilgiler" } } \ No newline at end of file diff --git a/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs b/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs index d021cbabe1..2741aabe82 100644 --- a/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs +++ b/modules/account/src/Volo.Abp.Account.Web/AbpAccountUserMenuContributor.cs @@ -24,6 +24,8 @@ namespace Volo.Abp.Account.Web context.Menu.AddItem(new ApplicationMenuItem("Account.ChangePassword", l["ChangePassword"], icon: "fa fa-key", url: "#", elementId: "abp-account-change-password")); + context.Menu.AddItem(new ApplicationMenuItem("Account.PersonalSettings", l["PersonalInfo"], icon: "fa fa-info", url: "#", elementId: "abp-account-personal-settings")); + context.Menu.AddItem(new ApplicationMenuItem("Account.Logout", l["Logout"], url: "/Account/Logout", icon: "fa fa-power-off", order: int.MaxValue - 1000)); return Task.CompletedTask; diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181108104704_Identity_Changes.Designer.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181108104704_Identity_Changes.Designer.cs new file mode 100644 index 0000000000..4cd1b0c993 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181108104704_Identity_Changes.Designer.cs @@ -0,0 +1,694 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.BloggingTestApp.EntityFrameworkCore; + +namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(BloggingTestAppDbContext))] + [Migration("20181108104704_Identity_Changes")] + partial class Identity_Changes + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.1.1-rtm-30846") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256); + + b.Property("Regex") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasMaxLength(128); + + b.Property("Required"); + + b.Property("ValueType"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp"); + + b.Property("IsDefault") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256); + + b.Property("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasMaxLength(1024); + + b.Property("RoleId"); + + b.Property("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnName("AccessFailedCount") + .HasDefaultValue(0); + + b.Property("ConcurrencyStamp") + .IsRequired() + .HasColumnName("ConcurrencyStamp") + .HasMaxLength(256); + + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.Property("DeleterId"); + + b.Property("DeletionTime"); + + b.Property("Email") + .HasColumnName("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("EmailConfirmed") + .HasDefaultValue(false); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted"); + + b.Property("LastModificationTime"); + + b.Property("LastModifierId"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("LockoutEnabled") + .HasDefaultValue(false); + + b.Property("LockoutEnd"); + + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + + b.Property("NormalizedEmail") + .HasColumnName("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .IsRequired() + .HasColumnName("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash") + .HasColumnName("PasswordHash") + .HasMaxLength(256); + + b.Property("PhoneNumber") + .HasColumnName("PhoneNumber") + .HasMaxLength(16); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("PhoneNumberConfirmed") + .HasDefaultValue(false); + + b.Property("SecurityStamp") + .IsRequired() + .HasColumnName("SecurityStamp") + .HasMaxLength(256); + + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnName("TwoFactorEnabled") + .HasDefaultValue(false); + + b.Property("UserName") + .IsRequired() + .HasColumnName("UserName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256); + + b.Property("ClaimValue") + .HasMaxLength(1024); + + b.Property("TenantId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(64); + + b.Property("ProviderDisplayName") + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196); + + b.Property("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.Property("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(64); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("TenantId"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64); + + b.Property("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(64); + + b.Property("ProviderName") + .HasMaxLength(64); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("Volo.Blogging.Blogs.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnName("Description") + .HasMaxLength(1024); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnName("Name") + .HasMaxLength(256); + + b.Property("ShortName") + .IsRequired() + .HasColumnName("ShortName") + .HasMaxLength(32); + + b.HasKey("Id"); + + b.ToTable("BlgBlogs"); + }); + + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("PostId") + .HasColumnName("PostId"); + + b.Property("RepliedCommentId") + .HasColumnName("RepliedCommentId"); + + b.Property("Text") + .IsRequired() + .HasColumnName("Text") + .HasMaxLength(1024); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.HasIndex("RepliedCommentId"); + + b.ToTable("BlgComments"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BlogId") + .HasColumnName("BlogId"); + + b.Property("Content") + .HasColumnName("Content") + .HasMaxLength(1048576); + + b.Property("CoverImage") + .IsRequired() + .HasColumnName("CoverImage"); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("ReadCount"); + + b.Property("Title") + .IsRequired() + .HasColumnName("Title") + .HasMaxLength(512); + + b.Property("Url") + .IsRequired() + .HasColumnName("Url") + .HasMaxLength(64); + + b.HasKey("Id"); + + b.HasIndex("BlogId"); + + b.ToTable("BlgPosts"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b => + { + b.Property("PostId") + .HasColumnName("PostId"); + + b.Property("TagId") + .HasColumnName("TagId"); + + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.HasKey("PostId", "TagId"); + + b.HasIndex("TagId"); + + b.ToTable("BlgPostTags"); + }); + + modelBuilder.Entity("Volo.Blogging.Tagging.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CreationTime") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasColumnName("Description") + .HasMaxLength(512); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnName("IsDeleted") + .HasDefaultValue(false); + + b.Property("LastModificationTime") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasColumnName("Name") + .HasMaxLength(64); + + b.Property("UsageCount") + .HasColumnName("UsageCount"); + + b.HasKey("Id"); + + b.ToTable("BlgTags"); + }); + + modelBuilder.Entity("Volo.Blogging.Users.BlogUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Email") + .HasColumnName("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("EmailConfirmed") + .HasDefaultValue(false); + + b.Property("ExtraProperties") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + + b.Property("PhoneNumber") + .HasColumnName("PhoneNumber") + .HasMaxLength(16); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnName("PhoneNumberConfirmed") + .HasDefaultValue(false); + + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + + b.Property("TenantId") + .HasColumnName("TenantId"); + + b.Property("UserName") + .IsRequired() + .HasColumnName("UserName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.ToTable("BlgUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole") + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser") + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser") + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Volo.Abp.Identity.IdentityUser") + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser") + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Blogging.Comments.Comment", b => + { + b.HasOne("Volo.Blogging.Posts.Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Volo.Blogging.Comments.Comment") + .WithMany() + .HasForeignKey("RepliedCommentId"); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.Post", b => + { + b.HasOne("Volo.Blogging.Blogs.Blog") + .WithMany() + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Volo.Blogging.Posts.PostTag", b => + { + b.HasOne("Volo.Blogging.Posts.Post") + .WithMany("Tags") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Volo.Blogging.Tagging.Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181108104704_Identity_Changes.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181108104704_Identity_Changes.cs new file mode 100644 index 0000000000..8e7a402cd7 --- /dev/null +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/20181108104704_Identity_Changes.cs @@ -0,0 +1,170 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations +{ + public partial class Identity_Changes : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Name", + table: "BlgUsers", + maxLength: 64, + nullable: true); + + migrationBuilder.AddColumn( + name: "Surname", + table: "BlgUsers", + maxLength: 64, + nullable: true); + + migrationBuilder.AddColumn( + name: "CreationTime", + table: "AbpUsers", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.AddColumn( + name: "CreatorId", + table: "AbpUsers", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeleterId", + table: "AbpUsers", + nullable: true); + + migrationBuilder.AddColumn( + name: "DeletionTime", + table: "AbpUsers", + nullable: true); + + migrationBuilder.AddColumn( + name: "IsDeleted", + table: "AbpUsers", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "LastModificationTime", + table: "AbpUsers", + nullable: true); + + migrationBuilder.AddColumn( + name: "LastModifierId", + table: "AbpUsers", + nullable: true); + + migrationBuilder.AddColumn( + name: "Name", + table: "AbpUsers", + maxLength: 64, + nullable: true); + + migrationBuilder.AddColumn( + name: "Surname", + table: "AbpUsers", + maxLength: 64, + nullable: true); + + migrationBuilder.AddColumn( + name: "IsDefault", + table: "AbpRoles", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "IsPublic", + table: "AbpRoles", + nullable: false, + defaultValue: false); + + migrationBuilder.AddColumn( + name: "IsStatic", + table: "AbpRoles", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "AbpClaimTypes", + columns: table => new + { + Id = table.Column(nullable: false), + Name = table.Column(maxLength: 256, nullable: false), + Required = table.Column(nullable: false), + IsStatic = table.Column(nullable: false), + Regex = table.Column(maxLength: 512, nullable: true), + RegexDescription = table.Column(maxLength: 128, nullable: true), + Description = table.Column(maxLength: 256, nullable: true), + ValueType = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AbpClaimTypes", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpClaimTypes"); + + migrationBuilder.DropColumn( + name: "Name", + table: "BlgUsers"); + + migrationBuilder.DropColumn( + name: "Surname", + table: "BlgUsers"); + + migrationBuilder.DropColumn( + name: "CreationTime", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "CreatorId", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "DeleterId", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "DeletionTime", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "IsDeleted", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "LastModificationTime", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "LastModifierId", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "Name", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "Surname", + table: "AbpUsers"); + + migrationBuilder.DropColumn( + name: "IsDefault", + table: "AbpRoles"); + + migrationBuilder.DropColumn( + name: "IsPublic", + table: "AbpRoles"); + + migrationBuilder.DropColumn( + name: "IsStatic", + table: "AbpRoles"); + } + } +} diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs index b59ab48a69..7c57df160e 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Migrations/BloggingTestAppDbContextModelSnapshot.cs @@ -19,6 +19,35 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description") + .HasMaxLength(256); + + b.Property("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256); + + b.Property("Regex") + .HasMaxLength(512); + + b.Property("RegexDescription") + .HasMaxLength(128); + + b.Property("Required"); + + b.Property("ValueType"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => { b.Property("Id") @@ -26,6 +55,15 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ConcurrencyStamp"); + b.Property("IsDefault") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnName("IsStatic"); + b.Property("Name") .IsRequired() .HasMaxLength(256); @@ -81,6 +119,14 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("ConcurrencyStamp") .HasMaxLength(256); + b.Property("CreationTime"); + + b.Property("CreatorId"); + + b.Property("DeleterId"); + + b.Property("DeletionTime"); + b.Property("Email") .HasColumnName("Email") .HasMaxLength(256); @@ -93,6 +139,12 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("IsDeleted"); + + b.Property("LastModificationTime"); + + b.Property("LastModifierId"); + b.Property("LockoutEnabled") .ValueGeneratedOnAdd() .HasColumnName("LockoutEnabled") @@ -100,6 +152,10 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("LockoutEnd"); + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + b.Property("NormalizedEmail") .HasColumnName("NormalizedEmail") .HasMaxLength(256); @@ -127,6 +183,10 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("SecurityStamp") .HasMaxLength(256); + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + b.Property("TenantId") .HasColumnName("TenantId"); @@ -219,9 +279,10 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("UserId"); b.Property("LoginProvider") - .HasMaxLength(128); + .HasMaxLength(64); - b.Property("Name"); + b.Property("Name") + .HasMaxLength(128); b.Property("TenantId"); @@ -518,6 +579,10 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations b.Property("ExtraProperties") .HasColumnName("ExtraProperties"); + b.Property("Name") + .HasColumnName("Name") + .HasMaxLength(64); + b.Property("PhoneNumber") .HasColumnName("PhoneNumber") .HasMaxLength(16); @@ -527,6 +592,10 @@ namespace Volo.BloggingTestApp.EntityFrameworkCore.Migrations .HasColumnName("PhoneNumberConfirmed") .HasDefaultValue(false); + b.Property("Surname") + .HasColumnName("Surname") + .HasMaxLength(64); + b.Property("TenantId") .HasColumnName("TenantId"); diff --git a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj index f4de95d72b..0e83df5472 100644 --- a/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj +++ b/modules/blogging/app/Volo.BloggingTestApp.EntityFrameworkCore/Volo.BloggingTestApp.EntityFrameworkCore.csproj @@ -4,6 +4,10 @@ netstandard2.0 + + + + diff --git a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Users/BlogUser.cs b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Users/BlogUser.cs index cde09cdb4d..56f8287b19 100644 --- a/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Users/BlogUser.cs +++ b/modules/blogging/src/Volo.Blogging.Domain/Volo/Blogging/Users/BlogUser.cs @@ -14,6 +14,10 @@ namespace Volo.Blogging.Users public virtual string Email { get; protected set; } + public virtual string Name { get; set; } + + public virtual string Surname { get; set; } + public virtual bool EmailConfirmed { get; protected set; } public virtual string PhoneNumber { get; protected set; } @@ -31,6 +35,8 @@ namespace Volo.Blogging.Users { Id = user.Id; Email = user.Email; + Name = user.Name; + Surname = user.Surname; EmailConfirmed = user.EmailConfirmed; PhoneNumber = user.PhoneNumber; PhoneNumberConfirmed = user.PhoneNumberConfirmed; diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs new file mode 100644 index 0000000000..9e0a5cbacf --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IProfileAppService.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Application.Services; + +namespace Volo.Abp.Identity +{ + public interface IProfileAppService : IApplicationService + { + Task GetAsync(); + + Task UpdateAsync(UpdateProfileDto input); + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs index a3461fcd90..0715d2512a 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserCreateOrUpdateDtoBase.cs @@ -9,6 +9,12 @@ namespace Volo.Abp.Identity [StringLength(IdentityUserConsts.MaxUserNameLength)] public string UserName { get; set; } + [StringLength(IdentityUserConsts.MaxNameLength)] + public string Name { get; set; } + + [StringLength(IdentityUserConsts.MaxSurnameLength)] + public string Surname { get; set; } + [Required] [EmailAddress] [StringLength(IdentityUserConsts.MaxEmailLength)] diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs index 893d2ea710..bc28a79f8e 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/IdentityUserDto.cs @@ -4,12 +4,16 @@ using Volo.Abp.MultiTenancy; namespace Volo.Abp.Identity { - public class IdentityUserDto : EntityDto, IMultiTenant + public class IdentityUserDto : FullAuditedEntityDto, IMultiTenant { public Guid? TenantId { get; set; } public string UserName { get; set; } + public string Name { get; set; } + + public string Surname { get; set; } + public string Email { get; set; } public bool EmailConfirmed { get; set; } diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/ProfileDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/ProfileDto.cs new file mode 100644 index 0000000000..ac9b09e287 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/ProfileDto.cs @@ -0,0 +1,15 @@ +namespace Volo.Abp.Identity +{ + public class ProfileDto + { + public string UserName { get; set; } + + public string Email { get; set; } + + public string Name { get; set; } + + public string Surname { get; set; } + + public string PhoneNumber { get; set; } + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/UpdateProfileDto.cs b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/UpdateProfileDto.cs new file mode 100644 index 0000000000..40a576f871 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application.Contracts/Volo/Abp/Identity/UpdateProfileDto.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; + +namespace Volo.Abp.Identity +{ + public class UpdateProfileDto + { + [StringLength(IdentityUserConsts.MaxUserNameLength)] + public string UserName { get; set; } + + [StringLength(IdentityUserConsts.MaxEmailLength)] + public string Email { get; set; } + + [StringLength(IdentityUserConsts.MaxNameLength)] + public string Name { get; set; } + + [StringLength(IdentityUserConsts.MaxSurnameLength)] + public string Surname { get; set; } + + [StringLength(IdentityUserConsts.MaxPhoneNumberLength)] + public string PhoneNumber { get; set; } + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs index c20c4109f3..054ce247ac 100644 --- a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/IdentityUserAppService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Security.Authentication; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; @@ -149,6 +150,9 @@ namespace Volo.Abp.Identity (await _userManager.SetTwoFactorEnabledAsync(user, input.TwoFactorEnabled)).CheckErrors(); (await _userManager.SetLockoutEnabledAsync(user, input.LockoutEnabled)).CheckErrors(); + user.Name = input.Name; + user.Surname = input.Surname; + if (input.RoleNames != null) { (await _userManager.SetRolesAsync(user, input.RoleNames)).CheckErrors(); diff --git a/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs new file mode 100644 index 0000000000..d133350921 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Application/Volo/Abp/Identity/ProfileAppService.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Volo.Abp.Users; + +namespace Volo.Abp.Identity +{ + [Authorize] + public class ProfileAppService : IdentityAppServiceBase, IProfileAppService + { + private readonly IdentityUserManager _userManager; + + public ProfileAppService(IdentityUserManager userManager) + { + _userManager = userManager; + } + + public async Task GetAsync() + { + return ObjectMapper.Map( + await _userManager.GetByIdAsync(CurrentUser.GetId()) + ); + } + + public async Task UpdateAsync(UpdateProfileDto input) + { + var user = await _userManager.GetByIdAsync(CurrentUser.GetId()); + + (await _userManager.SetUserNameAsync(user, input.UserName)).CheckErrors(); + (await _userManager.SetEmailAsync(user, input.Email)).CheckErrors(); + (await _userManager.SetPhoneNumberAsync(user, input.PhoneNumber)).CheckErrors(); + user.Name = input.Name; + user.Surname = input.Surname; + + (await _userManager.UpdateAsync(user)).CheckErrors(); + await CurrentUnitOfWork.SaveChangesAsync(); + + return ObjectMapper.Map(user); + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityUserConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityUserConsts.cs index c41c63280d..f56a59e967 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityUserConsts.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityUserConsts.cs @@ -6,6 +6,10 @@ namespace Volo.Abp.Identity { public const int MaxUserNameLength = AbpUserConsts.MaxUserNameLength; + public const int MaxNameLength = AbpUserConsts.MaxNameLength; + + public const int MaxSurnameLength = AbpUserConsts.MaxSurnameLength; + public const int MaxNormalizedUserNameLength = MaxUserNameLength; public const int MaxEmailLength = AbpUserConsts.MaxEmailLength; diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs index a381ec66ba..dc93110075 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUser.cs @@ -8,12 +8,13 @@ using Microsoft.AspNetCore.Identity; using Volo.Abp.Auditing; using Volo.Abp.Data; using Volo.Abp.Domain.Entities; +using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Guids; using Volo.Abp.Users; namespace Volo.Abp.Identity { - public class IdentityUser : AggregateRoot, IHasConcurrencyStamp, IUser, IHasExtraProperties + public class IdentityUser : FullAuditedAggregateRoot, IHasConcurrencyStamp, IUser, IHasExtraProperties { public virtual Guid? TenantId { get; protected set; } @@ -28,6 +29,16 @@ namespace Volo.Abp.Identity [DisableAuditing] public virtual string NormalizedUserName { get; protected internal set; } + /// + /// Gets or sets the Name for the user. + /// + public virtual string Name { get; set; } + + /// + /// Gets or sets the Surame for the user. + /// + public virtual string Surname { get; set; } + /// /// Gets or sets the email address for this user. /// diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserExtensions.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserExtensions.cs index 3535bb5904..bdb1e9044e 100644 --- a/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi.Client/Volo/Abp/Identity/IdentityUserExtensions.cs @@ -10,6 +10,8 @@ namespace Volo.Abp.Identity user.Id, user.UserName, user.Email, + user.Name, + user.Surname, user.EmailConfirmed, user.PhoneNumber, user.PhoneNumberConfirmed, diff --git a/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs new file mode 100644 index 0000000000..449383956b --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.HttpApi/Volo/Abp/Identity/ProfileController.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; + +namespace Volo.Abp.Identity +{ + [RemoteService] + [Area("identity")] + [ControllerName("Profile")] + public class ProfileController : IProfileAppService + { + private readonly IProfileAppService _profileAppService; + + public ProfileController(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + public Task GetAsync() + { + return _profileAppService.GetAsync(); + } + + public Task UpdateAsync(UpdateProfileDto input) + { + return _profileAppService.UpdateAsync(input); + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs index c8651d8e88..4c991466e9 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebAutoMapperProfile.cs @@ -1,5 +1,6 @@ using AutoMapper; using Volo.Abp.Identity.Web.Pages.Identity.Roles; +using Volo.Abp.Identity.Web.Pages.Identity.Shared; using CreateUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.CreateModalModel; using EditUserModalModel = Volo.Abp.Identity.Web.Pages.Identity.Users.EditModalModel; @@ -11,6 +12,7 @@ namespace Volo.Abp.Identity.Web { CreateUserMappings(); CreateRoleMappings(); + CreateProfileMappings(); } private void CreateUserMappings() @@ -31,6 +33,10 @@ namespace Volo.Abp.Identity.Web CreateMap() .ForMember(dest => dest.IsAssigned, opt => opt.Ignore()); + + CreateMap(); + + CreateMap(); } private void CreateRoleMappings() @@ -44,5 +50,11 @@ namespace Volo.Abp.Identity.Web //EditModal CreateMap(); } + + private void CreateProfileMappings() + { + CreateMap(); + CreateMap(); + } } } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs index f898ad3ea3..934d0460b2 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/AbpIdentityWebModule.cs @@ -75,7 +75,8 @@ namespace Volo.Abp.Identity.Web options .ScriptBundles .Get(StandardBundles.Scripts.Global) - .AddFiles("/Pages/Identity/Shared/change-password-modal.js"); + .AddFiles("/Pages/Identity/Shared/change-password-modal.js") + .AddFiles("/Pages/Identity/Shared/personal-settings-modal.js"); }); } } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json index 3e97ea3700..e16e24134b 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/en.json @@ -13,10 +13,14 @@ "DisplayName:IsPublic": "Public", "Roles": "Roles", "Password": "Password", + "PersonalInfo": "Personal Info", + "PersonalSettings": "Personal settings", "UserDeletionConfirmationMessage": "User '{0}' will be deleted. Do you confirm that?", "RoleDeletionConfirmationMessage": "Role '{0}' will be deleted. Do you confirm that?", "DisplayName:RoleName": "Role name", "DisplayName:UserName": "User name", + "DisplayName:Name": "Name", + "DisplayName:Surname": "Surname", "DisplayName:Password": "Password", "DisplayName:EmailAddress": "Email address", "DisplayName:PhoneNumber": "Phone number", @@ -29,6 +33,7 @@ "DisplayName:CurrentPassword": "Current password", "DisplayName:NewPassword": "New password", "DisplayName:NewPasswordConfirm": "Confirm new password", - "PasswordChangedMessage": "Your password has been changed successfully." + "PasswordChangedMessage": "Your password has been changed successfully.", + "PersonalSettingsSavedMessage": "Your personal settings has been saved successfully." } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/tr.json b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/tr.json index e0ecf1b5cb..5393b25f43 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/tr.json +++ b/modules/identity/src/Volo.Abp.Identity.Web/Localization/Resources/AbpIdentity/tr.json @@ -13,10 +13,14 @@ "UserInformations": "Kullanıcı bilgileri", "Roles": "Roller", "Password": "Şifre", + "PersonalInfo": "Kişisel bilgi", + "PersonalSettings": "Kişisel Ayarlar", "UserDeletionConfirmationMessage": "{0} kullanıcısı silinecektir. Onaylıyor musunuz?", "RoleDeletionConfirmationMessage": "'{0}' rolü silinecektir. Onaylıyor musunuz?", "DisplayName:RoleName": "Rol adı", "DisplayName:UserName": "Kullanıcı adı", + "DisplayName:Name": "Adı", + "DisplayName:Surname": "Soyadı", "DisplayName:Password": "Şifre", "DisplayName:EmailAddress": "E-posta adresi", "DisplayName:PhoneNumber": "Telefon numarası", @@ -30,6 +34,7 @@ "DisplayName:NewPassword": "Yeni şifre", "DisplayName:NewPasswordConfirm": "Yeni şifre (tekrar)", "PasswordChangedMessage": "Şifreniz başarıyla değiştirildi.", + "PersonalSettingsSavedMessage": "Kişisel bilgileriniz başarıyla kaydedildi.", "Identity.StaticRoleRenamingErrorMessage": "Bir Sabit rolün ismi değiştirilemez.", "Identity.StaticRoleDeletionErrorMessage": "Bir Sabit rol silinemez." } diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml new file mode 100644 index 0000000000..e6d828dd39 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml @@ -0,0 +1,20 @@ +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal +@using Volo.Abp.Identity.Localization +@using Volo.Abp.Identity.Web.Pages.Identity.Shared +@model PersonalSettingsModal +@inject IHtmlLocalizer L +@{ + Layout = null; +} + + + + + + + + + + \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml.cs new file mode 100644 index 0000000000..6799b3a971 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/PersonalSettingsModal.cshtml.cs @@ -0,0 +1,66 @@ +using System.ComponentModel.DataAnnotations; +using System.Security.Authentication; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Localization; +using Volo.Abp.AspNetCore.Mvc.UI.RazorPages; +using Volo.Abp.Identity.Localization; + +namespace Volo.Abp.Identity.Web.Pages.Identity.Shared +{ + public class PersonalSettingsModal : AbpPageModel + { + [BindProperty] + public PersonalSettingsInfoModel PersonalSettingsInfoModel { get; set; } + + private readonly IProfileAppService _profileAppService; + + public PersonalSettingsModal(IProfileAppService profileAppService) + { + _profileAppService = profileAppService; + } + + public async Task OnGetAsync() + { + var user = await _profileAppService.GetAsync(); + + PersonalSettingsInfoModel = ObjectMapper.Map(user); + } + + public async Task OnPostAsync() + { + ValidateModel(); + + var updateDto = ObjectMapper.Map(PersonalSettingsInfoModel); + + await _profileAppService.UpdateAsync(updateDto); + + return NoContent(); + } + } + + public class PersonalSettingsInfoModel + { + [Required] + [StringLength(IdentityUserConsts.MaxUserNameLength)] + [Display(Name = "DisplayName:UserName")] + public string UserName { get; set; } + + [Required] + [StringLength(IdentityUserConsts.MaxEmailLength)] + [Display(Name = "DisplayName:Email")] + public string Email { get; set; } + + [StringLength(IdentityUserConsts.MaxNameLength)] + [Display(Name = "DisplayName:Name")] + public string Name { get; set; } + + [StringLength(IdentityUserConsts.MaxSurnameLength)] + [Display(Name = "DisplayName:Surname")] + public string Surname { get; set; } + + [StringLength(IdentityUserConsts.MaxPhoneNumberLength)] + [Display(Name = "DisplayName:PhoneNumber")] + public string PhoneNumber { get; set; } + } +} \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/personal-settings-modal.js b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/personal-settings-modal.js new file mode 100644 index 0000000000..36cd526a29 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Shared/personal-settings-modal.js @@ -0,0 +1,18 @@ +(function ($) { + + var l = abp.localization.getResource('AbpIdentity'); + var _personalSettingsModal = new abp.ModalManager(abp.appPath + 'Identity/Shared/PersonalSettingsModal'); + + $(function () { + + $("#abp-account-personal-settings").click(function (e) { + e.preventDefault(); + _personalSettingsModal.open(); + }); + + _personalSettingsModal.onResult(function () { + //abp.message.success(l("PersonalSettingsSavedMessage")); + }); + }); + +})(jQuery); diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml index 448d5c5633..ed45747c0c 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml @@ -15,6 +15,8 @@ @* TODO: Can we use dynamic form? *@ + + diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs index 15eb60a0b6..ce7a5a0507 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs @@ -56,6 +56,12 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users [StringLength(IdentityUserConsts.MaxUserNameLength)] public string UserName { get; set; } + [StringLength(IdentityUserConsts.MaxNameLength)] + public string Name { get; set; } + + [StringLength(IdentityUserConsts.MaxSurnameLength)] + public string Surname { get; set; } + [Required] [StringLength(IdentityUserConsts.MaxPasswordLength)] [DataType(DataType.Password)] diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml index 639918d8ad..afa0df85ed 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml @@ -14,12 +14,14 @@ @* TODO: Can we use dynamic form? *@ - - - - - - + + + + + + + + @for (var i = 0; i < Model.Roles.Length; i++) diff --git a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs index c9bac5c792..25615aca94 100644 --- a/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs +++ b/modules/identity/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs @@ -63,6 +63,12 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users [StringLength(IdentityUserConsts.MaxUserNameLength)] public string UserName { get; set; } + [StringLength(IdentityUserConsts.MaxNameLength)] + public string Name { get; set; } + + [StringLength(IdentityUserConsts.MaxSurnameLength)] + public string Surname { get; set; } + [Required] [EmailAddress] [StringLength(IdentityUserConsts.MaxEmailLength)] diff --git a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/ProfileAppService_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/ProfileAppService_Tests.cs new file mode 100644 index 0000000000..70f626ccbc --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/ProfileAppService_Tests.cs @@ -0,0 +1,97 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; +using NSubstitute; +using Shouldly; +using Volo.Abp.Users; +using Xunit; + +namespace Volo.Abp.Identity +{ + public class ProfileAppService_Tests : AbpIdentityApplicationTestBase + { + private readonly IProfileAppService _profileAppService; + private readonly IIdentityUserRepository _userRepository; + private readonly SignInManager _signInManager; + private readonly IdentityTestData _testData; + private ICurrentUser _currentUser; + + public ProfileAppService_Tests() + { + _profileAppService = GetRequiredService(); + _userRepository = GetRequiredService(); + _signInManager = GetRequiredService>(); + _testData = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + _currentUser = Substitute.For(); + services.AddSingleton(_currentUser); + } + + [Fact] + public async Task GetAsync() + { + //Arrange + _currentUser.Id.Returns(_testData.UserJohnId); + _currentUser.IsAuthenticated.Returns(true); + + //Act + var result = await _profileAppService.GetAsync(); + + //Assert + var johnNash = GetUser("john.nash"); + + result.UserName.ShouldBe(johnNash.UserName); + result.Email.ShouldBe(johnNash.Email); + result.PhoneNumber.ShouldBe(johnNash.PhoneNumber); + } + + + [Fact] + public async Task UpdateAsync() + { + //Arrange + + //Arrange + _currentUser.Id.Returns(_testData.UserJohnId); + _currentUser.IsAuthenticated.Returns(true); + + var input = new UpdateProfileDto + { + UserName = CreateRandomString(), + PhoneNumber = CreateRandomPhoneNumber(), + Email = CreateRandomEmail(), + Name = CreateRandomString(), + Surname = CreateRandomString() + }; + + //Act + var result = await _profileAppService.UpdateAsync(input); + + //Assert + result.UserName.ShouldBe(input.UserName); + result.Email.ShouldBe(input.Email); + result.PhoneNumber.ShouldBe(input.PhoneNumber); + result.Surname.ShouldBe(input.Surname); + result.Name.ShouldBe(input.Name); + } + + private static string CreateRandomEmail() + { + return CreateRandomString() + "@abp.io"; + } + + private static string CreateRandomString() + { + return Guid.NewGuid().ToString("N").Left(16); + } + + private static string CreateRandomPhoneNumber() + { + return RandomHelper.GetRandom(10000000, 100000000).ToString(); + } + } +} diff --git a/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/IUserData.cs b/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/IUserData.cs index e7c0d8dab7..f4f2874c7f 100644 --- a/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/IUserData.cs +++ b/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/IUserData.cs @@ -11,6 +11,10 @@ namespace Volo.Abp.Users string UserName { get; } + string Name { get; } + + string Surname { get; } + [CanBeNull] string Email { get; } diff --git a/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/UserData.cs b/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/UserData.cs index 7ed587cb9c..be70f20047 100644 --- a/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/UserData.cs +++ b/modules/users/src/Volo.Abp.Users.Abstractions/Volo/Abp/Users/UserData.cs @@ -9,6 +9,10 @@ namespace Volo.Abp.Users public string UserName { get; set; } + public string Name { get; set; } + + public string Surname { get; set; } + public string Email { get; set; } public bool EmailConfirmed { get; set; } @@ -28,6 +32,8 @@ namespace Volo.Abp.Users Guid id, [NotNull] string userName, [CanBeNull] string email = null, + [CanBeNull] string name = null, + [CanBeNull] string surname = null, bool emailConfirmed = false, [CanBeNull] string phoneNumber = null, bool phoneNumberConfirmed = false, @@ -36,6 +42,8 @@ namespace Volo.Abp.Users Id = id; UserName = userName; Email = email; + Name = name; + Surname = surname; EmailConfirmed = emailConfirmed; PhoneNumber = phoneNumber; PhoneNumberConfirmed = phoneNumberConfirmed; diff --git a/modules/users/src/Volo.Abp.Users.Domain.Shared/Volo/Abp/Users/AbpUserConsts.cs b/modules/users/src/Volo.Abp.Users.Domain.Shared/Volo/Abp/Users/AbpUserConsts.cs index 96fecdd60e..acfce7f37b 100644 --- a/modules/users/src/Volo.Abp.Users.Domain.Shared/Volo/Abp/Users/AbpUserConsts.cs +++ b/modules/users/src/Volo.Abp.Users.Domain.Shared/Volo/Abp/Users/AbpUserConsts.cs @@ -3,6 +3,10 @@ namespace Volo.Abp.Users public class AbpUserConsts { public const int MaxUserNameLength = 256; + + public const int MaxNameLength = 64; + + public const int MaxSurnameLength = 64; public const int MaxEmailLength = 256; diff --git a/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/AbpUserExtensions.cs b/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/AbpUserExtensions.cs index 19dea86bf5..41c3c30e3c 100644 --- a/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/AbpUserExtensions.cs +++ b/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/AbpUserExtensions.cs @@ -7,6 +7,8 @@ namespace Volo.Abp.Users return new UserData( user.Id, user.UserName, + user.Name, + user.Surname, user.Email, user.EmailConfirmed, user.PhoneNumber, diff --git a/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/IUser.cs b/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/IUser.cs index 374c41a0b7..2b06e8de97 100644 --- a/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/IUser.cs +++ b/modules/users/src/Volo.Abp.Users.Domain/Volo/Abp/Users/IUser.cs @@ -12,6 +12,12 @@ namespace Volo.Abp.Users [CanBeNull] string Email { get; } + [CanBeNull] + string Name { get; } + + [CanBeNull] + string Surname { get; } + bool EmailConfirmed { get; } [CanBeNull] diff --git a/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/AbpUsersDbContextModelCreatingExtensions.cs b/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/AbpUsersDbContextModelCreatingExtensions.cs index 1367fc423e..108b3f4278 100644 --- a/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/AbpUsersDbContextModelCreatingExtensions.cs +++ b/modules/users/src/Volo.Abp.Users.EntityFrameworkCore/Volo/Abp/Users/EntityFrameworkCore/AbpUsersDbContextModelCreatingExtensions.cs @@ -12,6 +12,8 @@ namespace Volo.Abp.Users.EntityFrameworkCore b.Property(u => u.TenantId).HasColumnName(nameof(IUser.TenantId)); b.Property(u => u.UserName).IsRequired().HasMaxLength(AbpUserConsts.MaxUserNameLength).HasColumnName(nameof(IUser.UserName)); b.Property(u => u.Email).HasMaxLength(AbpUserConsts.MaxEmailLength).HasColumnName(nameof(IUser.Email)); + b.Property(u => u.Name).HasMaxLength(AbpUserConsts.MaxNameLength).HasColumnName(nameof(IUser.Name)); + b.Property(u => u.Surname).HasMaxLength(AbpUserConsts.MaxSurnameLength).HasColumnName(nameof(IUser.Surname)); b.Property(u => u.EmailConfirmed).HasDefaultValue(false).HasColumnName(nameof(IUser.EmailConfirmed)); b.Property(u => u.PhoneNumber).HasMaxLength(AbpUserConsts.MaxPhoneNumberLength).HasColumnName(nameof(IUser.PhoneNumber)); b.Property(u => u.PhoneNumberConfirmed).HasDefaultValue(false).HasColumnName(nameof(IUser.PhoneNumberConfirmed));