Restliche Funktionen Hinzugefügt

Siehe Projekttagebuch
This commit is contained in:
2026-02-04 14:32:53 +01:00
parent 34366d782c
commit 6dfd21da3b
420 changed files with 8088 additions and 114 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,37 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\Users\\tweee\\source\\repos\\Projekt-dev-env\\src\\Project-CBackend\\TicketSystem\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{0BBF8E29-1D9F-41AD-A1A2-637C72FA90D1}|TicketSystem.csproj|c:\\users\\tweee\\source\\repos\\projekt-dev-env\\src\\project-cbackend\\ticketsystem\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{0BBF8E29-1D9F-41AD-A1A2-637C72FA90D1}|TicketSystem.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 0,
"Children": [
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "Program.cs",
"DocumentMoniker": "C:\\Users\\tweee\\source\\repos\\Projekt-dev-env\\src\\Project-CBackend\\TicketSystem\\Program.cs",
"RelativeDocumentMoniker": "Program.cs",
"ToolTip": "C:\\Users\\tweee\\source\\repos\\Projekt-dev-env\\src\\Project-CBackend\\TicketSystem\\Program.cs",
"RelativeToolTip": "Program.cs",
"ViewState": "AgIAAHwAAAAAAAAAAAAAAIEAAABEAAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-03T10:53:32.912Z",
"EditorCaption": ""
}
]
}
]
}
]
}

View File

@@ -0,0 +1,37 @@
{
"Version": 1,
"WorkspaceRootPath": "C:\\Users\\tweee\\source\\repos\\Projekt-dev-env\\src\\Project-CBackend\\TicketSystem\\",
"Documents": [
{
"AbsoluteMoniker": "D:0:0:{0BBF8E29-1D9F-41AD-A1A2-637C72FA90D1}|TicketSystem.csproj|c:\\users\\tweee\\source\\repos\\projekt-dev-env\\src\\project-cbackend\\ticketsystem\\program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}",
"RelativeMoniker": "D:0:0:{0BBF8E29-1D9F-41AD-A1A2-637C72FA90D1}|TicketSystem.csproj|solutionrelative:program.cs||{A6C744A8-0E4A-4FC6-886A-064283054674}"
}
],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": [
{
"DockedWidth": 200,
"SelectedChildIndex": 0,
"Children": [
{
"$type": "Document",
"DocumentIndex": 0,
"Title": "Program.cs",
"DocumentMoniker": "C:\\Users\\tweee\\source\\repos\\Projekt-dev-env\\src\\Project-CBackend\\TicketSystem\\Program.cs",
"RelativeDocumentMoniker": "Program.cs",
"ToolTip": "C:\\Users\\tweee\\source\\repos\\Projekt-dev-env\\src\\Project-CBackend\\TicketSystem\\Program.cs",
"RelativeToolTip": "Program.cs",
"ViewState": "AgIAACoAAAAAAAAAAAAAADIAAAA4AAAAAAAAAA==",
"Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000738|",
"WhenOpened": "2026-02-03T10:53:32.912Z",
"EditorCaption": ""
}
]
}
]
}
]
}

View File

@@ -1,12 +1,20 @@
using BCrypt.Net;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Identity.Data;
using Microsoft.AspNetCore.WebSockets;
using Microsoft.IdentityModel.Tokens;
using MySqlConnector;
using SIPSorcery.Net;
using System.Collections.Generic;
using System.Data;
using System.IdentityModel.Tokens.Jwt;
using System.Net.WebSockets;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
@@ -17,13 +25,24 @@ var jwtAudience = builder.Configuration["Jwt:Audience"] ?? "Ticket-System";
builder.Services.AddTransient(_ => new MySqlConnection(connectionString));
builder.Services.AddWebSockets(options =>
{
options.KeepAliveInterval = TimeSpan.FromSeconds(120);
});
var app = builder.Build();
app.UseWebSockets();
app.Use(async (context, next) =>
{
var path = context.Request.Path.Value ?? "";
if (path.Equals("/signin", StringComparison.OrdinalIgnoreCase)) //|| path.Equals("/user/create", StringComparison.OrdinalIgnoreCase))
if (path.Equals("/signin", StringComparison.OrdinalIgnoreCase)
|| path.Equals("/webrtc", StringComparison.OrdinalIgnoreCase)
|| path.Equals("/user/create", StringComparison.OrdinalIgnoreCase))
{
await next();
return;
@@ -55,19 +74,23 @@ app.Use(async (context, next) =>
await context.Response.WriteAsJsonAsync(new { error = "Invalid token specified" });
return;
}
context.Items["user"] = principal.Identity?.Name ?? principal.FindFirstValue(ClaimTypes.Name) ?? "";
context.Items["user"] = principal.FindFirstValue(ClaimTypes.NameIdentifier) ?? "";
//context.Items["user"] = principal.Identity?.Name ?? principal.FindFirstValue(ClaimTypes.Name) ?? "";
await next();
});
app.MapPost("/signin", async (SignInRequest req, MySqlConnection conn) =>
{
try
{
const string sql = "SELECT userID, username, password FROM User WHERE username = @username LIMIT 1;";
await conn.OpenAsync();
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@username", req.name);
cmd.Parameters.AddWithValue("@username", req.user);
await using var reader = await cmd.ExecuteReaderAsync();
@@ -82,13 +105,334 @@ app.MapPost("/signin", async (SignInRequest req, MySqlConnection conn) =>
if (!ok)
return Results.Unauthorized();
conn.Close();
await conn.OpenAsync();
var token = CreateJwt(userId, username, jwtSecret, jwtIssuer, jwtAudience, minutesValid: 120);
const string cleanupSql = "DELETE FROM ValidateToken\r\nWHERE STR_TO_DATE(validationDate, '%Y-%m-%d %H:%i:%s')\r\n < (UTC_TIMESTAMP() - INTERVAL 24 HOUR);\r\n";
await using (var cleanup = new MySqlCommand(cleanupSql, conn))
{
await cleanup.ExecuteNonQueryAsync();
}
conn.Close();
await conn.OpenAsync();
const string insertTokenSql = """
INSERT INTO ValidateToken (validationDate, token)
VALUES (@validationdate, @token);
""";
await using (var ins = new MySqlCommand(insertTokenSql, conn))
{
ins.Parameters.AddWithValue("@token", token);
ins.Parameters.AddWithValue("@validationdate", DateTime.Now);
await ins.ExecuteNonQueryAsync();
}
conn.Close();
return Results.Ok(new ResponseToken(token));
}
catch (Exception ex)
{
return Results.Problem(ex.Message);
}
});
app.MapGet("/token/validate", (HttpContext ctx) =>
#region web rtc
app.Map("/webrtc", async context =>
{
return Results.Ok(new TokenIsValid(true));
if (!context.WebSockets.IsWebSocketRequest)
{
context.Response.StatusCode = 400;
return;
}
var token = context.Request.Query["token"].ToString();
var principal = string.IsNullOrWhiteSpace(token) ? null : ValidateJwt(token, jwtSecret, jwtIssuer, jwtAudience);
if (principal == null)
{
context.Response.StatusCode = 401;
return;
}
using var socket = await context.WebSockets.AcceptWebSocketAsync();
var pc = new RTCPeerConnection(new RTCConfiguration
{
iceServers = new List<RTCIceServer>
{
new RTCIceServer { urls = "http://10.204.192.64:3000" }
}
});
pc.oniceconnectionstatechange += (state) =>
Console.WriteLine($"[webrtc] ICE: {state}");
pc.onconnectionstatechange += (state) =>
Console.WriteLine($"[webrtc] PC: {state}");
// Server -> Client: ICE candidates
pc.onicecandidate += async cand =>
{
if (cand == null || socket.State != WebSocketState.Open) return;
var json = JsonSerializer.Serialize(cand);
await socket.SendAsync(Encoding.UTF8.GetBytes(json),
WebSocketMessageType.Text, true, CancellationToken.None);
};
var buffer = new byte[32 * 1024];
var jsonOpts = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
while (socket.State == WebSocketState.Open)
{
using var ms = new MemoryStream();
WebSocketReceiveResult res;
do
{
res = await socket.ReceiveAsync(buffer, CancellationToken.None);
if (res.MessageType == WebSocketMessageType.Close)
{
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "bye", CancellationToken.None);
return;
}
ms.Write(buffer, 0, res.Count);
}
while (!res.EndOfMessage);
var msg = Encoding.UTF8.GetString(ms.ToArray());
if (msg.Contains("\"sdp\"", StringComparison.OrdinalIgnoreCase))
{
// Browser sendet meist { type: "offer", sdp: "..." }
var sdp = JsonSerializer.Deserialize<RTCSessionDescriptionInit>(msg, jsonOpts);
if (sdp == null)
{
Console.WriteLine("[webrtc] SDP deserialize = null");
continue;
}
// SIPSorcery kann je nach Version sync/async sein -> wir behandeln BEIDES:
var setRemoteOk = await SetRemote(pc, sdp);
if (!setRemoteOk)
{
Console.WriteLine("[webrtc] setRemoteDescription failed");
continue;
}
if (sdp.type == RTCSdpType.offer)
{
var answer = pc.createAnswer(null);
var setLocalOk = await SetLocal(pc, answer);
if (!setLocalOk)
{
Console.WriteLine("[webrtc] setLocalDescription failed");
continue;
}
var json = JsonSerializer.Serialize(answer, jsonOpts);
await socket.SendAsync(Encoding.UTF8.GetBytes(json),
WebSocketMessageType.Text, true, CancellationToken.None);
}
continue;
}
// ---- ICE candidate from client
if (msg.Contains("candidate", StringComparison.OrdinalIgnoreCase))
{
var ice = JsonSerializer.Deserialize<RTCIceCandidateInit>(msg, jsonOpts);
if (ice == null)
{
Console.WriteLine("[webrtc] ICE deserialize = null");
continue;
}
pc.addIceCandidate(ice);
continue;
}
Console.WriteLine($"[webrtc] unknown msg: {msg}");
}
});
static async Task HandleWebRtc(WebSocket socket)
{
var pc = new RTCPeerConnection(new RTCConfiguration
{
iceServers = new List<RTCIceServer>
{
new RTCIceServer { urls = "stun:stun.l.google.com:19302" }
}
});
pc.onicecandidate += async candidate =>
{
if (candidate != null)
{
var json = JsonSerializer.Serialize(candidate);
await socket.SendAsync(
Encoding.UTF8.GetBytes(json),
WebSocketMessageType.Text,
true,
CancellationToken.None
);
}
};
pc.onconnectionstatechange += (state) =>
{
Console.WriteLine($"[webrtc] connection state: {state}");
};
pc.oniceconnectionstatechange += (state) =>
{
Console.WriteLine($"[webrtc] ICE state: {state}");
};
pc.onicecandidate += (cand) =>
{
if (cand != null) Console.WriteLine("[webrtc] ICE candidate generated");
};
var buffer = new byte[8192];
var jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
while (socket.State == WebSocketState.Open)
{
var result = await socket.ReceiveAsync(buffer, CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
break;
var msg = Encoding.UTF8.GetString(buffer, 0, result.Count);
if (msg.Contains("\"sdp\""))
{
var sdp = JsonSerializer.Deserialize<RTCSessionDescriptionInit>(msg, jsonOptions);
if (sdp == null) continue;
var r1 = pc.setRemoteDescription(sdp);
if (r1 != SetDescriptionResultEnum.OK)
{
Console.WriteLine($"setRemoteDescription failed: {r1}");
continue;
}
if (sdp.type == RTCSdpType.offer)
{
var answer = pc.createAnswer(null);
var r2 = pc.setLocalDescription(answer);
var json = JsonSerializer.Serialize(answer, jsonOptions);
await socket.SendAsync(
Encoding.UTF8.GetBytes(json),
WebSocketMessageType.Text,
true,
CancellationToken.None
);
}
}
else if (msg.Contains("candidate"))
{
var ice = JsonSerializer.Deserialize<RTCIceCandidateInit>(msg, jsonOptions);
if (ice == null) continue;
pc.addIceCandidate(ice);
}
}
}
static async Task<bool> SetRemote(RTCPeerConnection pc, RTCSessionDescriptionInit sdp)
{
var r = pc.setRemoteDescription(sdp);
if (r is SetDescriptionResultEnum e)
return e == SetDescriptionResultEnum.OK;
if (r != null && r.GetType().Name.Contains("SetDescriptionResult"))
{
var prop = r.GetType().GetProperty("Result");
if (prop?.GetValue(r) is SetDescriptionResultEnum e2)
return e2 == SetDescriptionResultEnum.OK;
}
return false;
}
static async Task<bool> SetLocal(RTCPeerConnection pc, RTCSessionDescriptionInit sdp)
{
var r = pc.setLocalDescription(sdp);
//if (r is SetDescriptionResultEnum e)
// return e == SetDescriptionResultEnum.OK;
//if (r != SetDescriptionResultEnum.OK)
//{
// Console.WriteLine($"setLocalDescription failed: {r}");
// //continue;
//}
if (r is Task<SetDescriptionResultEnum> t)
return (await t) == SetDescriptionResultEnum.OK;
if (r != null && r.GetType().Name.Contains("SetDescriptionResult"))
{
var prop = r.GetType().GetProperty("Result");
if (prop?.GetValue(r) is SetDescriptionResultEnum e2)
return e2 == SetDescriptionResultEnum.OK;
}
return false;
}
#endregion
static ClaimsPrincipal? ValidateJwtFromQuery(HttpContext ctx, string secret, string issuer, string audience)
{
var token = ctx.Request.Query["token"].ToString();
if (string.IsNullOrEmpty(token)) return null;
return ValidateJwt(token, secret, issuer, audience);
}
app.MapGet("/token/validate", async (HttpContext ctx, MySqlConnection conn) =>
{
if (!ctx.Request.Headers.TryGetValue("Authorization", out var authHeaderValues))
return Results.Unauthorized();
var parts = authHeaderValues.ToString().Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2 || !parts[0].Equals("Bearer", StringComparison.OrdinalIgnoreCase))
return Results.Unauthorized();
var token = parts[1];
await conn.OpenAsync();
const string checkSql = """
SELECT 1
FROM ValidateToken
WHERE token = @token
AND STR_TO_DATE(validationDate, '%Y-%m-%d %H:%i') >= (UTC_TIMESTAMP() - INTERVAL 24 HOUR)
LIMIT 1;
""";
await using var cmd = new MySqlCommand(checkSql, conn);
cmd.Parameters.AddWithValue("@token", token);
var ok = (await cmd.ExecuteScalarAsync()) != null;
return Results.Ok(new TokenIsValid(ok));
});
app.MapGet("/me", (HttpContext ctx) =>
@@ -112,19 +456,19 @@ app.MapPost("/user/create", async (RegisterRequest req, MySqlConnection conn) =>
await using var cmd = new MySqlCommand(insertSql, conn);
cmd.Parameters.AddWithValue("@userID", userId);
cmd.Parameters.AddWithValue("@username", req.name);
cmd.Parameters.AddWithValue("@username", req.user);
cmd.Parameters.AddWithValue("@password", pwHash);
var rows = await cmd.ExecuteNonQueryAsync();
if (rows != 1)
return Results.Problem("User konnte nicht angelegt werden.");
var token = CreateJwt(userId, req.name, jwtSecret, jwtIssuer, jwtAudience, minutesValid: 120);
var token = CreateJwt(userId, req.user, jwtSecret, jwtIssuer, jwtAudience, minutesValid: 120);
return Results.Created($"/user/{userId}", new ResponseToken(token));
});
app.MapPost("/ticket/create", async (HttpContext ctx, CreateTicketRequest req, MySqlConnection conn) =>
app.MapGet("/user/show/all", async (HttpContext ctx, MySqlConnection conn) =>
{
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrEmpty(userId))
@@ -132,19 +476,182 @@ app.MapPost("/ticket/create", async (HttpContext ctx, CreateTicketRequest req, M
await conn.OpenAsync();
const string sql = """
SELECT *
FROM User
""";
await using var cmd = new MySqlCommand(sql, conn);
await using var reader = await cmd.ExecuteReaderAsync();
var user = new List<object>();
while (await reader.ReadAsync())
{
user.Add(new
{
userID = reader.GetInt64("userID"),
username = reader.GetString("username"),
isEmployee = reader.GetInt32("isEmployee"),
});
}
return Results.Ok(user);
});
app.MapGet("/categories", async (HttpContext ctx, MySqlConnection conn) =>
{
await conn.OpenAsync();
const string sql = """
SELECT categoryname
FROM Category
""";
await using var cmd = new MySqlCommand(sql, conn);
await using var reader = await cmd.ExecuteReaderAsync();
List<string> categories = new List<string>();
while (await reader.ReadAsync())
{
categories.Add(reader.GetString("categoryname"));
}
return Results.Ok(categories);
});
app.MapGet("/user/hasrights/categories", async (HttpContext ctx, MySqlConnection conn) =>
{
await conn.OpenAsync();
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrEmpty(userId))
return Results.Unauthorized();
const string sql = """
SELECT c.categoryname
FROM User u
JOIN Category c ON c.categoryId = u.categoryId
WHERE u.userId = @userId;
""";
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@userID", userId);
await using var reader = await cmd.ExecuteReaderAsync();
List<string> categorys = new List<string>();
while (await reader.ReadAsync())
{
categorys.Add(reader.GetString("categoryname"));
}
return Results.Ok(categorys);
});
app.MapGet("/user/hasrights", async (HttpContext ctx, MySqlConnection conn) =>
{
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrEmpty(userId))
return Results.Unauthorized();
await conn.OpenAsync();
const string sql = """
SELECT isEmployee
FROM User
WHERE userID = @userID
""";
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@userID", userId);
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
if (reader.GetInt32("isEmployee") == 1)
{
return Results.Ok($"User: {userId} has rights = true");
}
else
{
return Results.Ok($"User: {userId} has rights = false");
}
}
return Results.Unauthorized();
});
app.MapPost("/ticket/create", async (HttpContext ctx, Ticket req, MySqlConnection conn) =>
{
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrEmpty(userId))
return Results.Unauthorized();
int categoryId = 0;
switch (req.category)
{
case "Hardware":
categoryId = 1;
break;
case "Software":
categoryId = 2;
break;
case "Schäden":
categoryId = 3;
break;
case "Personal-Probleme":
categoryId = 4;
break;
}
await conn.OpenAsync();
const string insertSql = """
INSERT INTO ticket (userID, ticketID, ticketname, status, priority, OpenAt, property)
VALUES (@userID,(select max(ticketID) from ticket) + 1, @ticketname, @beschreibung, @status, @priority, @openAt, @property);
INSERT INTO Ticket (
userID,
ticketname,
status,
category,
description,
categoryId,
priority,
opendAt
)
VALUES (
@userID,
@ticketname,
@status,
@category,
@description,
@categoryId,
@priority,
@opendAt
);
""";
await using var cmd = new MySqlCommand(insertSql, conn);
cmd.Parameters.AddWithValue("@userID", userId);
cmd.Parameters.AddWithValue("@status", req.status);
cmd.Parameters.AddWithValue("@userID", Convert.ToInt32(userId));
cmd.Parameters.AddWithValue("@ticketname", req.ticketname);
cmd.Parameters.AddWithValue("@beschreibung", req.beschreibung);
cmd.Parameters.AddWithValue("@priority", req.priority);
cmd.Parameters.AddWithValue("@openAt", DateTime.UtcNow);
cmd.Parameters.AddWithValue("@property", req.property);
cmd.Parameters.AddWithValue("@category", req.category);
cmd.Parameters.AddWithValue("@categoryId", categoryId);
cmd.Parameters.AddWithValue("@description", req.description);
cmd.Parameters.AddWithValue("@status", Convert.ToInt32(req.status));
cmd.Parameters.AddWithValue("@priority", Convert.ToInt32(req.priority));
cmd.Parameters.AddWithValue("@opendAt", DateTime.UtcNow);
var rows = await cmd.ExecuteNonQueryAsync();
if (rows != 1)
@@ -152,10 +659,9 @@ app.MapPost("/ticket/create", async (HttpContext ctx, CreateTicketRequest req, M
var ticketId = cmd.LastInsertedId;
return Results.Created($"/ticket/{ticketId}", new
return Results.Created($"/ticket/show/{ticketId}", new
{
ticketID = ticketId,
userID = userId
ticketID = ticketId
});
});
@@ -171,13 +677,15 @@ app.MapGet("/ticket/show/all", async (HttpContext ctx, MySqlConnection conn) =>
SELECT
t.ticketID,
t.ticketname,
u.username,
owner.username AS owner_name,
t.status,
t.priority,
t.category
FROM ticket t
JOIN User u ON t.userID = u.userID
WHERE t.userID = @userID
t.categoryId
FROM Ticket t
LEFT JOIN User owner ON t.userID = owner.userID
CROSS JOIN User u_search
WHERE u_search.userID = @userID
AND (t.userID = u_search.userID OR t.categoryId = u_search.categoryId)
ORDER BY t.priority;
""";
@@ -194,46 +702,122 @@ app.MapGet("/ticket/show/all", async (HttpContext ctx, MySqlConnection conn) =>
{
ticketID = reader.GetInt64("ticketID"),
ticketname = reader.GetString("ticketname"),
username = reader.GetString("username"),
username = reader.IsDBNull("owner_name") ? "" : reader.GetString("owner_name"),
status = reader.GetInt32("status"),
priority = reader.GetInt32("priority"),
category = reader.GetString("category")
categoryId = reader.IsDBNull("categoryId") ? 0 : Convert.ToInt32(reader.GetInt32("categoryId")),
});
}
return Results.Ok(tickets);
});
app.MapGet("/ticket/show/{ticketId:int}", async (
HttpContext ctx,
long ticketId,
MySqlConnection conn) =>
app.MapPost("/ticket/update/{ticketId:int}", async (HttpContext ctx, int ticketID, Ticket req, MySqlConnection conn) =>
{
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrEmpty(userId))
return Results.Unauthorized();
int categoryId = 0;
switch (req.category)
{
case "Hardware":
categoryId = 1;
break;
case "Software":
categoryId = 2;
break;
case "Schäden":
categoryId = 3;
break;
case "Personal-Probleme":
categoryId = 4;
break;
}
await conn.OpenAsync();
const string updateSql = """
UPDATE Ticket
SET
ticketname = @ticketname,
status = @status,
priority = @priority,
opendAt = @opendAt,
description = @description,
category = @category,
categoryID = @categoryId
WHERE
ticketID = @ticketID
AND userID = @userID;
""";
await using var cmd = new MySqlCommand(updateSql, conn);
cmd.Parameters.AddWithValue("@ticketID", ticketID);
cmd.Parameters.AddWithValue("@userID", Convert.ToInt32(userId));
cmd.Parameters.AddWithValue("@ticketname", req.ticketname);
cmd.Parameters.AddWithValue("@category", req.category);
cmd.Parameters.AddWithValue("@categoryId", categoryId);
cmd.Parameters.AddWithValue("@description", req.description);
cmd.Parameters.AddWithValue("@status", Convert.ToInt32(req.status));
cmd.Parameters.AddWithValue("@priority", Convert.ToInt32(req.priority));
cmd.Parameters.AddWithValue("@opendAt", DateTime.UtcNow);
var rows = await cmd.ExecuteNonQueryAsync();
if (rows != 1)
return Results.Problem("Ticket konnte nicht aktualisiert werden");
return Results.Ok(new
{
ticketID = ticketID,
updated = true
});
});
app.MapGet("/ticket/show/{ticketId:int}", async (
HttpContext ctx,
int ticketId,
MySqlConnection conn) =>
{
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrWhiteSpace(userId))
return Results.Unauthorized();
await conn.OpenAsync();
const string ticketSql = """
SELECT
t.TicketID,
t.Ticketname,
t.UserID,
u.Username AS OwnerUsername,
t.Status,
t.Priority,
t.OpenAt,
t.ClosedAt,
t.ticketID,
t.ticketname,
t.userID,
u.username,
t.status,
t.description,
t.priority,
t.opendAt,
t.closedAt,
t.category
FROM Ticket t
JOIN User u ON u.UserID = t.UserID
WHERE t.TicketID = @ticketId
AND t.UserID = @userId;
JOIN User u ON u.userID = t.userID
WHERE t.ticketID = @ticketId
AND t.userID = @userId
LIMIT 1;
""";
object? ticket = null;
long vticketID;
string vticketname;
long vuserID;
string vusername;
int vstatus;
string vdescription;
int vpriority;
string vopenAt;
string? vclosedAt;
string vcategory;
await using (var cmd = new MySqlCommand(ticketSql, conn))
{
@@ -244,38 +828,34 @@ app.MapGet("/ticket/show/{ticketId:int}", async (
if (!await reader.ReadAsync())
return Results.NotFound("Ticket nicht gefunden");
ticket = new
{
ticketID = reader.GetInt64("TicketID"),
ticketname = reader.GetString("Ticketname"),
userID = reader.GetInt64("UserID"),
ownerUsername = reader.GetString("OwnerUsername"),
status = reader.GetInt32("Status"),
priority = reader.GetInt32("Priority"),
openAt = reader.GetString("OpenAt"),
closedAt = reader.IsDBNull("ClosedAt") ? null : reader.GetString("ClosedAt"),
category = reader.GetString("category")
};
vticketID = reader.GetInt64("ticketID");
vticketname = reader.GetString("ticketname");
vuserID = reader.GetInt64("userID");
vusername = reader.GetString("username");
vstatus = reader.GetInt32("status");
vdescription = reader.IsDBNull("description") ? "" : reader.GetString("description");
vpriority = reader.GetInt32("priority");
vopenAt = reader.GetString("opendAt");
vclosedAt = reader.IsDBNull("closedAt") ? null : reader.GetString("closedAt");
vcategory = reader.GetString("category");
}
const string messagesSql = """
SELECT
m.MessageID,
m.Sequence,
m.SendAt,
m.Content,
m.Sender,
su.Username AS SenderUsername,
m.Reciver,
ru.Username AS ReciverUsername
m.messageID,
m.sequence,
m.sendAt,
m.content,
m.sender,
u.username AS senderUsername
FROM Messages m
LEFT JOIN User su ON su.UserID = m.Sender
LEFT JOIN User ru ON ru.UserID = m.Reciver
WHERE m.TicketID = @ticketId
ORDER BY m.Sequence ASC;
LEFT JOIN User u ON u.userID = m.sender
WHERE m.ticketID = @ticketId
ORDER BY m.sequence ASC;
""";
var messages = new List<object>();
var vmessages = new List<object>();
await using (var cmd = new MySqlCommand(messagesSql, conn))
{
@@ -284,27 +864,59 @@ app.MapGet("/ticket/show/{ticketId:int}", async (
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
messages.Add(new
vmessages.Add(new
{
messageID = reader.GetInt64("MessageID"),
sequence = reader.GetInt32("Sequence"),
sendAt = reader.GetString("SendAt"),
content = reader.GetString("Content"),
sender = reader.GetInt64("Sender"),
senderUsername = reader.IsDBNull("SenderUsername") ? null : reader.GetString("SenderUsername"),
reciver = reader.GetInt64("Reciver"),
reciverUsername = reader.IsDBNull("ReciverUsername") ? null : reader.GetString("ReciverUsername")
messageID = reader.GetInt64("messageID"),
sequence = reader.GetInt32("sequence"),
sendAt = reader.GetString("sendAt"),
content = reader.GetString("content"),
sender = reader.GetInt64("sender"),
senderUsername = reader.IsDBNull("senderUsername") ? null : reader.GetString("senderUsername")
});
}
}
return Results.Ok(new
{
ticket,
messages
ticketID = vticketID,
ticketname = vticketname,
userID = vuserID,
username = vusername,
description = vdescription,
status = vstatus,
priority = vpriority,
openAt = vopenAt,
closedAt = vclosedAt,
category = vcategory,
messages = vmessages
});
});
app.MapPost("/message/attachment", async (HttpContext ctx, AddAttachments req, MySqlConnection conn) =>
{
var userId = ctx.Items["user"]?.ToString();
if (string.IsNullOrEmpty(userId))
return Results.Unauthorized();
await conn.OpenAsync();
const string sql = """
INSERT INTO Attachments (ticketID, messageID, attachment) values (@ticketId, @messageId, @attachment);
""";
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@ticketId", req.ticketId);
cmd.Parameters.AddWithValue("@messageID", req.messageId);
cmd.Parameters.AddWithValue("@attachments", req.attachments);
var rows = await cmd.ExecuteNonQueryAsync();
if (rows != 1)
return Results.Problem("User konnte nicht angelegt werden.");
return Results.Ok();
});
static string CreateJwt(string userId, string username, string secret, string issuer, string audience, int minutesValid)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
@@ -358,14 +970,18 @@ static ClaimsPrincipal? ValidateJwt(string token, string secret, string issuer,
app.Run();
public record RegisterRequest(string name, string password);
public record SignInRequest(string name, string password);
public record RegisterRequest(string user, string password);
public record SignInRequest(string user, string password);
public record AddAttachments(string ticketId, string messageId, Blob attachments);
public record ResponseToken(string token);
public record TokenIsValid(bool is_valid);
public record CreateTicketRequest(
public record Ticket(
int status,
int priority,
string property,
string category,
string username,
string ticketname,
string beschreibung
string description
);

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net10.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<ProjectGuid>0bbf8e29-1d9f-41ad-a1a2-637c72fa90d1</ProjectGuid>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<_PublishTargetUrl>C:\Users\tweee\source\repos\Projekt-dev-env\src\Project-CBackend\TicketSystem\bin\Release\net10.0\publish\</_PublishTargetUrl>
<History>True|2026-02-02T09:49:50.3650629Z||;True|2026-02-02T10:49:37.6510863+01:00||;True|2026-02-02T10:48:37.6053205+01:00||;True|2026-01-30T13:56:01.7191901+01:00||;False|2026-01-30T12:51:03.0995895+01:00||;True|2026-01-30T12:33:58.6336798+01:00||;True|2026-01-30T12:29:43.4279844+01:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

View File

@@ -1,11 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<PublishAot>false</PublishAot>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\TicketSystem</DockerfileContext>
<RunAnalyzersDuringBuild>False</RunAnalyzersDuringBuild>
</PropertyGroup>
<ItemGroup>
@@ -13,6 +15,7 @@
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.2" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.15.0" />
<PackageReference Include="MySqlConnector" Version="2.5.0" />
<PackageReference Include="SIPSorcery" Version="10.0.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
</ItemGroup>

View File

@@ -2,5 +2,6 @@
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>https</ActiveDebugProfile>
<NameOfLastUsedPublishProfile>C:\Users\tweee\source\repos\Projekt-dev-env\src\Project-CBackend\TicketSystem\Properties\PublishProfiles\FolderProfile.pubxml</NameOfLastUsedPublishProfile>
</PropertyGroup>
</Project>

View File

@@ -1,3 +1,3 @@
<Solution>
<Project Path="../TicketSystem/TicketSystem.csproj" Id="0bbf8e29-1d9f-41ad-a1a2-637c72fa90d1" />
<Project Path="TicketSystem.csproj" Id="0bbf8e29-1d9f-41ad-a1a2-637c72fa90d1" />
</Solution>

View File

@@ -1,6 +1,7 @@
{
"ConnectionStrings": {
"Default": "Server=10.204.192.110;Port=3306;Database=ticket_sys;User Id=root;Password=example;SslMode=None;AllowPublicKeyRetrieval=True;",
"Default": "Server=10.204.192.64;Port=3306;Database=ticket_sys;User Id=root;Password=example;SslMode=None;AllowPublicKeyRetrieval=True;"
//"Default": "jdbc:mysql://10.204.192.110:3306/ticket_sys"
},
"Jwt": {
"Secret": "CHANGE_ME_TO_A_LONG_RANDOM_SECRET_32+_CHARS",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,279 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"TicketSystem/1.0.0": {
"dependencies": {
"BCrypt.Net-Next": "4.0.3",
"Microsoft.AspNetCore.OpenApi": "10.0.2",
"Microsoft.IdentityModel.JsonWebTokens": "8.15.0",
"MySqlConnector": "2.5.0",
"SIPSorcery": "10.0.3",
"System.IdentityModel.Tokens.Jwt": "8.15.0"
},
"runtime": {
"TicketSystem.dll": {}
}
},
"BCrypt.Net-Next/4.0.3": {
"runtime": {
"lib/net6.0/BCrypt.Net-Next.dll": {
"assemblyVersion": "4.0.3.0",
"fileVersion": "4.0.3.0"
}
}
},
"BouncyCastle.Cryptography/2.6.2": {
"runtime": {
"lib/net6.0/BouncyCastle.Cryptography.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.6.2.46322"
}
}
},
"Concentus/2.2.2": {
"runtime": {
"lib/net8.0/Concentus.dll": {
"assemblyVersion": "2.2.2.0",
"fileVersion": "2.2.2.0"
}
}
},
"DnsClient/1.8.0": {
"runtime": {
"lib/net8.0/DnsClient.dll": {
"assemblyVersion": "1.8.0.0",
"fileVersion": "1.8.0.0"
}
}
},
"Microsoft.AspNetCore.OpenApi/10.0.2": {
"dependencies": {
"Microsoft.OpenApi": "2.0.0"
},
"runtime": {
"lib/net10.0/Microsoft.AspNetCore.OpenApi.dll": {
"assemblyVersion": "10.0.2.0",
"fileVersion": "10.0.225.61305"
}
}
},
"Microsoft.IdentityModel.Abstractions/8.15.0": {
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "8.15.0.0",
"fileVersion": "8.15.0.61118"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/8.15.0": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "8.15.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "8.15.0.0",
"fileVersion": "8.15.0.61118"
}
}
},
"Microsoft.IdentityModel.Logging/8.15.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "8.15.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "8.15.0.0",
"fileVersion": "8.15.0.61118"
}
}
},
"Microsoft.IdentityModel.Tokens/8.15.0": {
"dependencies": {
"Microsoft.IdentityModel.Logging": "8.15.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "8.15.0.0",
"fileVersion": "8.15.0.61118"
}
}
},
"Microsoft.OpenApi/2.0.0": {
"runtime": {
"lib/net8.0/Microsoft.OpenApi.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.0.0.0"
}
}
},
"MySqlConnector/2.5.0": {
"runtime": {
"lib/net10.0/MySqlConnector.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.5.0.0"
}
}
},
"SIPSorcery/10.0.3": {
"dependencies": {
"BouncyCastle.Cryptography": "2.6.2",
"Concentus": "2.2.2",
"DnsClient": "1.8.0",
"SIPSorcery.WebSocketSharp": "0.0.1",
"SIPSorceryMedia.Abstractions": "8.0.12"
},
"runtime": {
"lib/net10.0/SIPSorcery.dll": {
"assemblyVersion": "10.0.3.0",
"fileVersion": "10.0.3.0"
}
}
},
"SIPSorcery.WebSocketSharp/0.0.1": {
"runtime": {
"lib/netstandard2.0/websocket-sharp.dll": {
"assemblyVersion": "0.0.1.0",
"fileVersion": "0.0.1.0"
}
}
},
"SIPSorceryMedia.Abstractions/8.0.12": {
"runtime": {
"lib/net8.0/SIPSorceryMedia.Abstractions.dll": {
"assemblyVersion": "8.0.12.0",
"fileVersion": "8.0.12.0"
}
}
},
"System.IdentityModel.Tokens.Jwt/8.15.0": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "8.15.0",
"Microsoft.IdentityModel.Tokens": "8.15.0"
},
"runtime": {
"lib/net10.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "8.15.0.0",
"fileVersion": "8.15.0.61118"
}
}
}
}
},
"libraries": {
"TicketSystem/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"BCrypt.Net-Next/4.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-W+U9WvmZQgi5cX6FS5GDtDoPzUCV4LkBLkywq/kRZhuDwcbavOzcDAr3LXJFqHUi952Yj3LEYoWW0jbEUQChsA==",
"path": "bcrypt.net-next/4.0.3",
"hashPath": "bcrypt.net-next.4.0.3.nupkg.sha512"
},
"BouncyCastle.Cryptography/2.6.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-7oWOcvnntmMKNzDLsdxAYqApt+AjpRpP2CShjMfIa3umZ42UQMvH0tl1qAliYPNYO6vTdcGMqnRrCPmsfzTI1w==",
"path": "bouncycastle.cryptography/2.6.2",
"hashPath": "bouncycastle.cryptography.2.6.2.nupkg.sha512"
},
"Concentus/2.2.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-2B9YmHPKO+k7YpAAnqmiXwiMJnfjfj1C868RszOll2iZWLnGTAiC1q21L/d7CvTan7T+hyqU8dR0Dcy3cpjVfQ==",
"path": "concentus/2.2.2",
"hashPath": "concentus.2.2.2.nupkg.sha512"
},
"DnsClient/1.8.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-RRwtaCXkXWsx0mmsReGDqCbRLtItfUbkRJlet1FpdciVhyMGKcPd57T1+8Jki9ojHlq9fntVhXQroOOgRak8DQ==",
"path": "dnsclient/1.8.0",
"hashPath": "dnsclient.1.8.0.nupkg.sha512"
},
"Microsoft.AspNetCore.OpenApi/10.0.2": {
"type": "package",
"serviceable": true,
"sha512": "sha512-YuEjUNpsoZLs0I5ONt013Z+Udsz3f9sPUh1Xm59LN7+/Z8oVG/swCUYLBbANtfreiunWnoT2uk+5kst4s2jr3Q==",
"path": "microsoft.aspnetcore.openapi/10.0.2",
"hashPath": "microsoft.aspnetcore.openapi.10.0.2.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/8.15.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-e/DApa1GfxUqHSBHcpiQg8yaghKAvFVBQFcWh25jNoRobDZbduTUACY8bZ54eeGWXvimGmEDdF0zkS5Dq16XPQ==",
"path": "microsoft.identitymodel.abstractions/8.15.0",
"hashPath": "microsoft.identitymodel.abstractions.8.15.0.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/8.15.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3513f5VzvOZy3ELd42wGnh1Q3e83tlGAuXFSNbENpgWYoAhLLzgFtd5PiaOPGAU0gqKhYGVzKavghLUGfX3HQg==",
"path": "microsoft.identitymodel.jsonwebtokens/8.15.0",
"hashPath": "microsoft.identitymodel.jsonwebtokens.8.15.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/8.15.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-1gJLjhy0LV2RQMJ9NGzi5Tnb2l+c37o8D8Lrk2mrvmb6OQHZ7XJstd/XxvncXgBpad4x9CGXdipbZzJJCXKyAg==",
"path": "microsoft.identitymodel.logging/8.15.0",
"hashPath": "microsoft.identitymodel.logging.8.15.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/8.15.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-zUE9ysJXBtXlHHRtcRK3Sp8NzdCI1z/BRDTXJQ2TvBoI0ENRtnufYIep0O5TSCJRJGDwwuLTUx+l/bEYZUxpCA==",
"path": "microsoft.identitymodel.tokens/8.15.0",
"hashPath": "microsoft.identitymodel.tokens.8.15.0.nupkg.sha512"
},
"Microsoft.OpenApi/2.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-GGYLfzV/G/ct80OZ45JxnWP7NvMX1BCugn/lX7TH5o0lcVaviavsLMTxmFV2AybXWjbi3h6FF1vgZiTK6PXndw==",
"path": "microsoft.openapi/2.0.0",
"hashPath": "microsoft.openapi.2.0.0.nupkg.sha512"
},
"MySqlConnector/2.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hoAwfHHF8DlRRqwHOhN3u1KLi+XbX/4LPS7Anfa+SYC97vRyIfdEOEEfj1L50q01Ik8aDNvmDrNmu/VPFiAiaQ==",
"path": "mysqlconnector/2.5.0",
"hashPath": "mysqlconnector.2.5.0.nupkg.sha512"
},
"SIPSorcery/10.0.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-+VnD/wvg5myZY2Gj3CXWKdTnfoigv1WyU0uh55pmksT28MBMXBSULLSQt6csNV8VYTJ2aT1CYr9LvBEZrbX6aw==",
"path": "sipsorcery/10.0.3",
"hashPath": "sipsorcery.10.0.3.nupkg.sha512"
},
"SIPSorcery.WebSocketSharp/0.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-lBlR9rZmMty2v5kPzCseAyuSv95FSoGuYZJgDy6M/qqZ/xq1ejFnOVEpXMDqBIthiTUOH8rvMcpnva7HXK0ZVw==",
"path": "sipsorcery.websocketsharp/0.0.1",
"hashPath": "sipsorcery.websocketsharp.0.0.1.nupkg.sha512"
},
"SIPSorceryMedia.Abstractions/8.0.12": {
"type": "package",
"serviceable": true,
"sha512": "sha512-70bYl3RFc0lkL6Z2M2GD/vymnWvmnvTSJfEpFHE4Uh+bp5Rz9DWsEvuF8EZEhaW3foPGvpNIfP5nGj52cCXjgw==",
"path": "sipsorcerymedia.abstractions/8.0.12",
"hashPath": "sipsorcerymedia.abstractions.8.0.12.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/8.15.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dpodi7ixz6hxK8YCBYAWzm0IA8JYXoKcz0hbCbNifo519//rjUI0fBD8rfNr+IGqq+2gm4oQoXwHk09LX5SqqQ==",
"path": "system.identitymodel.tokens.jwt/8.15.0",
"hashPath": "system.identitymodel.tokens.jwt.8.15.0.nupkg.sha512"
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,20 @@
{
"runtimeOptions": {
"tfm": "net10.0",
"frameworks": [
{
"name": "Microsoft.NETCore.App",
"version": "10.0.0"
},
{
"name": "Microsoft.AspNetCore.App",
"version": "10.0.0"
}
],
"configProperties": {
"System.GC.Server": true,
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}

View File

@@ -0,0 +1 @@
{"Version":1,"ManifestType":"Build","Endpoints":[]}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,11 @@
{
"ConnectionStrings": {
"Default": "Server=10.204.192.64;Port=3306;Database=ticket_sys;User Id=root;Password=example;SslMode=None;AllowPublicKeyRetrieval=True;"
//"Default": "jdbc:mysql://10.204.192.110:3306/ticket_sys"
},
"Jwt": {
"Secret": "CHANGE_ME_TO_A_LONG_RANDOM_SECRET_32+_CHARS",
"Issuer": "Ticket-System",
"Audience": "Ticket-System"
}
}

View File

@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "10.0.2",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}

Some files were not shown because too many files have changed in this diff Show More