Former-commit-id: 94255d4d01e80d6060137164e11da923eb2cbb06
TangShanKaiPing
wanggang 6 years ago
parent 0690425149
commit c86e4774e1

@ -107,15 +107,7 @@ namespace Infrastructure.Web
o.SupportedUICultures = supportedCultures;
});
this.AddAuthentication(services);
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info
{
Title = this._cfg.GetValue<string>("openapi.title", "web api"),
Version = this._cfg.GetValue<string>("openapi.version", "1.0")
});
c.EnableAnnotations();
});
this.AddSwagger(services);
services.AddDistributedMemoryCache();
services.AddSession(options =>
{
@ -166,6 +158,19 @@ namespace Infrastructure.Web
});
}
public virtual void AddSwagger(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
c.SwaggerDoc(this._cfg.GetValue<string>("openapi.name", "v1"), new Info
{
Title = this._cfg.GetValue<string>("openapi.title", "web api"),
Version = this._cfg.GetValue<string>("openapi.version", "1.0")
});
c.EnableAnnotations();
});
}
public virtual void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Domain;
namespace Application.Domain.Entities
{
[Display(Name = "权限")]
public class Permission : BaseEntity, IDisableUpdate, IDisableDelete
{
public string Name { get; set; }
public string Number { get; set; }
public Guid? CategoryId { get; set; }
public PermissionCategory Category { get; set; } = new PermissionCategory();
public List<RolePermission> RolePermissions { get; set; } = new List<RolePermission>();
}
}

@ -0,0 +1,12 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Domain;
namespace Application.Domain.Entities
{
[Display(Name = "权限分类")]
public class PermissionCategory : BaseTreeEntity<PermissionCategory>
{
public List<Permission> Permissions { get; set; } = new List<Permission>();
}
}

@ -0,0 +1,14 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Domain;
namespace Application.Domain.Entities
{
[Display(Name = "角色")]
public class Role : BaseEntity
{
public string Name { get; set; }
public List<UserRole> UserRoles { get; set; } = new List<UserRole>();
public List<RolePermission> RolePermissions { get; set; } = new List<RolePermission>();
}
}

@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Domain;
namespace Application.Domain.Entities
{
[Display(Name = "角色权限")]
public class RolePermission : BaseEntity
{
public Guid RoleId { get; set; }
public Guid PermissionId { get; set; }
public Role Role { get; set; }
public Permission Permission { get; set; }
}
}

@ -0,0 +1,32 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Domain;
namespace Application.Domain.Entities
{
[Display(Name = "用户")]
public class User : BaseEntity, IDisableDelete
{
/// <summary>
/// 登录名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 加密混淆随机数
/// </summary>
public string SecurityStamp { get; set; }
/// <summary>
/// 加密密码
/// </summary>
public string PasswordHash { get; set; }
/// <summary>
/// 邮箱
/// </summary>
public string Email { get; set; }
public List<UserRole> UserRoles { get; set; } = new List<UserRole>();
}
}

@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Domain;
namespace Application.Domain.Entities
{
[Display(Name = "用户角色")]
public class UserRole : BaseEntity
{
public Guid UserId { get; set; }
public Guid RoleId { get; set; }
public User User { get; set; }
public Role Role { get; set; }
}
}

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
namespace Application.Models
{
[Display(Name = "修改密码")]
public class ChangePasswordModel
{
[Required(ErrorMessage = nameof(RequiredAttribute))]
[DataType(DataType.Password)]
[Display(Name = "当前密码")]
public string OldPassword { get; set; }
[Required(ErrorMessage = nameof(RequiredAttribute))]
[StringLength(100, MinimumLength = 6, ErrorMessage = "密码长度范围为{2}-{1}")]
[DataType(DataType.Password)]
[Display(Name = "新密码")]
public string NewPassword { get; set; }
[DataType(DataType.Password)]
[Display(Name = "确认新密码")]
[Compare(nameof(NewPassword), ErrorMessage = "{0}和{1}不符")]
public string ConfirmNewPassword { get; set; }
}
}

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using Infrastructure.Application;
namespace Application.Models
{
[Display(Name = "权限")]
public class EditPermissionModel : EditModel
{
[Display(Name = "分类")]
public string CategoryName { get; set; }
[Display(Name = "名称"), Required]
public string Name { get; set; }
[Display(Name = "编号"), Required]
public string Number { get; set; }
}
}

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Application;
namespace Application.Models
{
[Display(Name = "角色")]
public class EditRoleModel : EditModel
{
[Display(Name = "名称"), Required]
public string Name { get; set; }
[DataType("MultiSelectList")]
[Display(Name = "权限")]
public List<Guid> Permissions { get; set; } = new List<Guid>();
}
}

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Infrastructure.Application;
namespace Application.Models
{
[Display(Name = "用户")]
public class EditUserModel : EditModel
{
[Required(ErrorMessage = nameof(RequiredAttribute))]
[RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "")]
[StringLength(30, MinimumLength = 5, ErrorMessage = "用户名长度为5-30")]
[Display(Name = "用户名")]
public string UserName { get; set; }
[DataType("MultiSelectList")]
[Display(Name = "角色")]
public List<Guid> Roles { get; set; } = new List<Guid>();
}
}

@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
namespace Application.Models
{
[Display(Name = "忘记密码")]
public class ForgotPasswordModel
{
[Required(ErrorMessage = nameof(RequiredAttribute))]
[DataType(DataType.EmailAddress)]
[RegularExpression(@"^\w+@\w+\.\w+$", ErrorMessage = "邮箱格式错误")]
[Display(Name = "邮箱")]
[Remote("HasEmail", "Account", ErrorMessage = "邮箱不存在")]
public string Email { get; set; }
}
}

@ -0,0 +1,27 @@
using System.ComponentModel.DataAnnotations;
using Infrastructure.Web;
using Infrastructure.Web.DataAnnotations;
namespace Application.Models
{
[Display(Name = "登录")]
public class LoginModel
{
[Display(Name = "用户名")]
[Required(ErrorMessage = nameof(RequiredAttribute))]
public string UserName { get; set; }
[Display(Name = "密码")]
[Required(ErrorMessage = nameof(RequiredAttribute))]
[DataType(DataType.Password)]
public string Password { get; set; }
//[ImageCaptcha, UIHint("ImageCaptcha")]
//[Display(Name = "验证码")]
//[Required(ErrorMessage = nameof(RequiredAttribute))]
//public string ImageCaptcha { get; set; }
[Display(Name = "记住我")]
public bool RememberMe { get; set; }
}
}

@ -0,0 +1,42 @@
using System.ComponentModel.DataAnnotations;
using Infrastructure.Web.DataAnnotations;
using Infrastructure.Web.Mvc;
using Microsoft.AspNetCore.Mvc;
namespace Application.Models
{
[Display(Name = "邮箱注册")]
public class RegisterModel
{
[Required(ErrorMessage = nameof(RequiredAttribute))]
[RegularExpression("^[a-zA-Z0-9]+$", ErrorMessage = "")]
[StringLength(30, MinimumLength = 5, ErrorMessage = "用户名长度为5-30")]
[Display(Name = "用户名")]
[Remote("UserNameNotUsed", "Account", ErrorMessage = "用户名已存在")]
public string UserName { get; set; }
[Required(ErrorMessage = nameof(RequiredAttribute))]
[StringLength(100, MinimumLength = 6, ErrorMessage = "密码长度范围为{2}-{1}")]
[DataType(DataType.Password)]
[Display(Name = "登录密码")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "确认密码")]
[Compare("Password", ErrorMessage = "确认密码输入错误")]
public string ConfirmPassword { get; set; }
[Required(ErrorMessage = nameof(RequiredAttribute))]
[DataType(DataType.EmailAddress)]
[RegularExpression(@"^\w+@\w+\.\w+$", ErrorMessage = "邮箱格式错误")]
[Display(Name = "邮箱")]
[Remote("EmailNotUsed", "Account", ErrorMessage = "邮箱已占用")]
public string Email { get; set; }
[MustBeTrue(ErrorMessage = nameof(MustBeTrueAttribute))]
[AdditionalMetadata("用户服务协议", "/")]
[Display(Name = "我阅读并同意")]
[UIHint("MustBeTrue")]
public bool AgreeWith { get; set; }
}
}

@ -0,0 +1,24 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
namespace Application.Models
{
[Display(Name = "重设密码")]
public class ResetPasswordModel
{
[HiddenInput(DisplayValue = false)]
[ScaffoldColumn(true)]
public string Id { get; set; }
[Required(ErrorMessage = nameof(RequiredAttribute))]
[StringLength(100, MinimumLength = 6, ErrorMessage = "密码长度范围为{2}-{1}")]
[DataType(DataType.Password)]
[Display(Name = "登录密码")]
public string Password { get; set; }
[DataType(DataType.Password)]
[Display(Name = "确认密码")]
[Compare("Password", ErrorMessage = "确认密码输入错误")]
public string ConfirmPassword { get; set; }
}
}

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Application.Domain.Entities;
using Infrastructure.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace IoTNode.Areas.Admin.Controllers
{
[Area("Admin")]
public class AjaxController
{
private readonly ILogger<AjaxController> _logger;
private readonly IRepository<Role> _roleRepo;
private readonly IRepository<Permission> _permissionRepo;
public AjaxController(ILogger<AjaxController> logger,
IRepository<Role> roleRepo,
IRepository<Permission> permissionRepo)
{
this._logger = logger;
this._roleRepo = roleRepo;
this._permissionRepo = permissionRepo;
}
#region Role
public MultiSelectList GetRoleMultiSelectList(IEnumerable<Guid> selected)
{
if (selected == null)
{
selected = new List<Guid>();
}
var list = this._roleRepo.ReadOnlyTable()
.OrderBy(o => o.DisplayOrder)
.Select(o => new { o.Id, o.Name })
.ToList();
return new MultiSelectList(list, "Id", "Name", selected);
}
#endregion Role
#region Permission
public MultiSelectList GetPermissionMultiSelectList(IEnumerable<Guid> selectedValues)
{
if (selectedValues == null)
{
selectedValues = new List<Guid>();
}
var list = this._permissionRepo.Table()
.Include(o => o.Category)
.OrderBy(o => o.DisplayOrder)
.ThenBy(o => o.UpdatedOn)
.Select(o => new { o.Id, o.Name, Group = o.Category.Name })
.ToList();
return new MultiSelectList(list, "Id", "Name", selectedValues, "Group");
}
#endregion Permission
}
}

@ -0,0 +1,31 @@
using System.Linq;
using Infrastructure.Data;
using Infrastructure.Web.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Application.Domain.Entities;
using Application.Models;
using Infrastructure.Application;
namespace IoTNode.Areas.Admin.Controllers
{
[Authorize]
[Area(nameof(Admin))]
public class PermissionController : CrudController<Permission, PagedListModel<EditPermissionModel>, EditPermissionModel, EditPermissionModel>
{
public PermissionController(IRepository<Permission> repo) : base(repo)
{
}
public override IQueryable<Permission> Include(IQueryable<Permission> query)
{
return query.Include(o => o.Category).ThenInclude(o => o.Parent);
}
public override void ToModel(Permission entity, EditPermissionModel model)
{
model.CategoryName = entity.Category.GetFullName();
}
}
}

@ -0,0 +1,59 @@
using System.Linq;
using Infrastructure.Data;
using Infrastructure.Extensions;
using Infrastructure.Web.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Application.Domain.Entities;
using Application.Models;
using Infrastructure.Application;
namespace IoTNode.Areas.Admin.Controllers
{
[Authorize]
[Area(nameof(Admin))]
public class RoleController : CrudController<Role, PagedListModel<EditRoleModel>, EditRoleModel, EditRoleModel>
{
private readonly IRepository<Role> _roleRepo;
private readonly AjaxController _ajax;
public RoleController(IRepository<Role> roleRepo, AjaxController ajax) : base(roleRepo)
{
this._roleRepo = roleRepo;
this._ajax = ajax;
}
public override IQueryable<Role> Include(IQueryable<Role> query)
{
return query.Include(o => o.RolePermissions).ThenInclude(o => o.Permission).ThenInclude(o => o.Category).ThenInclude(o => o.Parent);
}
public override void ToModel(Role entity, EditRoleModel model)
{
if (entity != null)
{
model.Permissions = entity.RolePermissions.Select(o => o.PermissionId).ToList();
}
this.ViewData.MultiSelectList(o => model.Permissions, () => this._ajax.GetPermissionMultiSelectList(model.Permissions));
}
public override void ToEntity(EditRoleModel model, Role entity)
{
foreach (var id in entity.RolePermissions.Select(o => o.PermissionId).ToList())
{
if (!model.Permissions.Any(o => o == id))
{
entity.RolePermissions.RemoveAll(o => o.PermissionId == id);
}
}
foreach (var id in model.Permissions)
{
if (!entity.RolePermissions.Any(o => o.PermissionId == id))
{
entity.RolePermissions.Add(new RolePermission { PermissionId = id });
}
}
}
}
}

@ -0,0 +1,67 @@
using System.Linq;
using Application.Domain.Entities;
using Application.Models;
using Infrastructure.Application;
using Infrastructure.Data;
using Infrastructure.Extensions;
using Infrastructure.Security;
using Infrastructure.Web.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace IoTNode.Areas.Admin.Controllers
{
[Authorize]
[Area(nameof(Admin))]
public class UserController : CrudController<User, PagedListModel<EditUserModel>, EditUserModel, EditUserModel>
{
private readonly IRepository<User> _userRepo;
private readonly IEncryptionService _encrypitonService;
private readonly AjaxController _ajax;
public UserController(IRepository<User> userRepo, IEncryptionService encrypitonService, AjaxController ajax) : base(userRepo)
{
this._userRepo = userRepo;
this._encrypitonService = encrypitonService;
this._ajax = ajax;
}
public override IQueryable<User> Include(IQueryable<User> query)
{
return query.Include(o => o.UserRoles).ThenInclude(o => o.Role);
}
public override void ToModel(User entity, EditUserModel model)
{
if (entity != null)
{
model.Roles = entity.UserRoles.Select(o => o.RoleId).ToList();
}
this.ViewData.MultiSelectList(o => model.Roles, () => this._ajax.GetRoleMultiSelectList(model.Roles));
}
public override void ToEntity(EditUserModel model, User entity)
{
foreach (var id in entity.UserRoles.Select(o => o.RoleId).ToList())
{
if (!model.Roles.Any(o => o == id))
{
entity.UserRoles.RemoveAll(o => o.RoleId == id);
}
}
foreach (var id in model.Roles)
{
if (!entity.UserRoles.Any(o => o.RoleId == id))
{
entity.UserRoles.Add(new UserRole { RoleId = id });
}
}
}
public override void OnEdit(User entity, EditUserModel model)
{
model.UserName = entity.UserName;
}
}
}

@ -0,0 +1,317 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using Application.Domain.Entities;
using Application.Models;
using Infrastructure.Data;
using Infrastructure.Email;
using Infrastructure.Extensions;
using Infrastructure.Resources;
using Infrastructure.Security;
using Infrastructure.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Localization;
namespace IoT.UI.Shard.Controllers
{
[Authorize]
[ApiExplorerSettings(IgnoreApi = true)]
public class AccountController : BaseController
{
private readonly IConfiguration _configuration;
private readonly IRepository<User> _userRepo;
private readonly IStringLocalizer<Resource> _localizer;
private readonly IEncryptionService _encryptionService;
private readonly IEmailSender _emailSender;
public AccountController(IConfiguration configuration,
IRepository<User> userRepo,
IEncryptionService encryptionService,
IStringLocalizer<Resource> localizer,
IEmailSender emaliSender)
{
this._configuration = configuration;
this._userRepo = userRepo;
this._encryptionService = encryptionService;
this._localizer = localizer;
this._emailSender = emaliSender;
}
#region 权限不足
[AllowAnonymous]
public IActionResult AccessDenied(string returnUrl)
{
return View(model: returnUrl);
}
#endregion 权限不足
public IActionResult Index()
{
return View();
}
#region 注销
public IActionResult Logout()
{
HttpContext.SignOutAsync();
return RedirectToAction("Index", "Home");
}
#endregion 注销
#region 登录
[HttpGet]
[AllowAnonymous]
public IActionResult Login(string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[AllowAnonymous]
[HttpPost]
public IActionResult Login(LoginModel model, string returnUrl = null)
{
var userName = model.UserName;
var password = model.Password;
if (ModelState.IsValid)
{
try
{
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == userName);
if (user == null)
{
ModelState.AddModelError(nameof(model.UserName), this._localizer["用户不存在"]);
}
else
{
if (user.PasswordHash == this._encryptionService.CreatePasswordHash(password, user.SecurityStamp))
{
var userPermissions = this._userRepo.ReadOnlyTable().Where(o => o.UserName == userName)
.SelectMany(o => o.UserRoles)
.Select(o => o.Role)
.SelectMany(o => o.RolePermissions)
.Select(o => o.Permission.Number)
.ToList();
HttpContext.SignIn(model.UserName, userPermissions, model.RememberMe);
if (string.IsNullOrEmpty(returnUrl))
{
returnUrl = Url.Action("Index", "Home");
}
ViewBag.Url = returnUrl;
return Redirect(returnUrl);
}
else
{
ModelState.AddModelError(nameof(model.Password), this._localizer["密码错误"]);
}
}
}
catch (Exception ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
}
ViewData["ReturnUrl"] = returnUrl;
return View(model);
}
#endregion 登录
#region 注册
[AllowAnonymous]
public IActionResult Register()
{
return View();
}
[HttpPost]
[AllowAnonymous]
public IActionResult Register(RegisterModel model)
{
if (User.Identity.IsAuthenticated)
{
return RedirectTo("Index", "Home", "当前已登录,请退出");
}
if (ModelState.IsValid)
{
try
{
var user = new User().From(model);
user.SecurityStamp = this._encryptionService.CreateSalt();
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.Password, user.SecurityStamp);
user.Email = model.Email;
this._userRepo.Add(user);
this._userRepo.SaveChanges();
return RedirectTo("Login", "Account", "注册成功");
}
catch (Exception ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
}
return View(model);
}
#endregion 注册
#region 修改密码
public IActionResult ChangePassword()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
try
{
var user = this._userRepo.Table().FirstOrDefault(o => o.UserName == User.Identity.Name);
if (user.PasswordHash == this._encryptionService.CreatePasswordHash(model.OldPassword, user.SecurityStamp))
{
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.NewPassword, user.SecurityStamp);
this._userRepo.SaveChanges();
return RedirectTo(message: "密码修改成功");
}
else
{
ModelState.AddModelError(nameof(model.OldPassword), "当前密码输入错误");
}
}
catch (Exception ex)
{
ex.PrintStack();
ModelState.AddModelError("", ex.Message);
}
}
return View(model);
}
#endregion 修改密码
#region 忘记密码
[AllowAnonymous]
public IActionResult ForgotPassword()
{
return View();
}
[HttpPost]
[AllowAnonymous]
public IActionResult ForgotPassword(ForgotPasswordModel model)
{
if (ModelState.IsValid)
{
var url = Url.FullAction(nameof(ResetPassword), "Account", new { id = this._encryptionService.EncryptObject($"{model.Email}&{DateTime.UtcNow.AddMinutes(10).ToUnixTimeMilliseconds()}") });
this._emailSender.SendMail(this._configuration["Name"], this._configuration["EmailUser"], model.Email, $"{this._configuration["Name"]}找回密码", $"点击链接或复制链接到浏览器中10分钟内有效 <a href=\"{url}\">{url}</a> ", this._configuration["EmailHost"], this._configuration.GetValue<int>("EmailPort"), this._configuration["EmailUser"], this._configuration["EmailPassword"]);
Console.WriteLine(url);
ViewBag.Message = "重设密码邮件已经发送到您的邮箱中";
}
return View(model);
}
[AllowAnonymous]
public IActionResult ResetPassword(string id)
{
var values = this._encryptionService.DecryptObject<string>(id).Split('&');
var timestamp = long.Parse(values[1]);
if (DateTime.UtcNow.AddMinutes(10).ToUnixTimeMilliseconds() > timestamp)
{
return RedirectTo(controller: "Home", message: "链接已失效");
}
return View(new ResetPasswordModel { Id = id });
}
[AllowAnonymous]
[HttpPost]
public IActionResult ResetPassword(ResetPasswordModel model)
{
if (ModelState.IsValid)
{
var values = this._encryptionService.DecryptObject<string>(model.Id).Split('&');
var email = values[0];
var timestamp = long.Parse(values[1]);
if (DateTime.UtcNow.AddMinutes(10).ToUnixTimeMilliseconds() > timestamp)
{
return RedirectTo(controller: "Home", message: "链接已失效");
}
var user = this._userRepo.Table().FirstOrDefault(o => o.Email == email);
user.PasswordHash = this._encryptionService.CreatePasswordHash(model.Password, user.SecurityStamp);
this._userRepo.SaveChanges();
return RedirectTo(action: "Login", message: "密码设置成功");
}
return View(model);
}
#endregion 忘记密码
#region Ajax验证
[AllowAnonymous]
public JsonResult UserNameNotUsed([Required]string userName)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.UserName == userName));
}
return Json("用户名不能为空");
}
[AllowAnonymous]
public JsonResult EmailNotUsed([Required]string email)
{
if (ModelState.IsValid)
{
return Json(!this._userRepo.ReadOnlyTable().Any(o => o.Email == email));
}
return Json("邮箱不能为空");
}
[AllowAnonymous]
public JsonResult HasEmail([Required]string email)
{
if (ModelState.IsValid)
{
var user = this._userRepo.ReadOnlyTable().FirstOrDefault(o => o.Email == email);
if (user != null)
{
return Json(true);
}
return Json("邮箱不存在");
}
return Json("邮箱不能为空");
}
#endregion Ajax验证
[Route("/Login")]
[AllowAnonymous]
public IActionResult Test()
{
var userName = "admin";
var userPermissions = this._userRepo.ReadOnlyTable().Where(o => o.UserName == userName)
.SelectMany(o => o.UserRoles)
.Select(o => o.Role)
.SelectMany(o => o.RolePermissions)
.Select(o => o.Permission.Number)
.ToList();
HttpContext.SignIn(userName, userPermissions, true);
return RedirectToAction("Index", "Home");
}
}
}

@ -0,0 +1,148 @@
using Application.Domain.Entities;
using Infrastructure.Data;
using Infrastructure.Domain;
using Infrastructure.Email;
using Infrastructure.Extensions;
using Infrastructure.Security;
using Infrastructure.UI;
using Infrastructure.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace IoT.UI.Shard
{
public class IoTServiceStartup : BaseStartup
{
public IoTServiceStartup(IConfiguration configuration, IHostingEnvironment env) : base(configuration, env)
{
}
public override void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IEmailSender, EmptyEmailSender>();
base.ConfigureServices(services);
}
public override void ConfigureOptions(IServiceCollection services)
{
services.ConfigureOptions(new FileConfigureOptions(_env, new List<string> { "IoT.Shared" }));
}
public override void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
base.Configure(app, env, loggerFactory);
}
public override Task ValidatePrincipal(CookieValidatePrincipalContext arg)
{
return Task.Run(() =>
{
var userRepo = arg.HttpContext.RequestServices.GetService<IRepository<User>>();
var userName = arg.Principal.Identity.Name;
var userPermissions = userRepo.ReadOnlyTable().Where(o => o.UserName == userName)
.SelectMany(o => o.UserRoles)
.Select(o => o.Role)
.SelectMany(o => o.RolePermissions)
.Select(o => o.Permission.Number)
.ToList();
var currentPermissions = arg.Principal.Claims.Where(o => o.Type == "Role").Select(o => o.Value).ToList();
if (!currentPermissions.SequenceEqual(userPermissions))
{
arg.HttpContext.SignOutAsync();
arg.HttpContext.SignIn(userName, userPermissions, arg.Properties.IsPersistent);
}
});
}
public override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PermissionCategory>().HasOne(o => o.Parent).WithMany(o => o.Children).HasForeignKey(o => o.ParentId).OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<Permission>().HasOne(o => o.Category).WithMany(o => o.Permissions).HasForeignKey(o => o.CategoryId).OnDelete(DeleteBehavior.SetNull);
modelBuilder.Entity<UserRole>().HasOne(o => o.User).WithMany(o => o.UserRoles).HasForeignKey(o => o.UserId);
modelBuilder.Entity<UserRole>().HasOne(o => o.Role).WithMany(o => o.UserRoles).HasForeignKey(o => o.RoleId);
modelBuilder.Entity<RolePermission>().HasOne(o => o.Role).WithMany(o => o.RolePermissions).HasForeignKey(o => o.RoleId);
modelBuilder.Entity<RolePermission>().HasOne(o => o.Permission).WithMany(o => o.RolePermissions).HasForeignKey(o => o.PermissionId);
modelBuilder.Entity<User>().HasIndex(o => o.UserName).IsUnique();
modelBuilder.Entity<User>().HasIndex(o => o.Email).IsUnique();
modelBuilder.Entity<Role>().HasIndex(o => o.Name).IsUnique();
modelBuilder.Entity<PermissionCategory>().HasIndex(o => o.Number).IsUnique();
modelBuilder.Entity<Permission>().HasIndex(o => o.Number).IsUnique();
modelBuilder.Entity<UserRole>().HasIndex(o => new { o.UserId, o.RoleId }).IsUnique();
modelBuilder.Entity<RolePermission>().HasIndex(o => new { o.RoleId, o.PermissionId }).IsUnique();
}
public override void Seed(DbContext dbContext, IServiceProvider serviceProvider, IConfiguration configuration)
{
dbContext.Set<PermissionCategory>().Add(new PermissionCategory
{
Name = "配置",
Number = "Configuration",
Permissions = new List<Permission> {
new Permission { Name = "查询配置", Number = "ListConfiguration",DisplayOrder =1 },
new Permission { Name = "修改配置", Number = "EditConfiguration",DisplayOrder =2 }
}
}); int i = 1;
var skipReadCollection = new string[] { "Permission" };
var skipAddCollection = new string[] { "Permission", "Setting" };
foreach (var item in dbContext.Model.GetEntityTypes())
{
var type = item.ClrType;
var name = type.GetDisplayName();
var number = type.Name;
var category = new PermissionCategory
{
Name = name,
Number = type.Name,
DisplayOrder = i
};
category.Permissions.Add(new Permission { Name = $"查询{name}", Number = $"List{number}", DisplayOrder = 10 * i + 1 });
if (!skipReadCollection.Contains(type.Name))
{
category.Permissions.Add(new Permission { Name = $"查看{name}", Number = $"Read{number}", DisplayOrder = 10 * i + 2 });
}
if (!skipAddCollection.Contains(type.Name))
{
category.Permissions.Add(new Permission { Name = $"添加{name}", Number = $"Add{number}", DisplayOrder = 10 * i + 3 });
}
if (!typeof(IDisableUpdate).IsAssignableFrom(type))
{
category.Permissions.Add(new Permission { Name = $"修改{name}", Number = $"Edit{number}", DisplayOrder = 10 * i + 4 });
}
if (!typeof(IDisableDelete).IsAssignableFrom(type))
{
category.Permissions.Add(new Permission { Name = $"删除{name}", Number = $"Delete{number}", DisplayOrder = 10 * i + 5 });
}
dbContext.Set<PermissionCategory>().Add(category);
i += 1;
}
dbContext.SaveChanges();
var adminRole = new Role { Name = "管理员", IsReadOnly = true };
foreach (var item in dbContext.Set<Permission>())
{
adminRole.RolePermissions.Add(new RolePermission { Permission = item, IsReadOnly = true });
}
var encryptionService = serviceProvider.GetService<IEncryptionService>();
var securityStam = "123456";
dbContext.Set<User>().Add(new User
{
UserName = "admin",
SecurityStamp = securityStam,
PasswordHash = encryptionService.CreatePasswordHash("123456", securityStam),
Email = "test@test.com",
UserRoles = new List<UserRole> { new UserRole { Role = adminRole } }
});
dbContext.SaveChanges();
}
}
}

@ -0,0 +1,5 @@
@model ChangePasswordModel
@{
HtmlTitle = ViewContext.ViewData.ModelMetadata.ModelType.GetDisplayName();
}
@Html.EditorForModel()

@ -0,0 +1,8 @@
@model ForgotPasswordModel
@{
Layout = "/Views/Shared/_Layout.cshtml";
DisableBackUrl = true;
HtmlTitle = ViewContext.ViewData.ModelMetadata.ModelType.GetDisplayName();
}
@ViewBag.Message
@Html.EditorForModel()

@ -0,0 +1,3 @@
@{
HtmlTitle = "用户中心";
}

@ -0,0 +1,7 @@
@model LoginModel
@{
Layout = "/Views/Shared/_Layout.cshtml";
DisableBackUrl = true;
HtmlTitle = ViewContext.ViewData.ModelMetadata.ModelType.GetDisplayName();
}
@Html.EditorForModel()

@ -0,0 +1,7 @@
@model RegisterModel
@{
Layout = "/Views/Shared/_Layout.cshtml";
DisableBackUrl = true;
HtmlTitle = ViewContext.ViewData.ModelMetadata.ModelType.GetDisplayName();
}
@Html.EditorForModel()

@ -0,0 +1,7 @@
@model ResetPasswordModel
@{
Layout = "/Views/Shared/_Layout.cshtml";
DisableBackUrl = true;
HtmlTitle = ViewContext.ViewData.ModelMetadata.ModelType.GetDisplayName();
}
@Html.EditorForModel()

@ -0,0 +1,21 @@
<section class="sidebar" style="height: auto;">
<ul class="sidebar-menu" data-widget="tree">
<li class="@GetClass("Index")"><a href="@Url.Action("Index")"><i class="fa fa-circle-o"></i><span>用户中心</span></a></li>
<li class="@GetClass("ChangePassword")"><a href="@Url.Action("ChangePassword")"><i class="fa fa-circle-o"></i><span>修改密码</span></a></li>
</ul>
</section>
@functions{
public string GetClass(params string[] controllers)
{
if (controllers.Select(o => o.ToLower()).Contains(this.ViewContext.RouteData.Values["controller"].ToString().ToLower()))
{
if (controllers.Length > 1)
{
return "active open";
}
return "active";
}
return "";
}
}

@ -0,0 +1,56 @@
@inject IConfiguration cfg
@{
var total = cfg.GetValue<int>("CaptchaSeconds");
var sec = total;
var session = this.Context.Session;
var model = session.Get<CodeCaptchaModel>(CodeCaptchaModel.Key);
if (model != null)
{
sec = (int)(model.ExpireDateUtc - DateTime.UtcNow).TotalSeconds;
}
}
<script>
var total = @total;
var sec = @sec;
var timer;
function StartTimer(sec) {
if (sec > 0) {
$('#send-code').attr("disabled", "disabled").attr("value", "重发" + sec + "秒");
timer = setTimeout('StartTimer("' + (sec - 1) + '")', 1000);
}
else {
$('#send-code').removeAttr("disabled").attr("value", "发送验证码");
EndTimer();
}
}
function EndTimer() {
clearTimeout(timer);
}
$(function () {
if (sec > 0 && sec < total) {
StartTimer(sec);
}
});
$(function () {
$('#send-code').click(function () {
$(this).attr("disabled", "disabled");
if (!valid()) {
$(this).removeAttr("disabled");
return;
}
var url = getUrl();
$.getJSON(url, function (json) {
if (json.success) {
StartTimer(json.data);
}
else {
alert(json.data);
$(this).removeAttr("disabled");
}
}).fail(function () {
$(this).removeAttr("disabled")
});
return false;
});
});
</script>

@ -1,10 +1,9 @@
using Infrastructure.Domain;
using Infrastructure.Extensions;
using System;
using System.IO;
using System.ComponentModel.DataAnnotations;
namespace Application.Domain.Entities
{
[Display(Name = "设备")]
public class FBeeDevice : BaseEntity
{
public int DataType { get; set; }

@ -1,7 +1,9 @@
using Infrastructure.Domain;
using System.ComponentModel.DataAnnotations;
namespace Application.Domain.Entities
{
[Display(Name = "网管")]
public class Gateway : BaseEntity
{
public string Sn { get; set; }

@ -16,7 +16,6 @@
<ItemGroup>
<ProjectReference Include="..\..\..\Infrastructure\Infrastructure.csproj" />
<ProjectReference Include="..\..\IoT.Shared\IoT.Shared.csproj" />
<ProjectReference Include="..\..\IoT.UI.Shard\IoT.UI.Shard.csproj" />
</ItemGroup>
<ProjectExtensions><VisualStudio><UserProperties libman_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>

@ -14,7 +14,8 @@ namespace FBeeService
var host = Helper.Instance.GetLocalIP().ToString();
WebHost.CreateDefaultBuilder(args)
.Run<Startup>(new List<EFConfigurationValue> {
new EFConfigurationValue { Id = "openapi.title", Value= "web api" },
new EFConfigurationValue { Id = "openapi.name", Value= "v1" },
new EFConfigurationValue { Id = "openapi.title", Value= "fbee api" },
new EFConfigurationValue { Id = "openapi.version", Value= "1.0" },
new EFConfigurationValue { Id = "security:key", Value= "111111111111111111111111"},
new EFConfigurationValue { Id = "security:iv", Value= "11111111"},

@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging;
namespace FBeeService
{
public class Startup : ShardStartup
public class Startup : IoTServiceStartup
{
public Startup(IConfiguration configuration, IHostingEnvironment env) : base(configuration, env)
{
@ -29,9 +29,9 @@ namespace FBeeService
public override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Gateway>().HasIndex(o => o.Sn).IsUnique();
modelBuilder.Entity<FBeeDevice>().HasIndex(o => new { o.Sn, o.IEEE }).IsUnique();
base.OnModelCreating(modelBuilder);
}
}
}
Loading…
Cancel
Save