mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2026-07-29 06:38:00 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44d5b286aa | ||
|
|
5664792162 | ||
|
|
3be8644769 | ||
|
|
32e0ae1a6b | ||
|
|
ee396146d3 | ||
|
|
98808a65ea | ||
|
|
4dd882cf90 | ||
|
|
be1c79799d | ||
|
|
e84e5d47ee | ||
|
|
0570a58743 | ||
|
|
889445bbcf | ||
|
|
2d108586e7 | ||
|
|
18c6fbfaad | ||
|
|
50769b94c6 | ||
|
|
a5bbfad2ff | ||
|
|
89c3133889 | ||
|
|
7ad9b54fd2 |
@@ -37,6 +37,8 @@
|
||||
//流程实例知会用户
|
||||
public const string INSTANCE_NOTICE_USER = "INSTANCE_NOTICE_USER";
|
||||
//流程实例知会角色
|
||||
public const string INSTANCE_NOTICE_ROLE = "INSTANCE_NOTICE_ROLE";
|
||||
public const string INSTANCE_NOTICE_ROLE = "INSTANCE_NOTICE_ROLE";
|
||||
|
||||
public const string API = "API_RESOURCE";
|
||||
}
|
||||
}
|
||||
@@ -82,8 +82,8 @@ namespace OpenAuth.App
|
||||
TypeId = obj.TypeId,
|
||||
UpdateTime = DateTime.Now,
|
||||
UpdateUserId = user.Id,
|
||||
UpdateUserName = user.Name
|
||||
//todo:要修改的字段赋值
|
||||
UpdateUserName = user.Name,
|
||||
SortNo = obj.SortNo
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -3,35 +3,31 @@ using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Humanizer;
|
||||
using Infrastructure;
|
||||
using Infrastructure.Utilities;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OpenAuth.Repository;
|
||||
using OpenAuth.Repository.Core;
|
||||
using OpenAuth.Repository.Domain;
|
||||
using OpenAuth.Repository.QueryObj;
|
||||
using SqlSugar;
|
||||
|
||||
namespace OpenAuth.App
|
||||
{
|
||||
public class DbExtension
|
||||
{
|
||||
private List<DbContext> _contexts = new List<DbContext>();
|
||||
protected ISqlSugarClient SugarClient;
|
||||
|
||||
private IOptions<AppSetting> _appConfiguration;
|
||||
private IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
public DbExtension(IOptions<AppSetting> appConfiguration, OpenAuthDBContext openAuthDbContext, IHttpContextAccessor httpContextAccessor)
|
||||
public DbExtension(IOptions<AppSetting> appConfiguration, ISqlSugarClient sugarClient, IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
_appConfiguration = appConfiguration;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_contexts.Add(openAuthDbContext); //如果有多个DBContext,可以按OpenAuthDBContext同样的方式添加到_contexts中
|
||||
SugarClient = sugarClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,19 +39,18 @@ namespace OpenAuth.App
|
||||
public List<BuilderTableColumn> GetTableColumnsFromDb(string moduleName)
|
||||
{
|
||||
var result = new List<BuilderTableColumn>();
|
||||
const string domain = "openauth.repository.domain.";
|
||||
IEntityType entity = null;
|
||||
_contexts.ForEach(u =>
|
||||
{
|
||||
entity = u.Model.GetEntityTypes()
|
||||
.FirstOrDefault(u => u.Name.ToLower() == domain + moduleName.ToLower());
|
||||
});
|
||||
if (entity == null)
|
||||
|
||||
//获取所有继承了StringEntity的类型
|
||||
//单元测试时,这个一直报错????奇怪
|
||||
var entiTypes = typeof(StringEntity).Assembly.GetTypes().Where(u => typeof(StringEntity).IsAssignableFrom(u) && !u.IsAbstract).ToList();
|
||||
|
||||
var entityType = entiTypes.FirstOrDefault(u => u.Name.ToLower() == moduleName.ToLower());
|
||||
if (entityType == null)
|
||||
{
|
||||
throw new Exception($"未能找到{moduleName}对应的实体类");
|
||||
}
|
||||
|
||||
foreach (var property in entity.ClrType.GetProperties())
|
||||
foreach (var property in entityType.GetProperties())
|
||||
{
|
||||
object[] objs = property.GetCustomAttributes(typeof(DescriptionAttribute), true);
|
||||
object[] browsableObjs = property.GetCustomAttributes(typeof(BrowsableAttribute), true);
|
||||
@@ -82,29 +77,6 @@ namespace OpenAuth.App
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库DbContext中所有的实体名称。
|
||||
/// <para>注意!并不能获取数据库中的所有表</para>
|
||||
/// </summary>
|
||||
public List<string> GetDbEntityNames()
|
||||
{
|
||||
var names = new List<string>();
|
||||
var models = _contexts.Select(u => u.Model);
|
||||
|
||||
foreach (var model in models)
|
||||
{
|
||||
// Get all the entity types information contained in the DbContext class, ...
|
||||
var entityTypes = model.GetEntityTypes();
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
var tableNameAnnotation = entityType.GetAnnotation("Relational:TableName");
|
||||
names.Add(tableNameAnnotation.Value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库表结构信息
|
||||
/// </summary>
|
||||
@@ -184,15 +156,12 @@ namespace OpenAuth.App
|
||||
and utc.table_name = '{tableName}'
|
||||
order by column_id; ";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
|
||||
return new List<SysTableColumn>();
|
||||
@@ -250,16 +219,15 @@ namespace OpenAuth.App
|
||||
WHERE
|
||||
table_name = '{tableName}'";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new List<SysTableColumn>();
|
||||
|
||||
@@ -327,15 +295,12 @@ namespace OpenAuth.App
|
||||
and schema.nspname = 'public' -- replace 'your_schema' with your schema name
|
||||
and class.relname = '{tableName}'";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
columnList.ForEach(u => u.ColumnName = u.ColumnName.Transform(To.LowerCase, To.TitleCase));
|
||||
return columnList;
|
||||
}
|
||||
|
||||
return new List<SysTableColumn>();
|
||||
@@ -435,14 +400,11 @@ namespace OpenAuth.App
|
||||
WHERE obj.name = '{tableName}') AS t
|
||||
ORDER BY t.colorder";
|
||||
|
||||
foreach (var context in _contexts)
|
||||
var columns = SugarClient.SqlQueryable<SysTableColumn>(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
var columns = context.Set<SysTableColumn>().FromSqlRaw(sql);
|
||||
var columnList = columns?.ToList();
|
||||
if (columnList != null && columnList.Any())
|
||||
{
|
||||
return columnList;
|
||||
}
|
||||
return columnList;
|
||||
}
|
||||
return new List<SysTableColumn>();
|
||||
}
|
||||
|
||||
115
OpenAuth.App/ExtDataSourceApp/ExtDataSourceApp.cs
Normal file
115
OpenAuth.App/ExtDataSourceApp/ExtDataSourceApp.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using OpenAuth.App.Interface;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
using OpenAuth.Repository.Domain;
|
||||
using SqlSugar;
|
||||
|
||||
|
||||
namespace OpenAuth.App
|
||||
{
|
||||
public class ExtDataSourceApp : SqlSugarBaseApp<ExternalDataSource>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 加载列表
|
||||
/// </summary>
|
||||
public async Task<TableData> Load(QueryExternalDataSourceListReq request)
|
||||
{
|
||||
var loginContext = _auth.GetCurrentUser();
|
||||
if (loginContext == null)
|
||||
{
|
||||
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
var result = new TableData();
|
||||
var objs = GetDataPrivilege("u");
|
||||
if (!string.IsNullOrEmpty(request.key))
|
||||
{
|
||||
objs = objs.Where(u => u.Name.Contains(request.key));
|
||||
}
|
||||
|
||||
result.data = objs.OrderBy(u => u.Name)
|
||||
.Skip((request.page - 1) * request.limit)
|
||||
.Take(request.limit).ToList();
|
||||
result.count = await objs.CountAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TableData GetDbTypes()
|
||||
{
|
||||
var result = new TableData();
|
||||
// 创建包含键值对的列表
|
||||
var dbTypeList = Enum.GetValues(typeof(DbType))
|
||||
.Cast<DbType>()
|
||||
.Select(item => new { label = item.ToString(), value = (int)item })
|
||||
.ToList();
|
||||
result.data = dbTypeList;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 测试数据源连接
|
||||
/// </summary>
|
||||
/// <param name="id">数据源ID</param>
|
||||
/// <returns>是否连接成功</returns>
|
||||
public bool TestConnection(TestConnectionReq req)
|
||||
{
|
||||
var conn = new SqlSugarClient(new ConnectionConfig()
|
||||
{
|
||||
ConnectionString = req.Connectionstring,
|
||||
DbType = (DbType)Enum.Parse(typeof(DbType), req.Dbtype.ToString()),
|
||||
IsAutoCloseConnection = true,
|
||||
});
|
||||
conn.Open();
|
||||
return true;
|
||||
}
|
||||
public void Add(AddOrUpdateExternalDataSourceReq req)
|
||||
{
|
||||
var obj = req.MapTo<ExternalDataSource>();
|
||||
obj.Id = Guid.NewGuid().ToString();
|
||||
obj.Createtime = DateTime.Now;
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
obj.Createuserid = user.Id;
|
||||
obj.Createusername = user.Name;
|
||||
Repository.Insert(obj);
|
||||
}
|
||||
|
||||
public void Update(AddOrUpdateExternalDataSourceReq obj)
|
||||
{
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
Repository.Update(u => new ExternalDataSource
|
||||
{
|
||||
Name = obj.Name,
|
||||
Dbtype = obj.Dbtype,
|
||||
Databasename = obj.Databasename,
|
||||
Server = obj.Server,
|
||||
Port = obj.Port,
|
||||
Username = obj.Username,
|
||||
Password = obj.Password,
|
||||
Description = obj.Description,
|
||||
Enabled = obj.Enabled,
|
||||
Testsuccess = obj.Testsuccess,
|
||||
Connectionstring = obj.Connectionstring,
|
||||
Updatetime = DateTime.Now,
|
||||
Updateuserid = user.Id,
|
||||
Updateusername = user.Name
|
||||
},u => u.Id == obj.Id);
|
||||
|
||||
}
|
||||
|
||||
public ExtDataSourceApp(ISqlSugarClient client, IAuth auth) : base(client, auth)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public record TestConnectionReq(string Connectionstring, int Dbtype);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// This code was generated by a CodeSmith Template.
|
||||
//
|
||||
// DO NOT MODIFY contents of this file. Changes to this
|
||||
// file will be lost if the code is regenerated.
|
||||
// Author:Yubao Li
|
||||
//------------------------------------------------------------------------------
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using OpenAuth.Repository.Core;
|
||||
|
||||
namespace OpenAuth.App.Request
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
|
||||
public class AddOrUpdateExternalDataSourceReq
|
||||
{
|
||||
/// <summary>
|
||||
///是否测试成功
|
||||
/// </summary>
|
||||
public bool? Testsuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///主键
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///是否启用
|
||||
/// </summary>
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///连接字符串
|
||||
/// </summary>
|
||||
public string Connectionstring { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///描述
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///用户名
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///端口
|
||||
/// </summary>
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///服务器地址
|
||||
/// </summary>
|
||||
public string Server { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库名称
|
||||
/// </summary>
|
||||
public string Databasename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库类型
|
||||
/// </summary>
|
||||
public int Dbtype { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据源名称
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace OpenAuth.App.Request
|
||||
{
|
||||
public class QueryExternalDataSourceListReq : PageReq
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.6.23" />
|
||||
<PackageReference Include="Moq" Version="4.13.1" />
|
||||
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
|
||||
17
OpenAuth.App/Relevance/Request/AssignRoleResources.cs
Normal file
17
OpenAuth.App/Relevance/Request/AssignRoleResources.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace OpenAuth.App.Request
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色分配资源
|
||||
/// </summary>
|
||||
public class AssignRoleResources
|
||||
{
|
||||
/// <summary>
|
||||
/// 角色id
|
||||
/// </summary>
|
||||
public string RoleId { get; set; }
|
||||
/// <summary>
|
||||
/// 资源id列表
|
||||
/// </summary>
|
||||
public string[] ResourceIds { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -234,5 +234,28 @@ namespace OpenAuth.App
|
||||
UnitWork.Save();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 为角色分配资源,需要统一提交,会删除以前该角色的所有资源
|
||||
/// </summary>
|
||||
/// <param name="request"></param>
|
||||
public void AssignRoleResources(AssignRoleResources request)
|
||||
{
|
||||
UnitWork.ExecuteWithTransaction(() =>
|
||||
{
|
||||
//删除以前的所有资源
|
||||
UnitWork.Delete<Relevance>(u => u.FirstId == request.RoleId && u.Key == Define.ROLERESOURCE);
|
||||
//批量分配角色资源
|
||||
UnitWork.BatchAdd((from firstId in request.ResourceIds
|
||||
select new Relevance
|
||||
{
|
||||
Key = Define.ROLERESOURCE,
|
||||
FirstId = request.RoleId,
|
||||
SecondId = firstId,
|
||||
OperateTime = DateTime.Now
|
||||
}).ToArray());
|
||||
UnitWork.Save();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using NUnit.Framework;
|
||||
using OpenAuth.App.Interface;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
@@ -17,6 +19,16 @@ namespace OpenAuth.App
|
||||
public class ResourceApp:SqlSugarBaseApp<SysResource>
|
||||
{
|
||||
private RevelanceManagerApp _revelanceApp;
|
||||
private ApiService _apiService;
|
||||
|
||||
private readonly IAuth _auth;
|
||||
|
||||
public ResourceApp(ISqlSugarClient client, IAuth auth, RevelanceManagerApp revelanceApp, ApiService apiService) : base(client, auth)
|
||||
{
|
||||
_revelanceApp = revelanceApp;
|
||||
_apiService = apiService;
|
||||
_auth = auth;
|
||||
}
|
||||
|
||||
public void Add(AddOrUpdateResReq resource)
|
||||
{
|
||||
@@ -95,10 +107,92 @@ namespace OpenAuth.App
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResourceApp(ISqlSugarClient client, IAuth auth, RevelanceManagerApp revelanceApp) : base(client, auth)
|
||||
/// <summary>
|
||||
/// 获取资源类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<SysResourceApp>> GetResourceApps()
|
||||
{
|
||||
_revelanceApp = revelanceApp;
|
||||
var types = await SugarClient.Queryable<SysResource>()
|
||||
.Distinct()
|
||||
.Select(u => new {u.AppId,u.AppName})
|
||||
.ToListAsync();
|
||||
return types.Select(u => new SysResourceApp(u.AppId, u.AppName)).ToList();
|
||||
}
|
||||
/// <summary>
|
||||
/// 同步站点API到资源列表
|
||||
/// <para>读取站点API信息,如果资源列表中不存在,则添加</para>
|
||||
/// </summary>
|
||||
public async Task Sync()
|
||||
{
|
||||
var apis = await _apiService.GetSwaggerEndpoints();
|
||||
var user = _auth.GetCurrentUser().User;
|
||||
foreach (var api in apis)
|
||||
{
|
||||
//检查资源是否存在
|
||||
var resource = Repository.GetFirst(u => u.Name == api.Path && u.TypeId == Define.API);
|
||||
if (resource != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
resource = new SysResource
|
||||
{
|
||||
Id = api.Path,
|
||||
Name = api.Path,
|
||||
Disable = false,
|
||||
SortNo = 0,
|
||||
AppId = $"{Define.API}_{api.Tag}",
|
||||
AppName = $"API接口-{api.Tag}",
|
||||
TypeId = Define.API,
|
||||
TypeName = "API接口",
|
||||
Description = api.Summary??"",
|
||||
CreateTime = DateTime.Now,
|
||||
CreateUserId = user.Id,
|
||||
CreateUserName = user.Name
|
||||
};
|
||||
CaculateCascade(resource);
|
||||
Repository.Insert(resource);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断当前登录用户是否拥有访问该API的权限
|
||||
/// <para>如果角色没有做任何分配,则默认拥有权限。这个可以根据实际需要修改。</para>
|
||||
/// </summary>
|
||||
/// <param name="apiPath">API路径</param>
|
||||
/// <returns>true:拥有权限,false:没有权限</returns>
|
||||
public bool CanAccess(string apiPath)
|
||||
{
|
||||
var loginContext = _auth.GetCurrentUser();
|
||||
if (loginContext == null)
|
||||
{
|
||||
throw new CommonException("登录已过期", Define.INVALID_TOKEN);
|
||||
}
|
||||
|
||||
//如果当前登录用户是管理员,则拥有所有权限
|
||||
if(loginContext.User.Account == Define.SYSTEM_USERNAME){
|
||||
return true;
|
||||
}
|
||||
|
||||
var elementIds = _revelanceApp.Get(Define.ROLERESOURCE, true, loginContext.Roles.Select(u => u.Id).ToArray());
|
||||
//如果角色没有做任何分配,则默认拥有权限。这个可以根据实际需要修改。
|
||||
if(elementIds.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//如果分配了资源,则判断是否拥有权限
|
||||
var resource = Repository.GetFirst(u => u.Name.Contains(apiPath) && u.TypeId == Define.API && elementIds.Contains(u.Id));
|
||||
if(resource == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 资源类型
|
||||
/// </summary>
|
||||
public record SysResourceApp(string Id, string Name);
|
||||
}
|
||||
99
OpenAuth.App/System/ApiService.cs
Normal file
99
OpenAuth.App/System/ApiService.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.OpenApi.Readers;
|
||||
|
||||
public class ApiService
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public ApiService(IHttpClientFactory httpClientFactory, IConfiguration configuration)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有API接口信息
|
||||
/// <para>这个方法单元测试必须启动WebApi站点</para>
|
||||
/// </summary>
|
||||
public async Task<List<SwaggerEndpointInfo>> GetSwaggerEndpoints()
|
||||
{
|
||||
|
||||
var reader = new OpenApiStringReader();
|
||||
var client = _httpClientFactory.CreateClient();
|
||||
|
||||
var baseUrl = _configuration["AppSetting:HttpHost"]?.Replace("*", "localhost");
|
||||
|
||||
var apis = new List<SwaggerEndpointInfo>();
|
||||
var controllers = GetControllers();
|
||||
|
||||
foreach (var controller in controllers)
|
||||
{
|
||||
var groupname = GetSwaggerGroupName(controller);
|
||||
var swaggerJsonUrl = $"{baseUrl}/swagger/{groupname}/swagger.json";
|
||||
|
||||
var response = await client.GetAsync(swaggerJsonUrl).ConfigureAwait(false);
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var document = reader.Read(content, out var diagnostic);
|
||||
//获取所有api
|
||||
var controllerApis = document.Paths
|
||||
.SelectMany(path => path.Value.Operations
|
||||
.Select(op => new SwaggerEndpointInfo(
|
||||
path.Key,
|
||||
op.Key.ToString(),
|
||||
op.Value.Summary,
|
||||
op.Value.Description,
|
||||
op.Value.Tags.FirstOrDefault()?.Name)));
|
||||
|
||||
apis.AddRange(controllerApis);
|
||||
}
|
||||
|
||||
return apis;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取控制器对应的swagger分组值
|
||||
/// </summary>
|
||||
private string GetSwaggerGroupName(Type controller)
|
||||
{
|
||||
var groupname = controller.Name.Replace("Controller", "");
|
||||
var apisetting = controller.GetCustomAttribute(typeof(ApiExplorerSettingsAttribute));
|
||||
if (apisetting != null)
|
||||
{
|
||||
groupname = ((ApiExplorerSettingsAttribute)apisetting).GroupName;
|
||||
}
|
||||
|
||||
return groupname;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有的控制器
|
||||
/// </summary>
|
||||
private List<Type> GetControllers()
|
||||
{
|
||||
var webApiAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(a => a.GetName().Name.Contains("OpenAuth.WebApi"));
|
||||
|
||||
var controlleractionlist = webApiAssembly.GetTypes()
|
||||
.Where(type => typeof(Microsoft.AspNetCore.Mvc.ControllerBase).IsAssignableFrom(type))
|
||||
.ToList();
|
||||
|
||||
return controlleractionlist;
|
||||
}
|
||||
}
|
||||
|
||||
public record SwaggerEndpointInfo(
|
||||
string Path,
|
||||
string HttpMethod,
|
||||
string Summary,
|
||||
string Description,
|
||||
string Tag);
|
||||
@@ -19,15 +19,6 @@ namespace OpenAuth.App.Test
|
||||
var result = app.GetTableColumnsFromDb("Category");
|
||||
Console.WriteLine(JsonHelper.Instance.Serialize(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetDbEntityNames()
|
||||
{
|
||||
var app = _autofacServiceProvider.GetService<DbExtension>();
|
||||
|
||||
var result = app.GetDbEntityNames();
|
||||
Console.WriteLine(JsonHelper.Instance.Serialize(result));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestGetTables()
|
||||
|
||||
139
OpenAuth.Repository/Domain/ExternalDataSource.cs
Normal file
139
OpenAuth.Repository/Domain/ExternalDataSource.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using OpenAuth.Repository.Core;
|
||||
|
||||
namespace OpenAuth.Repository.Domain
|
||||
{
|
||||
/// <summary>
|
||||
///外部数据源
|
||||
/// </summary>
|
||||
[Table("ExternalDataSource")]
|
||||
public class ExternalDataSource : StringEntity
|
||||
{
|
||||
public ExternalDataSource()
|
||||
{
|
||||
this.Createtime = DateTime.Now;
|
||||
this.Createusername = "";
|
||||
this.Createuserid = "";
|
||||
this.Updateuserid = "";
|
||||
this.Updateusername = "";
|
||||
this.Testsuccess = false;
|
||||
this.Updatetime = DateTime.Now;
|
||||
this.Enabled = false;
|
||||
this.Connectionstring = "";
|
||||
this.Description = "";
|
||||
this.Password = "";
|
||||
this.Username = "";
|
||||
this.Port = null;
|
||||
this.Server = "";
|
||||
this.Databasename = "";
|
||||
this.Dbtype = 0;
|
||||
this.Name = "";
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
///创建时间
|
||||
/// </summary>
|
||||
[Description("创建时间")]
|
||||
public DateTime Createtime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///创建用户名
|
||||
/// </summary>
|
||||
[Description("创建用户名")]
|
||||
public string Createusername { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///创建用户ID
|
||||
/// </summary>
|
||||
[Description("创建用户ID")]
|
||||
public string Createuserid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///更新用户ID
|
||||
/// </summary>
|
||||
[Description("更新用户ID")]
|
||||
public string Updateuserid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///更新用户名
|
||||
/// </summary>
|
||||
[Description("更新用户名")]
|
||||
public string Updateusername { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///是否测试成功
|
||||
/// </summary>
|
||||
[Description("是否测试成功")]
|
||||
public bool? Testsuccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///最后测试时间
|
||||
/// </summary>
|
||||
[Description("最后测试时间")]
|
||||
public DateTime? Updatetime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///是否启用
|
||||
/// </summary>
|
||||
[Description("是否启用")]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///连接字符串
|
||||
/// </summary>
|
||||
[Description("连接字符串")]
|
||||
public string Connectionstring { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///描述
|
||||
/// </summary>
|
||||
[Description("描述")]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///密码
|
||||
/// </summary>
|
||||
[Description("密码")]
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///用户名
|
||||
/// </summary>
|
||||
[Description("用户名")]
|
||||
public string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///端口
|
||||
/// </summary>
|
||||
[Description("端口")]
|
||||
public int? Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///服务器地址
|
||||
/// </summary>
|
||||
[Description("服务器地址")]
|
||||
public string Server { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库名称
|
||||
/// </summary>
|
||||
[Description("数据库名称")]
|
||||
public string Databasename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据库类型
|
||||
/// </summary>
|
||||
[Description("数据库类型")]
|
||||
public int Dbtype { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///数据源名称
|
||||
/// </summary>
|
||||
[Description("数据源名称")]
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,26 @@ namespace OpenAuth.WebApi.Controllers
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 角色分配资源,整体提交,会覆盖之前的配置
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public Response AssignRoleResources([FromBody] AssignRoleResources request)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.AssignRoleResources(request);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 部门分配用户,整体提交,会覆盖之前的配置
|
||||
|
||||
143
OpenAuth.WebApi/Controllers/ExternalDataSourcesController.cs
Normal file
143
OpenAuth.WebApi/Controllers/ExternalDataSourcesController.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using OpenAuth.App;
|
||||
using OpenAuth.App.Request;
|
||||
using OpenAuth.App.Response;
|
||||
using OpenAuth.Repository.Domain;
|
||||
|
||||
namespace OpenAuth.WebApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// 外部数据源管理接口
|
||||
/// </summary>
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
[ApiExplorerSettings(GroupName = "外部数据源管理接口_ExternalDataSources")]
|
||||
public class ExternalDataSourcesController : ControllerBase
|
||||
{
|
||||
private readonly ExtDataSourceApp _app;
|
||||
|
||||
//获取详情
|
||||
[HttpGet]
|
||||
public Response<ExternalDataSource> Get(string id)
|
||||
{
|
||||
var result = new Response<ExternalDataSource>();
|
||||
try
|
||||
{
|
||||
result.Result = _app.Get(id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//添加
|
||||
[HttpPost]
|
||||
public Response Add([FromBody]AddOrUpdateExternalDataSourceReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Add(obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//测试连接
|
||||
[HttpPost]
|
||||
public Response TestConnection([FromBody]TestConnectionReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.TestConnection(obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//修改
|
||||
[HttpPost]
|
||||
public Response Update([FromBody]AddOrUpdateExternalDataSourceReq obj)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Update(obj);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载列表
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<TableData> Load([FromQuery]QueryExternalDataSourceListReq request)
|
||||
{
|
||||
return await _app.Load(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数据库类型
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public TableData GetDbTypes()
|
||||
{
|
||||
|
||||
return _app.GetDbTypes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public Response Delete([FromBody]string[] ids)
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
_app.Delete(ids);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ExternalDataSourcesController(ExtDataSourceApp app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -22,7 +22,7 @@ namespace OpenAuth.WebApi.Controllers
|
||||
{
|
||||
private readonly ResourceApp _app;
|
||||
|
||||
public ResourcesController(IAuth authUtil, ResourceApp app)
|
||||
public ResourcesController(ResourceApp app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
@@ -32,6 +32,28 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return await _app.Load(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步站点API到资源列表
|
||||
/// <para>读取站点API信息,如果资源列表中不存在,则添加</para>
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public async Task<Response> Sync()
|
||||
{
|
||||
var result = new Response();
|
||||
try
|
||||
{
|
||||
await _app.Sync();
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = ex.InnerException?.Message ?? ex.Message;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public Response Delete([FromBody]string[] ids)
|
||||
{
|
||||
@@ -104,5 +126,23 @@ namespace OpenAuth.WebApi.Controllers
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源所属应用
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<Response<List<SysResourceApp>>> GetResourceApps()
|
||||
{
|
||||
var result = new Response<List<SysResourceApp>>();
|
||||
try
|
||||
{
|
||||
result.Result = await _app.GetResourceApps();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
result.Code = 500;
|
||||
result.Message = e.InnerException?.Message ?? e.Message;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,13 @@ namespace OpenAuth.WebApi.Model
|
||||
private readonly IAuth _authUtil;
|
||||
private readonly SysLogApp _logApp;
|
||||
|
||||
public OpenAuthFilter(IAuth authUtil, SysLogApp logApp)
|
||||
private readonly ResourceApp _resourceApp;
|
||||
|
||||
public OpenAuthFilter(IAuth authUtil, SysLogApp logApp, ResourceApp resourceApp)
|
||||
{
|
||||
_authUtil = authUtil;
|
||||
_logApp = logApp;
|
||||
_resourceApp = resourceApp;
|
||||
}
|
||||
|
||||
public void OnActionExecuting(ActionExecutingContext context)
|
||||
@@ -28,9 +31,9 @@ namespace OpenAuth.WebApi.Model
|
||||
var Controllername = description.ControllerName.ToLower();
|
||||
var Actionname = description.ActionName.ToLower();
|
||||
|
||||
//匿名标识
|
||||
var authorize = description.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute));
|
||||
if (authorize != null)
|
||||
//匿名访问的不需要验证
|
||||
var allowAnonymous = description.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute));
|
||||
if (allowAnonymous != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -41,14 +44,29 @@ namespace OpenAuth.WebApi.Model
|
||||
context.Result = new JsonResult(new Response
|
||||
{
|
||||
Code = 401,
|
||||
Message = "认证失败,请提供认证信息"
|
||||
Message = "登录已过期,请重新登录"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var apiPath = $"{Controllername}/{Actionname}";
|
||||
//判断登录角色是否拥有访问该URL的权限
|
||||
var resource = _resourceApp.CanAccess(apiPath);
|
||||
if(!resource)
|
||||
{
|
||||
context.Result = new JsonResult(new Response
|
||||
{
|
||||
Code = 500,
|
||||
Message = $"当前用户没有访问{apiPath}的权限,请在【角色管理】中分配资源"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_logApp.Add(new SysLog
|
||||
{
|
||||
Content = $"用户访问",
|
||||
Href = $"{Controllername}/{Actionname}",
|
||||
Href = apiPath,
|
||||
CreateName = _authUtil.GetUserName(),
|
||||
CreateId = _authUtil.GetCurrentUser().User.Id,
|
||||
TypeName = "访问日志"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="3.1.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.6.23" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.0" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.2.22" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Description: 代码生成器自动生成动态头部列表
|
||||
* @Copyright (c) 2022 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
* @Description: OpenAuth.Pro代码生成器自动生成
|
||||
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
@@ -9,50 +9,25 @@
|
||||
<div class="search-box">
|
||||
<el-input @keyup.enter="handleFilter" size="small" class="custom-input w-200" :placeholder="'名称'"
|
||||
v-model="listQuery.key"></el-input>
|
||||
|
||||
<el-button size="small" class="custom-button filter-item" icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<el-button size="small" class="custom-button filter-item" icon="el-icon-search"
|
||||
@click="handleFilter">搜索</el-button>
|
||||
</div>
|
||||
<permission-btn v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</sticky>
|
||||
|
||||
<auth-table
|
||||
ref="mainTable"
|
||||
:select-type="'checkbox'"
|
||||
:table-fields="headerList"
|
||||
:data="list"
|
||||
:v-loading="listLoading"
|
||||
@row-click="rowClick"
|
||||
@selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit"
|
||||
@current-change="handleCurrentChange" />
|
||||
<auth-table ref="mainTableRef" :select-type="'checkbox'" :table-fields="headerList" :data="list"
|
||||
:v-loading="listLoading" @row-click="rowClick" @selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination v-show="total > 0" :total="total" v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
<el-dialog
|
||||
draggable
|
||||
class="dialog-mini"
|
||||
width="500px"
|
||||
:title="txtDlgTitle[dialogStatus]"
|
||||
v-model="dialogFormVisible">
|
||||
<auth-form
|
||||
ref="dataForm"
|
||||
:rules="rules"
|
||||
:edit-model="true"
|
||||
:form-fields="headerList"
|
||||
:data="temp"
|
||||
<el-dialog draggable class="dialog-mini" width="500px" :title="dialogStatus==0?'新增':'编辑'" v-model="dialogFormVisible">
|
||||
<auth-form ref="dataFormRef" :rules="rules" :edit-model="true" :form-fields="headerList" :data="temp"
|
||||
:col-num="2"></auth-form>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<el-button size="small" @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
v-if="dialogStatus == 'create'"
|
||||
type="primary"
|
||||
@click="createData">
|
||||
<el-button size="small" v-if="dialogStatus == 0" type="primary" @click="createData">
|
||||
确认
|
||||
</el-button>
|
||||
<el-button size="small" v-else type="primary" @click="updateData">
|
||||
@@ -76,46 +51,35 @@ import Sticky from '@/components/Sticky/index.vue'
|
||||
import permissionBtn from '@/components/PermissionBtn/index.vue'
|
||||
import AuthForm from '../../components/Base/AuthForm.vue'
|
||||
import AuthTable from '../../components/Base/AuthTable.vue'
|
||||
|
||||
const headerList = ref([]) //列表头
|
||||
const multipleSelection = ref([]) //列表checkbox选中的值
|
||||
const list = ref([]) //列表值
|
||||
const total = ref(0) //总条数
|
||||
const listLoading = ref(true) //进度条
|
||||
const dialogFormVisible = ref(false) //是否显示编辑框
|
||||
const dialogStatus = ref('')
|
||||
const dialogStatus = ref(0) //0:新增 1:编辑
|
||||
let temp = reactive({}) //新增(编辑)绑定对话框
|
||||
|
||||
const listQuery = reactive({
|
||||
// 查询条件
|
||||
page: 1,
|
||||
limit: 20,
|
||||
key: undefined,
|
||||
})
|
||||
|
||||
const txtDlgTitle = reactive({
|
||||
//对话框标题
|
||||
update: '编辑',
|
||||
create: '添加',
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||
})
|
||||
|
||||
//组件refs
|
||||
const mainTable = ref(null)
|
||||
const dataForm = ref(null)
|
||||
|
||||
const mainTableRef = ref(null)
|
||||
const dataFormRef = ref(null)
|
||||
onMounted(() => {
|
||||
headerList.value = [
|
||||
{HeaderList}
|
||||
{HeaderList}
|
||||
]
|
||||
getList()
|
||||
})
|
||||
|
||||
const rowClick = function (row) {
|
||||
mainTable.value.clearSelection()
|
||||
mainTable.value.toggleRowSelection(row)
|
||||
mainTableRef.value.clearSelection()
|
||||
mainTableRef.value.toggleRowSelection(row)
|
||||
}
|
||||
const handleSelectionChange = function (val) {
|
||||
multipleSelection.value = val
|
||||
@@ -127,27 +91,18 @@ const onBtnClicked = function (domId, callback) {
|
||||
break
|
||||
case 'btnEdit':
|
||||
if (multipleSelection.value.length !== 1) {
|
||||
ElMessage.error({
|
||||
message: '只能选中一个进行编辑',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('只能选中一个进行编辑')
|
||||
return
|
||||
}
|
||||
handleUpdate(multipleSelection.value[0])
|
||||
break
|
||||
case 'btnDel':
|
||||
if (multipleSelection.value.length < 1) {
|
||||
ElMessage.error({
|
||||
message: '至少删除一个',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('至少删除一个')
|
||||
return
|
||||
}
|
||||
handleDelete(multipleSelection.value)
|
||||
break
|
||||
case 'btnExport':
|
||||
mainTable.value.exportExcel('资源文件', callback)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -164,22 +119,12 @@ const handleFilter = function () {
|
||||
listQuery.page = 1
|
||||
getList()
|
||||
}
|
||||
const handleSizeChange = function (val) {
|
||||
listQuery.limit = val
|
||||
getList()
|
||||
}
|
||||
|
||||
const handleCurrentChange = function (val) {
|
||||
listQuery.page = val
|
||||
getList()
|
||||
}
|
||||
const handleModifyStatus = function (row, disable) {
|
||||
// 模拟修改状态
|
||||
ElMessage.success({
|
||||
message: '操作成功',
|
||||
type: 'success',
|
||||
})
|
||||
row.disable = disable
|
||||
}
|
||||
|
||||
const resetTemp = function () {
|
||||
let obj = {}
|
||||
headerList.value.forEach(item => {
|
||||
@@ -188,39 +133,30 @@ const resetTemp = function () {
|
||||
Object.assign(temp, obj)
|
||||
}
|
||||
const handleCreate = async function () {
|
||||
// 弹出添加框
|
||||
resetTemp()
|
||||
dialogStatus.value = 'create'
|
||||
dialogStatus.value = 0
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const createData = function () {
|
||||
// 保存提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
{TableName}s.add(temp).then(() => {
|
||||
list.value.unshift(temp)
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '创建成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('创建成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleUpdate = async function (row) {
|
||||
// 弹出编辑框
|
||||
Object.assign(temp, row) //必需这样赋值才能响应式
|
||||
dialogStatus.value = 'update'
|
||||
dialogStatus.value = 1
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const updateData = function () {
|
||||
// 更新提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
const tempData = Object.assign({}, temp)
|
||||
{TableName}s.update(tempData).then(() => {
|
||||
for (const v of list.value) {
|
||||
@@ -231,17 +167,11 @@ const updateData = function () {
|
||||
}
|
||||
}
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '更新成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('更新成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleDelete = function (rows) {
|
||||
// 多行删除
|
||||
delrows({TableName}s, rows)
|
||||
delrows({TableName}s, rows, getList)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!--
|
||||
* @Author: yubaolee <yubaolee@163.com> | ahfu~ <954478625@qq.com>
|
||||
* @Description: 代码生成器自动生成动态头部列表
|
||||
* @Copyright (c) 2022 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
* @Description: OpenAuth.Pro代码生成器自动生成
|
||||
* Copyright (c) 2025 by yubaolee | ahfu~ , All Rights Reserved.
|
||||
-->
|
||||
<template>
|
||||
<div class="flex flex-column">
|
||||
@@ -9,50 +9,25 @@
|
||||
<div class="search-box">
|
||||
<el-input @keyup.enter="handleFilter" size="small" class="custom-input w-200" :placeholder="'名称'"
|
||||
v-model="listQuery.key"></el-input>
|
||||
|
||||
<el-button size="small" class="custom-button filter-item" icon="el-icon-search" @click="handleFilter">搜索</el-button>
|
||||
<el-button size="small" class="custom-button filter-item" icon="el-icon-search"
|
||||
@click="handleFilter">搜索</el-button>
|
||||
</div>
|
||||
<permission-btn v-on:btn-event="onBtnClicked"></permission-btn>
|
||||
</sticky>
|
||||
|
||||
<auth-table
|
||||
ref="mainTable"
|
||||
:select-type="'checkbox'"
|
||||
:table-fields="headerList"
|
||||
:data="list"
|
||||
:v-loading="listLoading"
|
||||
@row-click="rowClick"
|
||||
@selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit"
|
||||
@current-change="handleCurrentChange" />
|
||||
<auth-table ref="mainTableRef" :select-type="'checkbox'" :table-fields="headerList" :data="list"
|
||||
:v-loading="listLoading" @row-click="rowClick" @selection-change="handleSelectionChange"></auth-table>
|
||||
<el-pagination v-show="total > 0" :total="total" v-model:currentPage="listQuery.page"
|
||||
v-model:page-size="listQuery.limit" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
<el-dialog
|
||||
draggable
|
||||
class="dialog-mini"
|
||||
width="500px"
|
||||
:title="txtDlgTitle[dialogStatus]"
|
||||
v-model="dialogFormVisible">
|
||||
<auth-form
|
||||
ref="dataForm"
|
||||
:rules="rules"
|
||||
:edit-model="true"
|
||||
:form-fields="headerList"
|
||||
:data="temp"
|
||||
<el-dialog draggable class="dialog-mini" width="500px" :title="dialogStatus==0?'新增':'编辑'" v-model="dialogFormVisible">
|
||||
<auth-form ref="dataFormRef" :rules="rules" :edit-model="true" :form-fields="headerList" :data="temp"
|
||||
:col-num="2"></auth-form>
|
||||
<template v-slot:footer>
|
||||
<div>
|
||||
<el-button size="small" @click="dialogFormVisible = false">
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
v-if="dialogStatus == 'create'"
|
||||
type="primary"
|
||||
@click="createData">
|
||||
<el-button size="small" v-if="dialogStatus == 0" type="primary" @click="createData">
|
||||
确认
|
||||
</el-button>
|
||||
<el-button size="small" v-else type="primary" @click="updateData">
|
||||
@@ -70,48 +45,41 @@ import { onMounted, ref, reactive, nextTick } from 'vue'
|
||||
import * as {TableName}s from '@/api/{TableName}s'
|
||||
import { defaultVal } from '@/utils/index'
|
||||
import { delrows } from '@/utils/delRows.js'
|
||||
import ColumnDefine from '@/interface/columnDefine'
|
||||
//引入组件
|
||||
import Sticky from '@/components/Sticky/index.vue'
|
||||
import permissionBtn from '@/components/PermissionBtn/index.vue'
|
||||
import AuthForm from '../../components/Base/AuthForm.vue'
|
||||
import AuthTable from '../../components/Base/AuthTable.vue'
|
||||
|
||||
const headerList = ref([]) //列表头
|
||||
const multipleSelection = ref([]) //列表checkbox选中的值
|
||||
const list = ref([]) //列表值
|
||||
const total = ref(0) //总条数
|
||||
const listLoading = ref(true) //进度条
|
||||
const dialogFormVisible = ref(false) //是否显示编辑框
|
||||
const dialogStatus = ref('')
|
||||
const dialogStatus = ref(0) //0:新增 1:编辑
|
||||
let temp = reactive({}) //新增(编辑)绑定对话框
|
||||
|
||||
const listQuery = reactive({
|
||||
// 查询条件
|
||||
page: 1,
|
||||
limit: 20,
|
||||
key: undefined,
|
||||
})
|
||||
|
||||
const txtDlgTitle = reactive({
|
||||
//对话框标题
|
||||
update: '编辑',
|
||||
create: '添加',
|
||||
})
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||
})
|
||||
|
||||
//组件refs
|
||||
const mainTable = ref(null)
|
||||
const dataForm = ref(null)
|
||||
|
||||
const mainTableRef = ref(null)
|
||||
const dataFormRef = ref(null)
|
||||
onMounted(() => {
|
||||
headerList.value = [
|
||||
{HeaderList}
|
||||
]
|
||||
getList()
|
||||
})
|
||||
|
||||
const rowClick = function (row) {
|
||||
mainTable.value.clearSelection()
|
||||
mainTable.value.toggleRowSelection(row)
|
||||
mainTableRef.value.clearSelection()
|
||||
mainTableRef.value.toggleRowSelection(row)
|
||||
}
|
||||
const handleSelectionChange = function (val) {
|
||||
multipleSelection.value = val
|
||||
@@ -123,27 +91,18 @@ const onBtnClicked = function (domId, callback) {
|
||||
break
|
||||
case 'btnEdit':
|
||||
if (multipleSelection.value.length !== 1) {
|
||||
ElMessage.error({
|
||||
message: '只能选中一个进行编辑',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('只能选中一个进行编辑')
|
||||
return
|
||||
}
|
||||
handleUpdate(multipleSelection.value[0])
|
||||
break
|
||||
case 'btnDel':
|
||||
if (multipleSelection.value.length < 1) {
|
||||
ElMessage.error({
|
||||
message: '至少删除一个',
|
||||
type: 'error',
|
||||
})
|
||||
ElMessage.error('至少删除一个')
|
||||
return
|
||||
}
|
||||
handleDelete(multipleSelection.value)
|
||||
break
|
||||
case 'btnExport':
|
||||
mainTable.value.exportExcel('资源文件', callback)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -167,22 +126,12 @@ const handleFilter = function () {
|
||||
listQuery.page = 1
|
||||
getList()
|
||||
}
|
||||
const handleSizeChange = function (val) {
|
||||
listQuery.limit = val
|
||||
getList()
|
||||
}
|
||||
|
||||
const handleCurrentChange = function (val) {
|
||||
listQuery.page = val
|
||||
getList()
|
||||
}
|
||||
const handleModifyStatus = function (row, disable) {
|
||||
// 模拟修改状态
|
||||
ElMessage.success({
|
||||
message: '操作成功',
|
||||
type: 'success',
|
||||
})
|
||||
row.disable = disable
|
||||
}
|
||||
|
||||
const resetTemp = function () {
|
||||
let obj = {}
|
||||
headerList.value.forEach(item => {
|
||||
@@ -191,39 +140,30 @@ const resetTemp = function () {
|
||||
Object.assign(temp, obj)
|
||||
}
|
||||
const handleCreate = async function () {
|
||||
// 弹出添加框
|
||||
resetTemp()
|
||||
dialogStatus.value = 'create'
|
||||
dialogStatus.value = 0
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const createData = function () {
|
||||
// 保存提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
{TableName}s.add(temp).then(() => {
|
||||
list.value.unshift(temp)
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '创建成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('创建成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleUpdate = async function (row) {
|
||||
// 弹出编辑框
|
||||
Object.assign(temp, row) //必需这样赋值才能响应式
|
||||
dialogStatus.value = 'update'
|
||||
dialogStatus.value = 1
|
||||
dialogFormVisible.value = true
|
||||
await nextTick()
|
||||
dataForm.value.clearValidate()
|
||||
dataFormRef.value.clearValidate()
|
||||
}
|
||||
const updateData = function () {
|
||||
// 更新提交
|
||||
dataForm.value.validate(() => {
|
||||
dataFormRef.value.validate(() => {
|
||||
const tempData = Object.assign({}, temp)
|
||||
{TableName}s.update(tempData).then(() => {
|
||||
for (const v of list.value) {
|
||||
@@ -234,17 +174,11 @@ const updateData = function () {
|
||||
}
|
||||
}
|
||||
dialogFormVisible.value = false
|
||||
ElNotification({
|
||||
title: '成功',
|
||||
message: '更新成功',
|
||||
type: 'success',
|
||||
duration: 2000,
|
||||
})
|
||||
ElNotification.success('更新成功')
|
||||
})
|
||||
})
|
||||
}
|
||||
const handleDelete = function (rows) {
|
||||
// 多行删除
|
||||
delrows({TableName}s, rows)
|
||||
delrows({TableName}s, rows, getList)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
🔥.Net权限管理及快速开发框架、最好用的权限工作流系统。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、智能打印、表单设计、工作流、定时任务等。架构易扩展,是中小企业的首选。
|
||||
🔥.Net权限管理及快速开发框架、最好用的权限工作流系统。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、API鉴权、智能打印、表单设计、工作流、定时任务等。架构易扩展,是中小企业的首选。
|
||||
|
||||

|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
* 超强的自定义权限控制功能,请参考:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
|
||||
|
||||
* 完整的字段权限控制,可以控制字段可见及API是否返回字段值
|
||||
* 完整API鉴权,可以控制角色可访问的API资源,及模块功能字段可见及是否返回,请参考:[按角色授权API资源](http://doc.openauth.net.cn/core/apiauth.html#%E6%8C%89%E8%A7%92%E8%89%B2%E6%8E%88%E6%9D%83api%E8%B5%84%E6%BA%90) 及 [字段权限](http://doc.openauth.net.cn/core/datapropertyrule.html)
|
||||
|
||||
* 可拖拽的表单设计。详情:[可拖拽表单](http://doc.openauth.net.cn/pro/dragform.html)
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
* 全网最好用的打印解决方案。详情:[智能打印](http://doc.openauth.net.cn/pro/printerplan.html)
|
||||
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能,请参考:[定时任务](http://doc.openauth.net.cn/core/job.html)
|
||||
|
||||
* 基于CodeSmith的代码生成功能,可快速生成带有头/明细结构的页面
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
* 支持多租户
|
||||
|
||||
* 集成IdentityServer4,实现基于OAuth2的登录体系
|
||||
* 支持搭建自己的IdentityServer服务器,实现基于OAuth2的登录体系,请参考:[登录认证及OAuth集成](http://doc.openauth.net.cn/core/identity.html)
|
||||
|
||||
* 建立三方对接规范,已有系统可以无缝对接流程引擎
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ features:
|
||||
- title: 紧随潮流
|
||||
details: 最新的.net sdk,配合最炫的vue框架。
|
||||
- title: 功能强大
|
||||
details: 角色授权、代码生成、智能打印、数据权限、拖拽表单、工作流引擎、定时任务。
|
||||
details: 角色授权、代码生成、API鉴权、智能打印、数据权限、拖拽表单、工作流引擎、定时任务。
|
||||
- title: 主流技术
|
||||
details: IdentityServer、EF、SqlSugar、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、VUE2、VUE3、Element-ui、Element-plus。
|
||||
footer: Copyright © 2025- yubaolee
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||

|
||||
|
||||
OpenAuth.Net是基于最新版.Net的开源权限工作流快速开发框架。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:组织机构、角色用户、权限授权、表单设计、工作流等。
|
||||
OpenAuth.Net是基于最新版.Net的开源权限工作流快速开发框架。源于Martin Fowler企业级应用开发思想及最新技术组合(SqlSugar、EF、Quartz、AutoFac、WebAPI、Swagger、Mock、NUnit、Vue2/3、Element-ui/plus、IdentityServer等)。核心模块包括:角色授权、代码生成、API鉴权、智能打印、表单设计、工作流、定时任务等。
|
||||
|
||||
开源版本演示:[http://demo.openauth.net.cn:1802/](http://demo.openauth.net.cn:1802/)
|
||||
|
||||
@@ -33,7 +33,7 @@ gitee上面两个版本。其中:
|
||||
|
||||
* 超强的自定义权限控制功能,请参考:[通用权限设计与实现](https://www.cnblogs.com/yubaolee/p/DataPrivilege.html)
|
||||
|
||||
* 完整的字段权限控制,可以控制字段可见及API是否返回字段值
|
||||
* 完整API鉴权,可以控制角色可访问的API资源,及模块功能字段可见及是否返回,请参考:[按角色授权API资源](http://doc.openauth.net.cn/core/apiauth.html#%E6%8C%89%E8%A7%92%E8%89%B2%E6%8E%88%E6%9D%83api%E8%B5%84%E6%BA%90) 及 [字段权限](http://doc.openauth.net.cn/core/datapropertyrule.html)
|
||||
|
||||
* 可拖拽的表单设计。详情:[可拖拽表单](http://doc.openauth.net.cn/pro/dragform.html)
|
||||
|
||||
@@ -41,7 +41,7 @@ gitee上面两个版本。其中:
|
||||
|
||||
* 全网最好用的打印解决方案。详情:[智能打印](http://doc.openauth.net.cn/pro/printerplan.html)
|
||||
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能
|
||||
* 基于Quartz.Net的定时任务控制,可随时启/停,可视化配置Cron表达式功能,请参考:[定时任务](http://doc.openauth.net.cn/core/job.html)
|
||||
|
||||
* 基于CodeSmith的代码生成功能,可快速生成带有头/明细结构的页面
|
||||
|
||||
@@ -51,7 +51,7 @@ gitee上面两个版本。其中:
|
||||
|
||||
* 支持多租户
|
||||
|
||||
* 集成IdentityServer4,实现基于OAuth2的登录体系
|
||||
* 支持搭建自己的IdentityServer服务器,实现基于OAuth2的登录体系,请参考:[登录认证及OAuth集成](http://doc.openauth.net.cn/core/identity.html)
|
||||
|
||||
* 建立三方对接规范,已有系统可以无缝对接流程引擎
|
||||
|
||||
|
||||
@@ -30,6 +30,15 @@ Host: localhost:52789
|
||||
X-Token: e4a5aa00
|
||||
|
||||
```
|
||||
## 按角色授权API资源
|
||||
|
||||
目前主流的接口平台都提供按角色(或账号)授权访问API的功能,OpenAuth.Net也不例外。在OpenAuth.Net中,接口API被当作资源处理。如图:
|
||||
|
||||

|
||||
|
||||
如果后端新增或删除API,点击【同步系统API资源】按钮,即可同步到资源列表中。在角色管理功能中,可以对登录的角色进行API资源授权。
|
||||
|
||||

|
||||
|
||||
## 不登录直接访问
|
||||
|
||||
|
||||
@@ -38,6 +38,25 @@ OpenAuth.Net支持两种登录认证方式:自定义token认证和基于Identi
|
||||
|
||||
当启用了Identity时,客户端调用API需要先通过OpenAuth.IdentityServer服务器的OAuth验证,才能调用接口。OpenAuth.Net调用API的客户端有两种:
|
||||
|
||||
#### OpenAuth.Pro vue3
|
||||
|
||||
在使用企业版vue界面访问OpenAuth.WebApi时,已经在文件`.env.dev`中配置好相关选项,可以直接使用,无需其他处理。
|
||||
|
||||
```python
|
||||
VITE_OIDC_AUTHORITY = http://localhost:12796 #Identity服务器地址
|
||||
VITE_OIDC_CLIENTID = OpenAuth.Pro #客户端名称
|
||||
VITE_OIDC_REDIRECTURI = http://localhost:1803 #登录回调
|
||||
VITE_OIDC_RESPONSETYPE = code #认证方式
|
||||
VITE_OIDC_SCOPE = openid profile openauthapi #认证范围
|
||||
VITE_OIDC_AUTOMATICSILENTRENEW = true #自动续期
|
||||
|
||||
```
|
||||
如果服务端启用了Identity认证,则打开登录界面如下:
|
||||

|
||||
|
||||
这时点击登录超链接,操作同OpenAuth.Mvc一样。
|
||||
|
||||
|
||||
#### SwaggerUI
|
||||
|
||||
当我们启动了OpenAuth.WebApi,在浏览器打开[http://localhost:52789/swagger/index.html](http://localhost:52789/swagger/index.html)时,其实是Swagger框架给我们生成的一个调动客户端,对于启用了Identity的服务,Swagger会有一个Authorise的操作按钮:
|
||||
@@ -54,21 +73,6 @@ OpenAuth.Net支持两种登录认证方式:自定义token认证和基于Identi
|
||||
|
||||

|
||||
|
||||
#### OpenAuth.Pro
|
||||
|
||||
在使用企业版vue界面访问OpenAuth.WebApi时,已经在文件`.env.dev`中配置好相关选项,可以直接使用,无需其他处理。
|
||||
|
||||
```python
|
||||
|
||||
VUE_APP_OIDC_AUTHORITY = http://localhost:12796 #Identity服务器地址
|
||||
VUE_APP_OIDC_CLIENTID = OpenAuth.Pro #客户端名称
|
||||
VUE_APP_OIDC_REDIRECTURI = http://localhost:1803/#/oidc-callback #登录回调
|
||||
VUE_APP_OIDC_POSTLOGOUTREDIRECTURI = http://localhost:1803 #退出登录回调
|
||||
VUE_APP_OIDC_RESPONSETYPE = code #认证方式
|
||||
VUE_APP_OIDC_SCOPE = openid profile openauthapi #认证范围
|
||||
VUE_APP_OIDC_AUTOMATICSILENTRENEW = true
|
||||
VUE_APP_OIDC_SILENTREDIRECTURI = http://localhost:1803/silent-renew-oidc.html
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
# 开发规范
|
||||
# 后端开发规范
|
||||
|
||||
## 新增数据库名称规范
|
||||
## 数据库表及字段命名
|
||||
|
||||
子系统名称+业务名称+表尾,其中表尾名称规则如下:
|
||||
SqlServer采用PascalCase命名,Oracle采用全大写命名,其他数据库采用camelCase命名。
|
||||
|
||||
::: tip 提示
|
||||
|
||||
开源版代码生成时,通过表结尾Dtbl来判断是否是生成明细表代码。因此建议数据库表命名时按:子系统名称+业务名称+表尾,其中表尾名称规则:
|
||||
- 基础主数据以Mst结尾;
|
||||
|
||||
- 普通业务表以Tbl结尾;
|
||||
|
||||
- 业务明细表以Dtbl结尾;
|
||||
|
||||
比如:
|
||||
|
||||
- WMS系统客户主数据表:WmsCustomerMst
|
||||
|
||||
- WMS系统入库订单头表:WmsInboundOrderTbl
|
||||
|
||||
- WMS系统入库订单明细表:WmsInboundOrderDtbl
|
||||
|
||||
如:WMS系统入库订单明细表:WmsInboundOrderDtbl
|
||||
:::
|
||||
|
||||
|
||||
## 数据库字段类型
|
||||
|
||||
Reference in New Issue
Block a user