Support User related functions.
This commit is contained in:
parent
c03be389ca
commit
8046ddafe6
|
|
@ -24,7 +24,7 @@ BotSharp is in accordance with components principle strictly, decouples every pa
|
|||
* Built-in multi-agents and conversation management.
|
||||
* Support multiple LLM platforms.
|
||||
* Support export/ import agent from other bot platforms directly.
|
||||
* Support different open source UI [Chatbot UI](src\Plugins\BotSharp.Plugin.ChatbotUI\Chatbot-UI.md), [HuggingChat UI](src\Plugins\BotSharp.Plugin.HuggingFace\HuggingChat-UI.md).
|
||||
* Support different open source UI [Chatbot UI](src/Plugins/BotSharp.Plugin.ChatbotUI/Chatbot-UI.md), [HuggingChat UI](src/Plugins/BotSharp.Plugin.HuggingFace/HuggingChat-UI.md).
|
||||
* Integrate with popular message channels like Facebook Messenger, Slack and Telegram.
|
||||
|
||||
### Quick Started
|
||||
|
|
@ -34,7 +34,7 @@ BotSharp is in accordance with components principle strictly, decouples every pa
|
|||
PS D:\> cd BotSharp
|
||||
PS D:\BotSharp\> dotnet run -p .\src\WebStarter
|
||||
```
|
||||
2. Run UI project, reference to [Chatbot UI](src\Plugins\BotSharp.Plugin.ChatbotUI\Chatbot-UI.md).
|
||||
2. Run UI project, reference to [Chatbot UI](src/Plugins/BotSharp.Plugin.ChatbotUI/Chatbot-UI.md).
|
||||
|
||||
### Extension Libraries
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Agents;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -5,7 +7,7 @@ namespace BotSharp.Abstraction.Agents;
|
|||
/// </summary>
|
||||
public interface IAgentService
|
||||
{
|
||||
void NewAgent();
|
||||
void DeleteAgent();
|
||||
void UpdateAgent();
|
||||
Task<string> CreateAgent(Agent agent);
|
||||
Task<bool> DeleteAgent(string id);
|
||||
Task UpdateAgent(Agent agent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
namespace BotSharp.Abstraction.Users;
|
||||
|
||||
public interface ICurrentUser
|
||||
{
|
||||
string Id { get; }
|
||||
string Email { get; }
|
||||
string FirstName { get; }
|
||||
string LastName { get; }
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.Abstraction.Users;
|
||||
|
||||
public interface IUserService
|
||||
{
|
||||
Task<User> CreateUser(User user);
|
||||
Task<Token> GetToken(string authorization);
|
||||
Task<User> GetMyProfile();
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace BotSharp.Abstraction.Users.Models;
|
||||
|
||||
public class Token
|
||||
{
|
||||
public string AccessToken { get; set; } = string.Empty;
|
||||
public string RefreshToken { get; set; } = string.Empty;
|
||||
public string TokenType { get; set; } = string.Empty;
|
||||
public int ExpireTime { get; set; }
|
||||
public string Scope { get; set; } = string.Empty;
|
||||
}
|
||||
13
src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
Normal file
13
src/Infrastructure/BotSharp.Abstraction/Users/Models/User.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
namespace BotSharp.Abstraction.Users.Models;
|
||||
|
||||
public class User
|
||||
{
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string Salt { get; set; } = string.Empty;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
|
||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
24
src/Infrastructure/BotSharp.Core/Agents/AgentController.cs
Normal file
24
src/Infrastructure/BotSharp.Core/Agents/AgentController.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.ApiAdapters;
|
||||
using BotSharp.Core.Agents.ViewModels;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BotSharp.Core.Agents;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class AgentController : ControllerBase, IApiAdapter
|
||||
{
|
||||
private readonly IAgentService _agentService;
|
||||
public AgentController(IAgentService agentService)
|
||||
{
|
||||
_agentService = agentService;
|
||||
}
|
||||
|
||||
[HttpPost("/agent")]
|
||||
public async Task<string> CreateAgent(AgentCreationModel agent)
|
||||
{
|
||||
return await _agentService.CreateAgent(agent.ToAgent());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Agents.Models;
|
||||
using BotSharp.Core.Repository;
|
||||
using BotSharp.Core.Repository.Abstraction;
|
||||
using BotSharp.Core.Repository.DbTables;
|
||||
using EntityFrameworkCore.BootKit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace BotSharp.Core.Agents.Services;
|
||||
|
||||
public class AgentService : IAgentService
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
public AgentService(IServiceProvider services)
|
||||
{
|
||||
_services = services;
|
||||
}
|
||||
|
||||
public async Task<string> CreateAgent(Agent agent)
|
||||
{
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var record = AgentRecord.FromAgent(agent);
|
||||
|
||||
db.Transaction<IAgentTable>(delegate
|
||||
{
|
||||
db.Add<IAgentTable>(record);
|
||||
});
|
||||
|
||||
return record.Id;
|
||||
}
|
||||
|
||||
public Task<bool> DeleteAgent(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task UpdateAgent(Agent agent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
|
||||
namespace BotSharp.Core.Agents.ViewModels;
|
||||
|
||||
public class AgentCreationModel
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
||||
public Agent ToAgent()
|
||||
{
|
||||
return new Agent
|
||||
{
|
||||
Name = Name,
|
||||
Description = Description
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace BotSharp.Core.Agents.ViewModels;
|
||||
|
||||
public class AgentUpdateModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
namespace BotSharp.Core.Agents.ViewModels;
|
||||
|
||||
public class AgentViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
}
|
||||
|
|
@ -67,14 +67,11 @@
|
|||
<PackageReference Include="LLamaSharp" Version="0.3.0" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cuda11" Version="0.3.0" />
|
||||
<PackageReference Include="TensorFlow.Keras" Version="0.10.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Infrastructures\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
using BotSharp.Abstraction.Agents;
|
||||
using BotSharp.Abstraction.Conversations;
|
||||
using BotSharp.Abstraction.TextGeneratives;
|
||||
using BotSharp.Abstraction.Users;
|
||||
using BotSharp.Core.Agents.Services;
|
||||
using BotSharp.Core.Conversations;
|
||||
using BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
|
||||
using BotSharp.Core.Repository;
|
||||
using EntityFrameworkCore.BootKit;
|
||||
using BotSharp.Core.Users.Services;
|
||||
using BotSharp.Plugins.LLamaSharp;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -14,6 +15,9 @@ public static class BotSharpServiceCollectionExtensions
|
|||
{
|
||||
public static IServiceCollection AddBotSharp(this IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
services.AddScoped<ICurrentUser, CurrentUser>();
|
||||
services.AddScoped<IUserService, UserService>();
|
||||
services.AddScoped<IAgentService, AgentService>();
|
||||
services.AddSingleton<ISessionService, SessionService>();
|
||||
services.AddSingleton<IConversationService, ConversationService>();
|
||||
|
||||
|
|
@ -59,17 +63,22 @@ public static class BotSharpServiceCollectionExtensions
|
|||
return DataContextHelper.GetDbContext<MongoDbContext>(myDatabaseSettings, x);
|
||||
});
|
||||
|
||||
services.AddSingleton(x =>
|
||||
services.AddScoped((IServiceProvider x) =>
|
||||
{
|
||||
var settings = new LlamaSharpSettings();
|
||||
config.Bind("LlamaSharp", settings);
|
||||
return settings;
|
||||
return DataContextHelper.GetDbContext<AgentDbContext>(myDatabaseSettings, x);
|
||||
});
|
||||
services.AddSingleton<IChatCompletionProvider, ChatCompletionProvider>();
|
||||
}
|
||||
|
||||
public static void RegisterPlugins(IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
|
||||
var settings = new LlamaSharpSettings();
|
||||
config.Bind("LlamaSharp", settings);
|
||||
services.AddSingleton(x =>
|
||||
{
|
||||
|
||||
return settings;
|
||||
});
|
||||
|
||||
// services.AddSingleton<IChatCompletionProvider, ChatCompletionProvider>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
namespace BotSharp.Core.Infrastructures;
|
||||
|
||||
public static class Utilities
|
||||
{
|
||||
public static string HashText(string password, string salt)
|
||||
{
|
||||
using var md5 = System.Security.Cryptography.MD5.Create();
|
||||
|
||||
var data = md5.ComputeHash(Encoding.UTF8.GetBytes(password + salt));
|
||||
var sb = new StringBuilder();
|
||||
foreach (var c in data)
|
||||
{
|
||||
sb.Append(c.ToString("x2"));
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static (string, string) SplitAsTuple(this string str, string sep)
|
||||
{
|
||||
var splits = str.Split(sep);
|
||||
return (splits[0], splits[1]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
using BotSharp.Abstraction.Models;
|
||||
using BotSharp.Abstraction.Plugins;
|
||||
using BotSharp.Abstraction.TextGeneratives;
|
||||
using LLama;
|
||||
using System.IO;
|
||||
|
||||
namespace BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
|
||||
namespace BotSharp.Plugins.LLamaSharp;
|
||||
|
||||
public class ChatCompletionProvider : IChatCompletionProvider, IBotSharpPlugin
|
||||
{
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
namespace BotSharp.Plugins.LLamaSharp;
|
||||
|
||||
public class LLamaSharpPlugin : IBotSharpPlugin
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
|
||||
namespace BotSharp.Plugins.LLamaSharp;
|
||||
|
||||
public class LlamaSharpSettings
|
||||
{
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
namespace BotSharp.Core.Plugins.TextGeneratives.LLamaSharp;
|
||||
|
||||
public class LLamaSharpPlugin : IBotSharpPlugin
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
namespace BotSharp.Core.Repository.Abstraction;
|
||||
|
||||
public interface IAgentTable
|
||||
{
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using BotSharp.Core.Repository.DbTables;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
||||
public class AgentDbContext : Database
|
||||
{
|
||||
public IQueryable<UserRecord> User => Table<UserRecord>();
|
||||
public IQueryable<AgentRecord> Agent => Table<AgentRecord>();
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
using BotSharp.Core.Repository.Abstraction;
|
||||
using EntityFrameworkCore.BootKit;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace BotSharp.Core.Repository;
|
||||
|
|
@ -23,6 +25,18 @@ public static class DataContextHelper
|
|||
IsRelational = false
|
||||
});
|
||||
}
|
||||
else if (typeof(T) == typeof(AgentDbContext))
|
||||
{
|
||||
dc.BindDbContext<IAgentTable, DbContext4SqlServer2>(new DatabaseBind
|
||||
{
|
||||
ServiceProvider = serviceProvider,
|
||||
MasterConnection = new SqlConnection(settings.Agent.Master),
|
||||
SlaveConnections = settings.Agent.Slavers.Length == 0 ?
|
||||
new List<DbConnection> { new SqlConnection(settings.Agent.Master) } :
|
||||
settings.Agent.Slavers.Select(x => new SqlConnection(x) as DbConnection).ToList(),
|
||||
CreateDbIfNotExist = true
|
||||
});
|
||||
}
|
||||
return dc;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
using BotSharp.Abstraction.Agents.Models;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace BotSharp.Core.Repository.DbTables;
|
||||
|
||||
[Table("Agent")]
|
||||
public class AgentRecord : DbRecord, IAgentTable
|
||||
{
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[MaxLength(512)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[Required]
|
||||
[MaxLength(36)]
|
||||
public string OwnerId { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public DateTime CreatedDateTime { get; set; }
|
||||
|
||||
[Required]
|
||||
public DateTime UpdatedDateTime { get; set; }
|
||||
|
||||
public static AgentRecord FromAgent(Agent agent)
|
||||
{
|
||||
return new AgentRecord
|
||||
{
|
||||
Id = agent.Id,
|
||||
Name = agent.Name,
|
||||
Description = agent.Description,
|
||||
OwnerId = agent.OwerId
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace BotSharp.Core.Repository.DbTables;
|
||||
|
||||
[Table("User")]
|
||||
public class UserRecord : DbRecord, IAgentTable
|
||||
{
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string FirstName { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string LastName { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[MaxLength(64)]
|
||||
public string Email { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[StringLength(32)]
|
||||
public string Salt { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[MaxLength(256)]
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
public DateTime UpdatedTime { get; set; } = DateTime.UtcNow;
|
||||
|
||||
[Required]
|
||||
public DateTime CreatedTime { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public static UserRecord FromUser(User user)
|
||||
{
|
||||
return new UserRecord
|
||||
{
|
||||
Id = user.Id,
|
||||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Email = user.Email,
|
||||
Password = user.Password
|
||||
};
|
||||
}
|
||||
|
||||
public User ToUser()
|
||||
{
|
||||
return new User
|
||||
{
|
||||
Id = Id,
|
||||
FirstName = FirstName,
|
||||
LastName = LastName,
|
||||
Email = Email,
|
||||
Salt = Salt,
|
||||
Password = Password,
|
||||
CreatedTime = CreatedTime,
|
||||
UpdatedTime = UpdatedTime
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -6,4 +6,5 @@ public class MyDatabaseSettings : DatabaseSettings
|
|||
{
|
||||
public string[] Assemblies { get; set; }
|
||||
public DbConnectionSetting MongoDb { get; set; }
|
||||
public DbConnectionSetting Agent { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
using BotSharp.Abstraction.Users;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace BotSharp.Core.Users.Services;
|
||||
|
||||
public class CurrentUser : ICurrentUser
|
||||
{
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
private IEnumerable<Claim> _claims => _contextAccessor.HttpContext.User.Claims;
|
||||
|
||||
public CurrentUser(IHttpContextAccessor contextAccessor)
|
||||
{
|
||||
_contextAccessor = contextAccessor;
|
||||
}
|
||||
|
||||
public string Id => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value;
|
||||
|
||||
|
||||
public string Email => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
|
||||
|
||||
public string FirstName => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname").Value;
|
||||
|
||||
public string LastName => _claims.First(x => x.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname").Value;
|
||||
}
|
||||
123
src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
Normal file
123
src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
using BotSharp.Abstraction.Users;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using BotSharp.Core.Infrastructures;
|
||||
using BotSharp.Core.Repository.DbTables;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace BotSharp.Core.Users.Services;
|
||||
|
||||
public class UserService : IUserService
|
||||
{
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly ICurrentUser _user;
|
||||
|
||||
public UserService(IServiceProvider services, ICurrentUser user)
|
||||
{
|
||||
_services = services;
|
||||
_user = user;
|
||||
}
|
||||
|
||||
public async Task<User> CreateUser(User user)
|
||||
{
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var record = db.User.FirstOrDefault(x => x.Email == user.Email.ToLower());
|
||||
if (record != null)
|
||||
{
|
||||
return record.ToUser();
|
||||
}
|
||||
|
||||
record = UserRecord.FromUser(user);
|
||||
record.Id = Guid.NewGuid().ToString();
|
||||
record.Email = user.Email.ToLower();
|
||||
record.Salt = Guid.NewGuid().ToString("N");
|
||||
record.Password = Utilities.HashText(user.Password, record.Salt);
|
||||
|
||||
db.Transaction<IAgentTable>(delegate
|
||||
{
|
||||
db.Add<IAgentTable>(record);
|
||||
});
|
||||
|
||||
return record.ToUser();
|
||||
}
|
||||
|
||||
public async Task<Token> GetToken(string authorization)
|
||||
{
|
||||
var base64 = Encoding.UTF8.GetString(Convert.FromBase64String(authorization));
|
||||
var (userEmail, password) = base64.SplitAsTuple(":");
|
||||
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var record = db.User.FirstOrDefault(x => x.Email == userEmail);
|
||||
if (record == null)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if (Utilities.HashText(password, record.Salt) != record.Password)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var accessToken = GenerateJwtToken(record);
|
||||
var jwt = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
|
||||
return new Token
|
||||
{
|
||||
AccessToken = accessToken,
|
||||
ExpireTime = jwt.Payload.Exp.Value,
|
||||
TokenType = "Bearer",
|
||||
Scope = "api"
|
||||
};
|
||||
}
|
||||
|
||||
private string GenerateJwtToken(UserRecord user)
|
||||
{
|
||||
var config = _services.GetRequiredService<IConfiguration>();
|
||||
var issuer = config["Jwt:Issuer"];
|
||||
var audience = config["Jwt:Audience"];
|
||||
var key = Encoding.ASCII.GetBytes(config["Jwt:Key"]);
|
||||
var tokenDescriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
Subject = new ClaimsIdentity(new[]
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.NameId, user.Id),
|
||||
new Claim(JwtRegisteredClaimNames.Email, user.Email),
|
||||
new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
|
||||
new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||
}),
|
||||
Expires = DateTime.UtcNow.AddMinutes(5),
|
||||
Issuer = issuer,
|
||||
Audience = audience,
|
||||
SigningCredentials = new SigningCredentials
|
||||
(new SymmetricSecurityKey(key),
|
||||
SecurityAlgorithms.HmacSha512Signature)
|
||||
};
|
||||
var tokenHandler = new JwtSecurityTokenHandler();
|
||||
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||
return tokenHandler.WriteToken(token);
|
||||
}
|
||||
|
||||
public async Task<User> GetMyProfile()
|
||||
{
|
||||
var userId = _user.Id;
|
||||
|
||||
var db = _services.GetRequiredService<AgentDbContext>();
|
||||
var user = (from u in db.User
|
||||
where u.Id == userId
|
||||
select new User
|
||||
{
|
||||
Id = u.Id,
|
||||
Email = u.Email,
|
||||
FirstName = u.FirstName,
|
||||
LastName = u.LastName,
|
||||
CreatedTime = u.CreatedTime,
|
||||
UpdatedTime = u.UpdatedTime,
|
||||
Password = u.Password,
|
||||
}).FirstOrDefault();
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
47
src/Infrastructure/BotSharp.Core/Users/UserController.cs
Normal file
47
src/Infrastructure/BotSharp.Core/Users/UserController.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
using BotSharp.Abstraction.ApiAdapters;
|
||||
using BotSharp.Abstraction.Users;
|
||||
using BotSharp.Abstraction.Users.Models;
|
||||
using BotSharp.Core.Users.ViewModels;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace BotSharp.Core.Users;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
public class UserController : ControllerBase, IApiAdapter
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
public UserController(IUserService userService)
|
||||
{
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("/token")]
|
||||
public async Task<ActionResult<Token>> GetToken()
|
||||
{
|
||||
var authcode = Request.Headers["Authorization"].ToString();
|
||||
var token = await _userService.GetToken(authcode.Split(' ')[1]);
|
||||
if (token == null)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
return Ok(token);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpPost("/user")]
|
||||
public async Task<UserViewModel> CreateUser(UserCreationModel user)
|
||||
{
|
||||
var createdUser = await _userService.CreateUser(user.ToUser());
|
||||
return UserViewModel.FromUser(createdUser);
|
||||
}
|
||||
|
||||
[HttpGet("/user/my")]
|
||||
public async Task<UserViewModel> GetMyUserProfile()
|
||||
{
|
||||
var user = await _userService.GetMyProfile();
|
||||
return UserViewModel.FromUser(user);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.Core.Users.ViewModels;
|
||||
|
||||
public class UserCreationModel
|
||||
{
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
|
||||
public User ToUser()
|
||||
{
|
||||
return new User
|
||||
{
|
||||
FirstName = FirstName,
|
||||
LastName = LastName,
|
||||
Email = Email,
|
||||
Password = Password
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using BotSharp.Abstraction.Users.Models;
|
||||
|
||||
namespace BotSharp.Core.Users.ViewModels;
|
||||
|
||||
public class UserViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Email { get; set; }
|
||||
|
||||
public static UserViewModel FromUser(User user)
|
||||
{
|
||||
return new UserViewModel
|
||||
{
|
||||
Id = user.Id,
|
||||
FirstName = user.FirstName,
|
||||
LastName = user.LastName,
|
||||
Email = user.Email
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -4,4 +4,7 @@ global using System.Text;
|
|||
global using System.Threading.Tasks;
|
||||
global using BotSharp.Abstraction;
|
||||
global using System.Linq;
|
||||
global using BotSharp.Abstraction.Plugins;
|
||||
global using BotSharp.Abstraction.Plugins;
|
||||
global using EntityFrameworkCore.BootKit;
|
||||
global using BotSharp.Core.Repository;
|
||||
global using BotSharp.Core.Repository.Abstraction;
|
||||
|
|
@ -11,7 +11,7 @@ public static class AzureOpenAiServiceCollectionExtensions
|
|||
public static IServiceCollection AddAzureOpenAiPlatform(this IServiceCollection services, IConfiguration config)
|
||||
{
|
||||
var settings = new AzureOpenAiSettings();
|
||||
config.Bind("AzureAi", settings);
|
||||
config.Bind("AzureOpenAi", settings);
|
||||
|
||||
services.AddSingleton(x =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.5" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
|
||||
<PackageReference Include="System.Text.Json" Version="7.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,42 @@
|
|||
using BotSharp.Core;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllers();
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
builder.Services.AddHttpContextAccessor();
|
||||
|
||||
// Add bearer authentication
|
||||
builder.Services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
}).AddJwtBearer(o =>
|
||||
{
|
||||
o.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidIssuer = builder.Configuration["Jwt:Issuer"],
|
||||
ValidAudience = builder.Configuration["Jwt:Audience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = false,
|
||||
ValidateIssuerSigningKey = true
|
||||
};
|
||||
});
|
||||
|
||||
// Add BotSharp
|
||||
builder.Services.AddBotSharp(builder.Configuration);
|
||||
// builder.Services.AddAzureOpenAiPlatform(builder.Configuration);
|
||||
builder.Services.AddAzureOpenAiPlatform(builder.Configuration);
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
|
|
@ -34,6 +58,7 @@ if (app.Environment.IsDevelopment())
|
|||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.16" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@
|
|||
},
|
||||
"AllowedHosts": "*",
|
||||
|
||||
"OpenAi": {
|
||||
"userName": "",
|
||||
"password": ""
|
||||
"Jwt": {
|
||||
"Issuer": "botsharp",
|
||||
"Audience": "botsharp",
|
||||
"Key": "31ba6052aa6f4569901facc3a41fcb4a"
|
||||
},
|
||||
|
||||
"LlamaSharp": {
|
||||
|
|
@ -33,7 +34,15 @@
|
|||
"MongoDb": {
|
||||
"Master": "mongodb://localhost:27017/chat-ui"
|
||||
},
|
||||
"Agent": {
|
||||
"Master": "Data Source=(localdb)\\ProjectModels;Initial Catalog=Agent;Integrated Security=True;Connect Timeout=30;Encrypt=False;Trust Server Certificate=False;Application Intent=ReadWrite;Multi Subnet Failover=False",
|
||||
"Slavers": []
|
||||
},
|
||||
"UseCamelCase": true,
|
||||
"Assemblies": [ "BotSharp.Core" ]
|
||||
},
|
||||
|
||||
"Providers": {
|
||||
"ChatCompletionProvider": "BotSharp.Plugins.LLamaSharp.ChatCompletionProvider"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,13 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.2.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
Loading…
Reference in a new issue