disable swagger + update cors for production

This commit is contained in:
2025-10-31 00:55:29 +07:00
parent 29685fd68d
commit 758e376381
6 changed files with 85 additions and 73 deletions

View File

@@ -140,3 +140,4 @@ namespace Managing.Api.HealthChecks
} }
} }

View File

@@ -1,43 +1,23 @@
#nullable enable
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace Managing.Api.Models.Requests; namespace Managing.Api.Models.Requests;
/// <summary>
/// Request model for submitting indicator requests to N8n webhook
/// </summary>
public class IndicatorRequestDto public class IndicatorRequestDto
{ {
/// <summary>
/// Name of the indicator (e.g., "MACD", "RSI", "Bollinger Bands")
/// </summary>
[Required] [Required]
[StringLength(200, MinimumLength = 4, ErrorMessage = "Indicator name must be between 4 and 200 characters.")] [StringLength(200, MinimumLength = 4, ErrorMessage = "Indicator name must be between 4 and 200 characters.")]
public string IndicatorName { get; set; } = string.Empty; public string IndicatorName { get; set; } = string.Empty;
/// <summary>
/// Strategy or description of how the indicator is used (e.g., "MACD Cross", "RSI Divergence")
/// </summary>
[Required] [Required]
[StringLength(1000, MinimumLength = 10, ErrorMessage = "Strategy description must be between 10 and 1000 characters.")] [StringLength(1000, MinimumLength = 10, ErrorMessage = "Strategy description must be between 10 and 1000 characters.")]
public string StrategyDescription { get; set; } = string.Empty; public string StrategyDescription { get; set; } = string.Empty;
/// <summary>
/// Primary documentation URL for the indicator
/// </summary>
[Url(ErrorMessage = "Documentation URL must be a valid URL.")] [Url(ErrorMessage = "Documentation URL must be a valid URL.")]
public string? DocumentationUrl { get; set; } public string? DocumentationUrl { get; set; }
/// <summary>
/// Image URL for the indicator (optional) - can be a chart, diagram, or visual representation
/// </summary>
[Url(ErrorMessage = "Image URL must be a valid URL.")] [Url(ErrorMessage = "Image URL must be a valid URL.")]
public string? ImageUrl { get; set; } public string? ImageUrl { get; set; }
/// <summary>
/// Telegram account handle of the person requesting the indicator (e.g., "cryptooda")
/// </summary>
[Required] [Required]
[RegularExpression(@"^(?=(?:[0-9_]*[a-z]){3})[a-z0-9_]{5,}$", [RegularExpression(@"^(?=(?:[0-9_]*[a-z]){3})[a-z0-9_]{5,}$",
ErrorMessage = "Requester name must be a valid Telegram handle (lowercase letters, numbers, underscores only, minimum 5 characters with at least 3 letters).")] ErrorMessage = "Requester name must be a valid Telegram handle (lowercase letters, numbers, underscores only, minimum 5 characters with at least 3 letters).")]

View File

@@ -243,16 +243,33 @@ builder.Services
}; };
}); });
builder.Services.AddCors(o => o.AddPolicy("CorsPolicy", builder => // Configure CORS from configuration (appsettings.json)
var allowedCorsOrigins = builder.Configuration
.GetSection("Cors:AllowedOrigins")
.Get<string[]>() ?? Array.Empty<string>();
builder.Services.AddCors(options =>
{ {
builder options.AddPolicy("CorsPolicy", policy =>
.SetIsOriginAllowed((host) => true) {
.AllowAnyOrigin() if (allowedCorsOrigins.Length > 0)
.WithOrigins("http://localhost:3000/") {
.AllowAnyMethod() policy
.AllowAnyHeader() .WithOrigins(allowedCorsOrigins)
.AllowCredentials(); .AllowAnyMethod()
})); .AllowAnyHeader()
.AllowCredentials();
}
else
{
// Fallback for development if no origins configured
policy
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(_ => true);
}
});
});
builder.Services.AddSignalR().AddJsonProtocol(); builder.Services.AddSignalR().AddJsonProtocol();
builder.Services.AddScoped<IJwtUtils, JwtUtils>(); builder.Services.AddScoped<IJwtUtils, JwtUtils>();
@@ -262,47 +279,51 @@ builder.Services.RegisterApiDependencies(builder.Configuration);
// Orleans is always configured, but grains can be controlled // Orleans is always configured, but grains can be controlled
builder.Host.ConfigureOrleans(builder.Configuration, builder.Environment.IsProduction()); builder.Host.ConfigureOrleans(builder.Configuration, builder.Environment.IsProduction());
builder.Services.AddHostedServices(); builder.Services.AddHostedServices();
builder.Services.AddEndpointsApiExplorer(); var enableSwagger = builder.Configuration.GetValue<bool>("EnableSwagger", builder.Environment.IsDevelopment());
builder.Services.AddOpenApiDocument(document => if (enableSwagger)
{ {
document.AddSecurity("JWT", Enumerable.Empty<string>(), new OpenApiSecurityScheme builder.Services.AddEndpointsApiExplorer();
{ builder.Services.AddOpenApiDocument(document =>
Type = OpenApiSecuritySchemeType.ApiKey,
Name = "Authorization",
In = OpenApiSecurityApiKeyLocation.Header,
Description = "Type into the textbox: Bearer {your JWT token}."
});
document.OperationProcessors.Add(
new AspNetCoreOperationSecurityScopeProcessor("JWT"));
});
builder.Services.AddSwaggerGen(options =>
{
options.SchemaFilter<EnumSchemaFilter>();
options.AddSecurityDefinition("Bearer,", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Description = "Please insert your JWT Token into field : Bearer {your_token}",
Name = "Authorization",
Type = SecuritySchemeType.Http,
In = ParameterLocation.Header,
Scheme = "Bearer",
BearerFormat = "JWT"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{ {
document.AddSecurity("JWT", Enumerable.Empty<string>(), new OpenApiSecurityScheme
{ {
new Microsoft.OpenApi.Models.OpenApiSecurityScheme Type = OpenApiSecuritySchemeType.ApiKey,
{ Name = "Authorization",
Reference = new OpenApiReference In = OpenApiSecurityApiKeyLocation.Header,
{ Description = "Type into the textbox: Bearer {your JWT token}."
Type = ReferenceType.SecurityScheme, });
Id = "Bearer"
} document.OperationProcessors.Add(
}, new AspNetCoreOperationSecurityScopeProcessor("JWT"));
new string[] { }
}
}); });
}); builder.Services.AddSwaggerGen(options =>
{
options.SchemaFilter<EnumSchemaFilter>();
options.AddSecurityDefinition("Bearer,", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Description = "Please insert your JWT Token into field : Bearer {your_token}",
Name = "Authorization",
Type = SecuritySchemeType.Http,
In = ParameterLocation.Header,
Scheme = "Bearer",
BearerFormat = "JWT"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
});
}
builder.WebHost.SetupDiscordBot(); builder.WebHost.SetupDiscordBot();
@@ -310,12 +331,15 @@ builder.WebHost.SetupDiscordBot();
var app = builder.Build(); var app = builder.Build();
app.UseSerilogRequestLogging(); app.UseSerilogRequestLogging();
app.UseOpenApi(); if (enableSwagger)
app.UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Managing API v1"); app.UseOpenApi();
c.RoutePrefix = string.Empty; app.UseSwaggerUI(c =>
}); {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Managing API v1");
c.RoutePrefix = string.Empty;
});
}
app.UseCors("CorsPolicy"); app.UseCors("CorsPolicy");

View File

@@ -35,5 +35,11 @@
"SentryEnabled": false, "SentryEnabled": false,
"LoopDetectionEnabled": true, "LoopDetectionEnabled": true,
"LogErrorsOnly": true "LogErrorsOnly": true
},
"Cors": {
"AllowedOrigins": [
"https://app.kaigen.ai",
"https://api.kaigen.ai"
]
} }
} }

View File

@@ -101,5 +101,6 @@
"LogSlowQueriesOnly": false, "LogSlowQueriesOnly": false,
"LogErrorsOnly": false, "LogErrorsOnly": false,
"DataRetentionMinutes": 300 "DataRetentionMinutes": 300
} },
"EnableSwagger": false
} }

View File

@@ -5,7 +5,7 @@ import {parseAbi} from 'viem'
import {GmxSdk} from '@gmx-io/sdk' import {GmxSdk} from '@gmx-io/sdk'
// ExchangeRouter contract address on Arbitrum // ExchangeRouter contract address on Arbitrum
const EXCHANGE_ROUTER_ADDRESS = '0x5aC4e27341e4cCcb3e5FD62f9E62db2Adf43dd57' const EXCHANGE_ROUTER_ADDRESS = '0x87d66368cD08a7Ca42252f5ab44B2fb6d1Fb8d15'
// ABI for the claimUiFees function // ABI for the claimUiFees function
const CLAIM_UI_FEES_ABI = parseAbi([ const CLAIM_UI_FEES_ABI = parseAbi([