infrastructure
parent
e0b7ab93ba
commit
f06a9fcaea
|
@ -0,0 +1,61 @@
|
||||||
|
using Chatbot.Api.Application.Services;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
using System.Text;
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Authentication
|
||||||
|
{
|
||||||
|
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
|
||||||
|
{
|
||||||
|
private readonly IUserService _userService;
|
||||||
|
|
||||||
|
public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IUserService userService)
|
||||||
|
: base(options, logger, encoder, clock)
|
||||||
|
{
|
||||||
|
_userService = userService;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
|
{
|
||||||
|
if (!Request.Headers.ContainsKey("Authorization"))
|
||||||
|
return AuthenticateResult.Fail("Missing Authorization Header");
|
||||||
|
|
||||||
|
User user;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var authHeader = AuthenticationHeaderValue.Parse(Request.Headers["Authorization"]);
|
||||||
|
var credentialBytes = Convert.FromBase64String(authHeader.Parameter);
|
||||||
|
var credentials = Encoding.UTF8.GetString(credentialBytes).Split(':');
|
||||||
|
var username = credentials.First();
|
||||||
|
var password = credentials.Last();
|
||||||
|
user = await _userService.Authenticate(username, password);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return AuthenticateResult.Fail("Invalid Authorization Header");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
return AuthenticateResult.Fail("Invalid Username or Password");
|
||||||
|
|
||||||
|
var claims = new[] {
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
|
||||||
|
new Claim(ClaimTypes.Name, user.UserName),
|
||||||
|
};
|
||||||
|
|
||||||
|
var identity = new ClaimsIdentity(claims, Scheme.Name);
|
||||||
|
var principal = new ClaimsPrincipal(identity);
|
||||||
|
var ticket = new AuthenticationTicket(principal, Scheme.Name);
|
||||||
|
|
||||||
|
return AuthenticateResult.Success(ticket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,5 +4,25 @@
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.4" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" />
|
||||||
|
<PackageReference Include="Serilog.AspNetCore" Version="$(SerilogPackageVersion)" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Logging" Version="$(SerilogExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="$(SerilogSinksConsolePackageVersion)" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.MSSqlServer" Version="$(SerilogSinksMSSqlServerPackageVersion)" />
|
||||||
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="$(AutoMapperExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="$(MediatRPackageVersion)" />
|
||||||
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="$(SwashbucklePackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Chatbot.Application\Chatbot.Api.Application.csproj" />
|
||||||
|
<ProjectReference Include="..\Chatbot.Domain.Data\Chatbot.Api.Domain.Data.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Chatbot.Api.Application.Queries;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
[Route("system")]
|
||||||
|
public class SystemController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IMediator _mediator;
|
||||||
|
|
||||||
|
public SystemController(IMediator mediator)
|
||||||
|
{
|
||||||
|
_mediator = mediator;
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpGet("ping")]
|
||||||
|
public IActionResult Ping()
|
||||||
|
{
|
||||||
|
return Ok("Chatbot api ping success.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("bots")]
|
||||||
|
public async Task<IActionResult> GetReleaseNotes([FromRoute] GetBots.Query query)
|
||||||
|
{
|
||||||
|
var result = await _mediator.Send(query);
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,39 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace Chatbot.Api.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class WeatherForecastController : ControllerBase
|
|
||||||
{
|
|
||||||
private static readonly string[] Summaries = new[]
|
|
||||||
{
|
|
||||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly ILogger<WeatherForecastController> _logger;
|
|
||||||
|
|
||||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
public IEnumerable<WeatherForecast> Get()
|
|
||||||
{
|
|
||||||
var rng = new Random();
|
|
||||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = DateTime.Now.AddDays(index),
|
|
||||||
TemperatureC = rng.Next(-20, 55),
|
|
||||||
Summary = Summaries[rng.Next(Summaries.Length)]
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Serilog;
|
||||||
|
using Serilog.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
using Serilog.Sinks.MSSqlServer;
|
||||||
|
|
||||||
namespace Chatbot.Api
|
namespace Chatbot.Api
|
||||||
{
|
{
|
||||||
|
@ -13,14 +16,61 @@ namespace Chatbot.Api
|
||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
CreateHostBuilder(args).Build().Run();
|
if (!args.Contains("--docker"))
|
||||||
|
{
|
||||||
|
var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
|
var pathToContentRoot = Path.GetDirectoryName(pathToExe);
|
||||||
|
Directory.SetCurrentDirectory(pathToContentRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
var configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var connectionString = configuration.GetConnectionString("DatabaseConnection");
|
||||||
|
var loggingLevelParam = configuration.GetValue<string>("Logging:LogLevel:Default");
|
||||||
|
|
||||||
|
Enum.TryParse(loggingLevelParam, out LogEventLevel loggingLevel);
|
||||||
|
var loggingLevelSwitch = new LoggingLevelSwitch(loggingLevel);
|
||||||
|
|
||||||
|
var columnOptions = new ColumnOptions();
|
||||||
|
columnOptions.Store.Remove(StandardColumn.Properties);
|
||||||
|
columnOptions.Store.Remove(StandardColumn.MessageTemplate);
|
||||||
|
columnOptions.Store.Add(StandardColumn.LogEvent);
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.MinimumLevel.ControlledBy(loggingLevelSwitch)
|
||||||
|
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
|
||||||
|
.Enrich.FromLogContext()
|
||||||
|
.WriteTo.Console()
|
||||||
|
.WriteTo.MSSqlServer(connectionString, "__Logs_Api", autoCreateSqlTable: true, columnOptions: columnOptions)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var urls = configuration.GetValue<string>("urls");
|
||||||
|
Log.Information("Starting chatbot API...");
|
||||||
|
Log.Information($"API listening on {urls}");
|
||||||
|
Console.WriteLine("Application started. Press Ctrl+C to shut down.");
|
||||||
|
CreateHostBuilder(args, configuration).Build().Run();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Fatal(ex, "Chatbot API host terminated unexpectedly");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Log.CloseAndFlush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
public static IHostBuilder CreateHostBuilder(string[] args, IConfiguration configuration) =>
|
||||||
Host.CreateDefaultBuilder(args)
|
Host.CreateDefaultBuilder(args)
|
||||||
.ConfigureWebHostDefaults(webBuilder =>
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
{
|
{
|
||||||
webBuilder.UseStartup<Startup>();
|
webBuilder.UseStartup<Startup>()
|
||||||
|
.UseConfiguration(configuration)
|
||||||
|
.UseSerilog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
using System;
|
using AutoMapper;
|
||||||
using System.Collections.Generic;
|
using Chatbot.Api.Authentication;
|
||||||
using System.Linq;
|
using Chatbot.Api.Domain.Data;
|
||||||
using System.Threading.Tasks;
|
using Chatbot.Api.Swagger;
|
||||||
|
using Chatbot.Application;
|
||||||
|
using MediatR;
|
||||||
|
using MediatR.Pipeline;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Newtonsoft.Json;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Chatbot.Api
|
namespace Chatbot.Api
|
||||||
{
|
{
|
||||||
|
@ -24,25 +28,60 @@ namespace Chatbot.Api
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddControllers();
|
services.AddControllers()
|
||||||
|
.AddNewtonsoftJson(o => o.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc);
|
||||||
|
|
||||||
|
// configure basic authentication
|
||||||
|
services.AddAuthentication("BasicAuthentication")
|
||||||
|
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);
|
||||||
|
|
||||||
|
// MediatR
|
||||||
|
services.AddMediatR(GetMediatRAssemblies());
|
||||||
|
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
|
||||||
|
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(RequestPostProcessorBehavior<,>));
|
||||||
|
|
||||||
|
// AutoMapper
|
||||||
|
services.AddAutoMapper(
|
||||||
|
typeof(Application.Mappings.MappingProfile).Assembly);
|
||||||
|
|
||||||
|
// Swagger
|
||||||
|
services.AddSwagger();
|
||||||
|
|
||||||
|
// Application
|
||||||
|
services.AddApplicationServices();
|
||||||
|
|
||||||
|
// DataAccess
|
||||||
|
services.AddDataAccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
|
// global cors policy
|
||||||
|
app.UseCors(x => x
|
||||||
|
.AllowAnyOrigin()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader());
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
if (env.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseDeveloperExceptionPage();
|
app.UseDeveloperExceptionPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
});
|
});
|
||||||
|
app.ConfigureSwagger();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Assembly[] GetMediatRAssemblies()
|
||||||
|
{
|
||||||
|
var assembly = typeof(Application.Queries.GetBots).Assembly;
|
||||||
|
return new Assembly[] { assembly };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
using Chatbot.Api.Application.Commands;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Swagger
|
||||||
|
{
|
||||||
|
public class DtoSchemaFilter : ISchemaFilter
|
||||||
|
{
|
||||||
|
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
|
||||||
|
{
|
||||||
|
var targetType = context.Type;
|
||||||
|
while (targetType != null)
|
||||||
|
{
|
||||||
|
if (typeof(ICommand).IsAssignableFrom(targetType))
|
||||||
|
{
|
||||||
|
foreach (var property in schema.Properties.ToList())
|
||||||
|
{
|
||||||
|
property.Value.ReadOnly = false;
|
||||||
|
|
||||||
|
switch (property.Key)
|
||||||
|
{
|
||||||
|
case "metadata":
|
||||||
|
schema.Properties.Remove(property.Key);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetType = targetType.DeclaringType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Swagger
|
||||||
|
{
|
||||||
|
public class PathParamsOperationFilter : IOperationFilter
|
||||||
|
{
|
||||||
|
public void Apply(OpenApiOperation operation, OperationFilterContext context)
|
||||||
|
{
|
||||||
|
const string paramCaptureGroup = "param";
|
||||||
|
|
||||||
|
var openApiPathParameters = operation.Parameters.Where(param => param.In == ParameterLocation.Path).ToList();
|
||||||
|
var pathParamRegEx = $@"\{{(?<{paramCaptureGroup}>[^\}}]+)\}}";
|
||||||
|
|
||||||
|
if (openApiPathParameters.Any())
|
||||||
|
{
|
||||||
|
var pathParameterMatches = Regex.Matches(context.ApiDescription.RelativePath, pathParamRegEx, RegexOptions.Compiled);
|
||||||
|
var pathParameters = pathParameterMatches.Select(x => x.Groups[paramCaptureGroup].Value);
|
||||||
|
|
||||||
|
foreach (var openApiPathParameter in openApiPathParameters)
|
||||||
|
{
|
||||||
|
var correspondingPathParameter = pathParameters.FirstOrDefault(x =>
|
||||||
|
string.Equals(x, openApiPathParameter.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (correspondingPathParameter != null)
|
||||||
|
openApiPathParameter.Name = correspondingPathParameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Swagger
|
||||||
|
{
|
||||||
|
public static class SwaggerExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddSwagger(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSwaggerGen(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerDoc("v1",
|
||||||
|
new OpenApiInfo
|
||||||
|
{
|
||||||
|
Title = "Chatbot API",
|
||||||
|
Version = "v1"
|
||||||
|
});
|
||||||
|
|
||||||
|
c.AddSecurityDefinition("Basic",
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Description = @"JWT Authorization header using the Basic scheme. Enter 'Basic' [space] and then your token in the text input below. Example: 'Basic 12345abcdef'",
|
||||||
|
Name = "Authorization",
|
||||||
|
Scheme = "Basic",
|
||||||
|
Type = SecuritySchemeType.ApiKey
|
||||||
|
});
|
||||||
|
|
||||||
|
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type = ReferenceType.SecurityScheme,
|
||||||
|
Id = "Basic"
|
||||||
|
},
|
||||||
|
Scheme = "Basic",
|
||||||
|
Name = "Authorization",
|
||||||
|
In = ParameterLocation.Header
|
||||||
|
},
|
||||||
|
new List<string>()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
c.OperationFilter<PathParamsOperationFilter>();
|
||||||
|
c.SchemaFilter<DtoSchemaFilter>();
|
||||||
|
c.CustomSchemaIds(type => type.ToString());
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IApplicationBuilder ConfigureSwagger(this IApplicationBuilder applicationBuilder)
|
||||||
|
{
|
||||||
|
applicationBuilder.UseSwagger(c =>
|
||||||
|
{
|
||||||
|
c.PreSerializeFilters.Add((swagger, httpRequest) =>
|
||||||
|
{
|
||||||
|
var (host, basePath, scheme) = GetUrlComponents(httpRequest);
|
||||||
|
|
||||||
|
swagger.Servers = new List<OpenApiServer>
|
||||||
|
{
|
||||||
|
new OpenApiServer {Url = $"{scheme}://{host}{basePath}"}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
c.RouteTemplate = "swagger/{documentName}/swagger.json";
|
||||||
|
});
|
||||||
|
|
||||||
|
applicationBuilder.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("v1/swagger.json", "Chatbot API");
|
||||||
|
c.RoutePrefix = $"swagger";
|
||||||
|
});
|
||||||
|
|
||||||
|
return applicationBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (string host, string basePath, string scheme) GetUrlComponents(HttpRequest request)
|
||||||
|
{
|
||||||
|
var host = ExtractHost(request);
|
||||||
|
var basePath = ExtractBasePath(request);
|
||||||
|
var scheme = ExtractScheme(request);
|
||||||
|
|
||||||
|
return (host, basePath, scheme);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractHost(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request.Headers.ContainsKey("X-Forwarded-Host"))
|
||||||
|
return request.Headers["X-Forwarded-Host"].First();
|
||||||
|
|
||||||
|
return request.Host.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractBasePath(HttpRequest request)
|
||||||
|
{
|
||||||
|
if (request.Headers.ContainsKey("X-Forwarded-PathBase"))
|
||||||
|
return request.Headers["X-Forwarded-PathBase"].First();
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ExtractScheme(HttpRequest request)
|
||||||
|
{
|
||||||
|
return request.Headers["X-Forwarded-Proto"].FirstOrDefault() ?? request.Scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Chatbot.Api
|
|
||||||
{
|
|
||||||
public class WeatherForecast
|
|
||||||
{
|
|
||||||
public DateTime Date { get; set; }
|
|
||||||
|
|
||||||
public int TemperatureC { get; set; }
|
|
||||||
|
|
||||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
|
||||||
|
|
||||||
public string Summary { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,8 @@
|
||||||
{
|
{
|
||||||
|
"urls": "http://*:5061",
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DatabaseConnection": "***REMOVED***"
|
||||||
|
},
|
||||||
"Logging": {
|
"Logging": {
|
||||||
"LogLevel": {
|
"LogLevel": {
|
||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
|
@ -6,5 +10,9 @@
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*",
|
||||||
|
"Credentials": {
|
||||||
|
"UserName": "***REMOVED***",
|
||||||
|
"Password": "***REMOVED***"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,17 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AutoMapper" Version="$(AutoMapperPackageVersion)" />
|
||||||
|
<PackageReference Include="MediatR" Version="$(MediatRPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsPackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Chatbot.Domain\Chatbot.Api.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Chatbot.Application
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Commands
|
||||||
|
{
|
||||||
|
public abstract class Command<TResponse> : ICommand, IRequest<TResponse>
|
||||||
|
{
|
||||||
|
public Metadata Metadata { get; }
|
||||||
|
|
||||||
|
protected Command(Metadata metadata)
|
||||||
|
{
|
||||||
|
Metadata = metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICommand
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Commands
|
||||||
|
{
|
||||||
|
public class Metadata : Dictionary<string, string>
|
||||||
|
{
|
||||||
|
public const string CorrelationIdKey = "CorrelationId";
|
||||||
|
|
||||||
|
public Guid CorrelationId
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Guid.Parse(this[CorrelationIdKey]);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (ContainsKey(CorrelationIdKey))
|
||||||
|
this[CorrelationIdKey] = value.ToString();
|
||||||
|
else
|
||||||
|
Add(CorrelationIdKey, value.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Chatbot.Api.Application.Services;
|
||||||
|
using Chatbot.Api.Domain.Services;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Chatbot.Application
|
||||||
|
{
|
||||||
|
public static class DependencyInjectionExtensions
|
||||||
|
{
|
||||||
|
public static void AddApplicationServices(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IParamProvider, ParamProvider>();
|
||||||
|
services.AddScoped<IUserService, UserService>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using AutoMapper;
|
||||||
|
using Chatbot.Api.Application.Queries;
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Mappings
|
||||||
|
{
|
||||||
|
public class MappingProfile : Profile
|
||||||
|
{
|
||||||
|
public MappingProfile()
|
||||||
|
{
|
||||||
|
CreateMap<Bot, GetBots.Model>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
using AutoMapper;
|
||||||
|
using Chatbot.Api.Domain.Repositories;
|
||||||
|
using MediatR;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Queries
|
||||||
|
{
|
||||||
|
public class GetBots
|
||||||
|
{
|
||||||
|
public class Query : Query<Model[]>
|
||||||
|
{
|
||||||
|
public Query() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Model
|
||||||
|
{
|
||||||
|
public Guid BotId { get; set; }
|
||||||
|
public string BotCode { get; set; }
|
||||||
|
public string BotName { get; set; }
|
||||||
|
public DateTime CreationDate { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QueryHandler : IRequestHandler<Query, Model[]>
|
||||||
|
{
|
||||||
|
private readonly IBotRepository _botRepository;
|
||||||
|
private readonly IMapper _mapper;
|
||||||
|
|
||||||
|
public QueryHandler(IBotRepository botRepository, IMapper mapper)
|
||||||
|
{
|
||||||
|
_botRepository = botRepository;
|
||||||
|
_mapper = mapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Model[]> Handle(Query request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var bots = await _botRepository.GetBots();
|
||||||
|
var result = _mapper.Map<Model[]>(bots);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Queries
|
||||||
|
{
|
||||||
|
public abstract class Query<TResponse> : IRequest<TResponse>, IBaseRequest
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using Chatbot.Api.Domain.Models.Settings;
|
||||||
|
using Chatbot.Api.Domain.Services;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Services
|
||||||
|
{
|
||||||
|
public class ParamProvider : IParamProvider
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
public ParamProvider(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Credentials Credentials => _configuration.GetSection("Credentials").Get<Credentials>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
using Chatbot.Api.Domain.Services;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Application.Services
|
||||||
|
{
|
||||||
|
public interface IUserService
|
||||||
|
{
|
||||||
|
Task<User> Authenticate(string username, string password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UserService : IUserService
|
||||||
|
{
|
||||||
|
private readonly IParamProvider _paramProvider;
|
||||||
|
|
||||||
|
public UserService(IParamProvider paramProvider)
|
||||||
|
{
|
||||||
|
_paramProvider = paramProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<User> Authenticate(string username, string password)
|
||||||
|
{
|
||||||
|
return await Task.Run(() => CheckCredentials(username, password));
|
||||||
|
}
|
||||||
|
|
||||||
|
private User CheckCredentials(string username, string password)
|
||||||
|
{
|
||||||
|
if (_paramProvider.Credentials.UserName == username && _paramProvider.Credentials.Password == password)
|
||||||
|
return new User() { UserName = username, Id = 1 };
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,4 +4,12 @@
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(EntityFrameworkCorePackageVersion)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Chatbot.Domain\Chatbot.Api.Domain.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Chatbot.Domain.Data
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
using Chatbot.Api.Domain.Data.EntityTypeConfiguration;
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Data.DbContexts
|
||||||
|
{
|
||||||
|
public class BotDbContext : DbContext
|
||||||
|
{
|
||||||
|
public DbSet<Bot> Bots { get; set; }
|
||||||
|
|
||||||
|
public BotDbContext(DbContextOptions<BotDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
base.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;
|
||||||
|
base.ChangeTracker.AutoDetectChangesEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.ApplyConfiguration(new BotConfiguration());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Data.DbContexts
|
||||||
|
{
|
||||||
|
public class ChatDbContext : DbContext
|
||||||
|
{
|
||||||
|
public ChatDbContext(DbContextOptions<ChatDbContext> options)
|
||||||
|
: base(options)
|
||||||
|
{
|
||||||
|
base.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.TrackAll;
|
||||||
|
base.ChangeTracker.AutoDetectChangesEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using Chatbot.Api.Domain.Data.DbContexts;
|
||||||
|
using Chatbot.Api.Domain.Data.Repositories;
|
||||||
|
using Chatbot.Api.Domain.Repositories;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Data
|
||||||
|
{
|
||||||
|
public static class DependencyInjectionExtensions
|
||||||
|
{
|
||||||
|
public static void AddDataAccess(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddScoped<IBotRepository, BotRepository>();
|
||||||
|
|
||||||
|
services
|
||||||
|
.AddDbContextPool<BotDbContext>(
|
||||||
|
(serviceProvider, options) =>
|
||||||
|
{
|
||||||
|
var configuration = serviceProvider.GetService<IConfiguration>();
|
||||||
|
var connectionString = configuration.GetConnectionString("DatabaseConnection");
|
||||||
|
options.UseSqlServer(connectionString);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Data.EntityTypeConfiguration
|
||||||
|
{
|
||||||
|
class BotConfiguration : IEntityTypeConfiguration<Bot>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Bot> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Bot").HasKey(key => key.BotId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
using Chatbot.Api.Domain.Data.DbContexts;
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
using Chatbot.Api.Domain.Repositories;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Data.Repositories
|
||||||
|
{
|
||||||
|
class BotRepository : IBotRepository
|
||||||
|
{
|
||||||
|
private readonly BotDbContext _dbContext;
|
||||||
|
|
||||||
|
public BotRepository(BotDbContext dbContext)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Bot[]> GetBots()
|
||||||
|
{
|
||||||
|
return await _dbContext.Bots.ToArrayAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'Bot' and type = 'U')
|
||||||
|
begin
|
||||||
|
create table Bot
|
||||||
|
(
|
||||||
|
BotId uniqueidentifier constraint DF_Bot_BotId default newid() not null,
|
||||||
|
BotCode varchar(100) not null,
|
||||||
|
BotName varchar(255) not null,
|
||||||
|
CreationDate datetime constraint DF_Bot_CreationDate default getdate(),
|
||||||
|
constraint PK_Bot primary key (BotId)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
go
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'BotSession' and type = 'U')
|
||||||
|
begin
|
||||||
|
create table BotSession
|
||||||
|
(
|
||||||
|
SessionId uniqueidentifier constraint DF_BotSession_SessionId default newid() not null,
|
||||||
|
StartDate datetime constraint DF_BotSession_StartDate default getdate(),
|
||||||
|
BotId uniqueidentifier not null,
|
||||||
|
ExternalId uniqueidentifier not null,
|
||||||
|
ClientApplication varchar(100) not null,
|
||||||
|
UserKey varchar(100) not null,
|
||||||
|
constraint PK_BotSession primary key (SessionId),
|
||||||
|
constraint FK_BotSession_Bot foreign key (BotId) references Bot(BotId)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
go
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'Chat' and type = 'U')
|
||||||
|
begin
|
||||||
|
create table Chat
|
||||||
|
(
|
||||||
|
ChatId uniqueidentifier constraint DF_Chat_ChatId default newid() not null,
|
||||||
|
SessionId uniqueidentifier not null,
|
||||||
|
StartDate datetime constraint DF_Chat_StartDate default getdate(),
|
||||||
|
StopDate datetime,
|
||||||
|
constraint PK_Chat primary key (ChatId),
|
||||||
|
constraint FK_Chat_BotSession foreign key (ChatId) references BotSession(SessionId)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
go
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'MessageSource' and type = 'U')
|
||||||
|
begin
|
||||||
|
create table MessageSource
|
||||||
|
(
|
||||||
|
MessageSourceId int not null,
|
||||||
|
MessageSourceCode varchar(20) not null,
|
||||||
|
MessageSourceName varchar(100) not null,
|
||||||
|
constraint PK_MessageSource primary key (MessageSourceId)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
go
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from sys.objects where name = 'ChatMessage' and type = 'U')
|
||||||
|
begin
|
||||||
|
create table ChatMessage
|
||||||
|
(
|
||||||
|
MessageId int identity(0, 1),
|
||||||
|
ChatId uniqueidentifier not null,
|
||||||
|
MessageSourceId int not null,
|
||||||
|
MessageDate datetime constraint DF_ChatMessage_MessageDate default getdate(),
|
||||||
|
MessageContent varchar(max)
|
||||||
|
constraint PK_ChatMessage primary key (MessageId),
|
||||||
|
constraint FK_ChatMessage_Chat foreign key (ChatId) references Chat(ChatId),
|
||||||
|
constraint FK_ChatMessage_MessageSource foreign key (MessageSourceId) references MessageSource(MessageSourceId)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
go
|
|
@ -0,0 +1,13 @@
|
||||||
|
if not exists (select top 1 1 from MessageSource where MessageSourceCode like 'BOT')
|
||||||
|
begin
|
||||||
|
insert into MessageSource (MessageSourceId, MessageSourceCode, MessageSourceName)
|
||||||
|
values (1, 'BOT', 'Bot')
|
||||||
|
end
|
||||||
|
go
|
||||||
|
|
||||||
|
if not exists (select top 1 1 from MessageSource where MessageSourceCode like 'USER')
|
||||||
|
begin
|
||||||
|
insert into MessageSource (MessageSourceId, MessageSourceCode, MessageSourceName)
|
||||||
|
values (2, 'USER', 'User')
|
||||||
|
end
|
||||||
|
go
|
|
@ -1,8 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Chatbot.Domain
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Entities
|
||||||
|
{
|
||||||
|
public class Bot
|
||||||
|
{
|
||||||
|
public Guid BotId { get; set; }
|
||||||
|
public string BotCode { get; set; }
|
||||||
|
public string BotName { get; set; }
|
||||||
|
public DateTime CreationDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Chatbot.Api.Domain.Entities
|
||||||
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Chatbot.Api.Domain.Models.Settings
|
||||||
|
{
|
||||||
|
public class Credentials
|
||||||
|
{
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Chatbot.Api.Domain.Entities;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Repositories
|
||||||
|
{
|
||||||
|
public interface IBotRepository
|
||||||
|
{
|
||||||
|
Task<Bot[]> GetBots();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
using Chatbot.Api.Domain.Models.Settings;
|
||||||
|
|
||||||
|
namespace Chatbot.Api.Domain.Services
|
||||||
|
{
|
||||||
|
public interface IParamProvider
|
||||||
|
{
|
||||||
|
Credentials Credentials { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
.gitignore = .gitignore
|
.gitignore = .gitignore
|
||||||
dependencies.props = dependencies.props
|
dependencies.props = dependencies.props
|
||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
|
Notes.txt = Notes.txt
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chatbot.Api.Application", "Chatbot.Application\Chatbot.Api.Application.csproj", "{3759725E-8E75-44F4-86A3-34CC1EAC1D6C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chatbot.Api.Application", "Chatbot.Application\Chatbot.Api.Application.csproj", "{3759725E-8E75-44F4-86A3-34CC1EAC1D6C}"
|
||||||
|
|
Loading…
Reference in New Issue