API V1 Aeldria
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.17" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
@Aeldria.Api_HostAddress = http://localhost:5152
|
||||
|
||||
GET {{Aeldria.Api_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -0,0 +1,76 @@
|
||||
using BCrypt.Net;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Aeldria.Api.Data;
|
||||
using Aeldria.Api.DTOs;
|
||||
using Aeldria.Api.Models;
|
||||
using Aeldria.Api.Services;
|
||||
|
||||
namespace Aeldria.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/auth")]
|
||||
public class AuthController : ControllerBase
|
||||
{
|
||||
private readonly AeldriaDbContext _db;
|
||||
private readonly JwtService _jwt;
|
||||
|
||||
public AuthController(AeldriaDbContext db, JwtService jwt)
|
||||
{
|
||||
_db = db;
|
||||
_jwt = jwt;
|
||||
}
|
||||
|
||||
[HttpPost("register")]
|
||||
public async Task<IActionResult> Register(RegisterRequest request)
|
||||
{
|
||||
if (await _db.Accounts.AnyAsync(x => x.Username == request.Username))
|
||||
return BadRequest("Nom d'utilisateur déjà utilisé.");
|
||||
|
||||
if (await _db.Accounts.AnyAsync(x => x.Email == request.Email))
|
||||
return BadRequest("Email déjà utilisé.");
|
||||
|
||||
var account = new Account
|
||||
{
|
||||
Username = request.Username,
|
||||
Email = request.Email,
|
||||
PasswordHash = PasswordService.HashPassword(request.Password),
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
IsBanned = false,
|
||||
IsVerified = false
|
||||
};
|
||||
|
||||
_db.Accounts.Add(account);
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Message = "Compte créé avec succès.",
|
||||
AccountId = account.AccountId
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("login")]
|
||||
public async Task<IActionResult> Login(LoginRequest request)
|
||||
{
|
||||
var account = await _db.Accounts
|
||||
.FirstOrDefaultAsync(x => x.Username == request.Username);
|
||||
|
||||
if (account == null)
|
||||
return Unauthorized("Compte introuvable.");
|
||||
|
||||
if (!PasswordService.VerifyPassword(request.Password, account.PasswordHash))
|
||||
return Unauthorized("Mot de passe incorrect.");
|
||||
|
||||
account.LastLogin = DateTime.UtcNow;
|
||||
await _db.SaveChangesAsync();
|
||||
var token = _jwt.GenerateToken(account);
|
||||
return Ok(new
|
||||
{
|
||||
Message = "Connexion réussie.",
|
||||
AccountId = account.AccountId,
|
||||
Username = account.Username,
|
||||
Token = token
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Aeldria.Api.Data;
|
||||
using Aeldria.Api.Models;
|
||||
using Aeldria.Api.DTOs;
|
||||
|
||||
namespace Aeldria.Api.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
public class CharactersController : ControllerBase
|
||||
{
|
||||
private readonly AeldriaDbContext _db;
|
||||
|
||||
public CharactersController(AeldriaDbContext db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
[HttpPost("create")]
|
||||
public async Task<IActionResult> Create(CreateCharacterRequest request)
|
||||
{
|
||||
if (await _db.Characters.AnyAsync(x => x.Name == request.Name))
|
||||
return BadRequest("Nom déjà utilisé.");
|
||||
var accountId = long.Parse(
|
||||
User.FindFirst(
|
||||
System.Security.Claims.ClaimTypes.NameIdentifier
|
||||
)!.Value
|
||||
);
|
||||
var character = new Character
|
||||
{
|
||||
AccountId = accountId,
|
||||
Name = request.Name,
|
||||
Level = 1,
|
||||
Experience = 0,
|
||||
PosX = 0,
|
||||
PosY = 0,
|
||||
PosZ = 0,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
FactionId = 1,
|
||||
RaceId = 1
|
||||
};
|
||||
|
||||
_db.Characters.Add(character);
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
return Ok(character);
|
||||
}
|
||||
|
||||
[HttpGet("my")]
|
||||
public async Task<IActionResult> GetCharacters()
|
||||
{
|
||||
var accountId = long.Parse(
|
||||
User.FindFirst(
|
||||
System.Security.Claims.ClaimTypes.NameIdentifier
|
||||
)!.Value
|
||||
);
|
||||
var characters = await _db.Characters
|
||||
.Where(x => x.AccountId == accountId)
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(characters);
|
||||
}
|
||||
[HttpGet("{characterId}")]
|
||||
public async Task<IActionResult> GetCharacter(long characterId)
|
||||
{
|
||||
var character = await _db.Characters
|
||||
.FirstOrDefaultAsync(x => x.CharacterId == characterId);
|
||||
|
||||
if (character == null)
|
||||
return NotFound();
|
||||
|
||||
return Ok(character);
|
||||
}
|
||||
[HttpPut("position")]
|
||||
public async Task<IActionResult> UpdatePosition(UpdatePositionRequest request)
|
||||
{
|
||||
var character = await _db.Characters
|
||||
.FirstOrDefaultAsync(x => x.CharacterId == request.CharacterId);
|
||||
|
||||
if (character == null)
|
||||
return NotFound();
|
||||
|
||||
character.PosX = request.PosX;
|
||||
character.PosY = request.PosY;
|
||||
character.PosZ = request.PosZ;
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
Message = "Position sauvegardée."
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Aeldria.Api.DTOs;
|
||||
|
||||
public class CreateCharacterRequest
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Aeldria.Api.DTOs;
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Aeldria.Api.DTOs;
|
||||
|
||||
public class RegisterRequest
|
||||
{
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
public string Email { get; set; } = string.Empty;
|
||||
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Aeldria.Api.DTOs;
|
||||
|
||||
public class UpdatePositionRequest
|
||||
{
|
||||
public long CharacterId { get; set; }
|
||||
|
||||
public double PosX { get; set; }
|
||||
|
||||
public double PosY { get; set; }
|
||||
|
||||
public double PosZ { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Aeldria.Api.Models;
|
||||
|
||||
namespace Aeldria.Api.Data;
|
||||
|
||||
public class AeldriaDbContext : DbContext
|
||||
{
|
||||
public AeldriaDbContext(DbContextOptions<AeldriaDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
public DbSet<Account> Accounts => Set<Account>();
|
||||
public DbSet<Character> Characters => Set<Character>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.HasDefaultSchema("aeldria");
|
||||
|
||||
modelBuilder.Entity<Account>(entity =>
|
||||
{
|
||||
entity.ToTable("accounts");
|
||||
|
||||
entity.HasKey(e => e.AccountId);
|
||||
|
||||
entity.Property(e => e.AccountId)
|
||||
.HasColumnName("account_id");
|
||||
|
||||
entity.Property(e => e.Username)
|
||||
.HasColumnName("username");
|
||||
|
||||
entity.Property(e => e.Email)
|
||||
.HasColumnName("email");
|
||||
|
||||
entity.Property(e => e.PasswordHash)
|
||||
.HasColumnName("password_hash");
|
||||
|
||||
entity.Property(e => e.CreatedAt)
|
||||
.HasColumnName("created_at");
|
||||
|
||||
entity.Property(e => e.LastLogin)
|
||||
.HasColumnName("last_login");
|
||||
|
||||
entity.Property(e => e.IsBanned)
|
||||
.HasColumnName("is_banned");
|
||||
|
||||
entity.Property(e => e.IsVerified)
|
||||
.HasColumnName("is_verified");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Character>(entity =>
|
||||
{
|
||||
entity.ToTable("characters");
|
||||
|
||||
entity.HasKey(e => e.CharacterId);
|
||||
|
||||
entity.Property(e => e.CharacterId)
|
||||
.HasColumnName("character_id");
|
||||
|
||||
entity.Property(e => e.AccountId)
|
||||
.HasColumnName("account_id");
|
||||
|
||||
entity.Property(e => e.FactionId)
|
||||
.HasColumnName("faction_id");
|
||||
|
||||
entity.Property(e => e.RaceId)
|
||||
.HasColumnName("race_id");
|
||||
|
||||
entity.Property(e => e.Name)
|
||||
.HasColumnName("name");
|
||||
|
||||
entity.Property(e => e.Level)
|
||||
.HasColumnName("level");
|
||||
|
||||
entity.Property(e => e.Experience)
|
||||
.HasColumnName("experience");
|
||||
|
||||
entity.Property(e => e.PosX)
|
||||
.HasColumnName("pos_x");
|
||||
|
||||
entity.Property(e => e.PosY)
|
||||
.HasColumnName("pos_y");
|
||||
|
||||
entity.Property(e => e.PosZ)
|
||||
.HasColumnName("pos_z");
|
||||
|
||||
entity.Property(e => e.CreatedAt)
|
||||
.HasColumnName("created_at");
|
||||
});
|
||||
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aeldria.Api.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aeldria.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(AeldriaDbContext))]
|
||||
[Migration("20260623072757_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.6")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Aeldria.Api.Models.Account", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aeldria.Api.Models.Character", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("AccountId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Experience")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Level")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aeldria.Api.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Accounts",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
Username = table.Column<string>(type: "text", nullable: false),
|
||||
Email = table.Column<string>(type: "text", nullable: false),
|
||||
PasswordHash = table.Column<string>(type: "text", nullable: false),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Accounts", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Characters",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
AccountId = table.Column<int>(type: "integer", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: false),
|
||||
Level = table.Column<int>(type: "integer", nullable: false),
|
||||
Experience = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Characters", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Accounts");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Characters");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Aeldria.Api.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Aeldria.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(AeldriaDbContext))]
|
||||
partial class AeldriaDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.6")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Aeldria.Api.Models.Account", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Username")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Aeldria.Api.Models.Character", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("AccountId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Experience")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Level")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Characters");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace Aeldria.Api.Models;
|
||||
|
||||
public class Account
|
||||
{
|
||||
public long AccountId { get; set; }
|
||||
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
public string Email { get; set; } = string.Empty;
|
||||
|
||||
public string PasswordHash { get; set; } = string.Empty;
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public DateTime? LastLogin { get; set; }
|
||||
|
||||
public bool IsBanned { get; set; }
|
||||
|
||||
public bool IsVerified { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace Aeldria.Api.Models;
|
||||
|
||||
public class Character
|
||||
{
|
||||
public long CharacterId { get; set; }
|
||||
|
||||
public long AccountId { get; set; }
|
||||
|
||||
public int FactionId { get; set; }
|
||||
|
||||
public int RaceId { get; set; }
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
public int Level { get; set; }
|
||||
|
||||
public long Experience { get; set; }
|
||||
|
||||
public double PosX { get; set; }
|
||||
|
||||
public double PosY { get; set; }
|
||||
|
||||
public double PosZ { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
using Aeldria.Api.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Aeldria.Api.Data;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
ForwardedHeaders.XForwardedFor |
|
||||
ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
|
||||
builder.Services.AddDbContext<AeldriaDbContext>(options =>
|
||||
options.UseNpgsql(
|
||||
builder.Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
// Add services to the container.
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
|
||||
builder.Services.AddScoped<JwtService>();
|
||||
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
|
||||
ValidIssuer = builder.Configuration["Jwt:Issuer"],
|
||||
ValidAudience = builder.Configuration["Jwt:Audience"],
|
||||
|
||||
IssuerSigningKey = new SymmetricSecurityKey(
|
||||
Encoding.UTF8.GetBytes(
|
||||
builder.Configuration["Jwt:Key"]!
|
||||
))
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
|
||||
|
||||
builder.Services.AddOpenApi();
|
||||
builder.Services.AddControllers();
|
||||
|
||||
var app = builder.Build();
|
||||
app.UseForwardedHeaders();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.MapOpenApi();
|
||||
}
|
||||
|
||||
//app.UseHttpsRedirection();
|
||||
|
||||
var summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
|
||||
app.MapGet("/weatherforecast", () =>
|
||||
{
|
||||
var forecast = Enumerable.Range(1, 5).Select(index =>
|
||||
new WeatherForecast
|
||||
(
|
||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
Random.Shared.Next(-20, 55),
|
||||
summaries[Random.Shared.Next(summaries.Length)]
|
||||
))
|
||||
.ToArray();
|
||||
return forecast;
|
||||
})
|
||||
.WithName("GetWeatherForecast");
|
||||
app.MapControllers();
|
||||
app.Run();
|
||||
|
||||
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
||||
{
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://0.0.0.0:5152",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://0.0.0.0:7241;http://0.0.0.0:5152",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Aeldria.Api.Models;
|
||||
|
||||
namespace Aeldria.Api.Services;
|
||||
|
||||
public class JwtService
|
||||
{
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
public JwtService(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public string GenerateToken(Account account)
|
||||
{
|
||||
var claims = new[]
|
||||
{
|
||||
new Claim(ClaimTypes.NameIdentifier, account.AccountId.ToString()),
|
||||
new Claim(ClaimTypes.Name, account.Username)
|
||||
};
|
||||
|
||||
var key = new SymmetricSecurityKey(
|
||||
Encoding.UTF8.GetBytes(_config["Jwt:Key"]!)
|
||||
);
|
||||
|
||||
var creds = new SigningCredentials(
|
||||
key,
|
||||
SecurityAlgorithms.HmacSha256
|
||||
);
|
||||
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: _config["Jwt:Issuer"],
|
||||
audience: _config["Jwt:Audience"],
|
||||
claims: claims,
|
||||
expires: DateTime.UtcNow.AddDays(7),
|
||||
signingCredentials: creds
|
||||
);
|
||||
|
||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Aeldria.Api.Services;
|
||||
|
||||
public static class PasswordService
|
||||
{
|
||||
public static string HashPassword(string password)
|
||||
{
|
||||
return BCrypt.Net.BCrypt.HashPassword(password);
|
||||
}
|
||||
|
||||
public static bool VerifyPassword(string password, string hash)
|
||||
{
|
||||
return BCrypt.Net.BCrypt.Verify(password, hash);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=192.168.1.165;Port=5432;Database=aeldria;Username=aeldria;Password=Aeldria@667-Ekip"
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "AeldriaSuperSecretKey2026Minimum32Characters",
|
||||
"Issuer": "Aeldria.Api",
|
||||
"Audience": "Aeldria.Client"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net9.0",
|
||||
"frameworks": [
|
||||
{
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "9.0.0"
|
||||
},
|
||||
{
|
||||
"name": "Microsoft.AspNetCore.App",
|
||||
"version": "9.0.0"
|
||||
}
|
||||
],
|
||||
"configProperties": {
|
||||
"System.GC.Server": true,
|
||||
"System.Reflection.NullabilityInfoContext.IsSupported": true,
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"ManifestType": "Build",
|
||||
"Endpoints": []
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=192.168.1.165;Port=5432;Database=aeldria;Username=aeldria;Password=Aeldria@667-Ekip"
|
||||
},
|
||||
"Jwt": {
|
||||
"Key": "AeldriaSuperSecretKey2026Minimum32Characters",
|
||||
"Issuer": "Aeldria.Api",
|
||||
"Audience": "Aeldria.Client"
|
||||
},
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user