Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using BotSharp.Abstraction.Models;
using BotSharp.Abstraction.Repositories.Filters;
using BotSharp.Abstraction.Users;
using BotSharp.Plugin.SqlDriver.Constants;
using BotSharp.Plugin.SqlDriver.Controllers.ViewModels;
using Microsoft.AspNetCore.Authorization;
Expand All @@ -11,30 +13,55 @@ namespace BotSharp.Plugin.SqlDriver.Controllers;
public class SqlDriverController : ControllerBase
{
private readonly IServiceProvider _services;
private readonly IUserIdentity _user;

public SqlDriverController(IServiceProvider services)
public SqlDriverController(IServiceProvider services, IUserIdentity user)
{
_services = services;
_user = user;
}

[HttpPost]
[Route("/sql-driver/{conversationId}/execute")]
public async Task<IActionResult> ExecuteSqlQuery([FromRoute] string conversationId, [FromBody] SqlQueryRequest sqlQueryRequest)
{
// [Authorize] only requires a logged-in session; it does not verify the
// caller owns conversationId. Without this check, any authenticated
// user could execute an arbitrary SQL statement against any configured
// data source by supplying any conversationId (including one they
// invent themselves), since SetConversationId performs no ownership
// check and silently creates the conversation if it doesn't exist.
// Mirror the same admin-or-owner check ConversationController.GetConversation
// already applies to reading a conversation's own dialog.
var userService = _services.GetRequiredService<IUserService>();
var conv = _services.GetRequiredService<IConversationService>();
var (isAdmin, currentUser) = await userService.IsAdminUser(_user.Id);
if (!isAdmin)
{
var existing = await conv.GetConversations(new ConversationFilter
{
Id = conversationId,
UserId = currentUser?.Id,
});
if (existing.Items?.FirstOrDefault() == null)
{
return Forbid();
}
}

var match = Regex.Match(sqlQueryRequest.SqlStatement, @"```sql\s*([\s\S]*?)\s*```", RegexOptions.IgnoreCase);
if (match.Success)
{
sqlQueryRequest.SqlStatement = match.Groups[1].Value.Trim();
}

var fn = _services.GetRequiredService<IRoutingService>();
var conv = _services.GetRequiredService<IConversationService>();
await conv.SetConversationId(conversationId,
await conv.SetConversationId(conversationId,
[
new MessageState(StateKeys.DBType, sqlQueryRequest.DbType),
new MessageState(StateKeys.DataSource, sqlQueryRequest.DataSource),
]);

var msg = new RoleDialogModel(AgentRole.User, sqlQueryRequest.SqlStatement)
{
CurrentAgentId = sqlQueryRequest.AgentId
Expand Down Expand Up @@ -63,7 +90,22 @@ await conv.SetConversationId(conversationId,
[Route("/sql-driver/{conversationId}/result")]
public async Task<IActionResult> AddQueryExecutionResult([FromRoute] string conversationId, [FromBody] SqlQueryExecutionResult sqlQueryResult)
{
var userService = _services.GetRequiredService<IUserService>();
var conv = _services.GetRequiredService<IConversationService>();
var (isAdmin, currentUser) = await userService.IsAdminUser(_user.Id);
if (!isAdmin)
{
var existing = await conv.GetConversations(new ConversationFilter
{
Id = conversationId,
UserId = currentUser?.Id,
});
if (existing.Items?.FirstOrDefault() == null)
{
return Forbid();
}
}

await conv.SetConversationId(conversationId, []);

var storage = _services.GetRequiredService<IConversationStorage>();
Expand Down
Loading