Compare commits

...

6 Commits

Author SHA1 Message Date
6dfd21da3b Restliche Funktionen Hinzugefügt
Siehe Projekttagebuch
2026-02-04 14:32:53 +01:00
34366d782c Solution hinzugefügt
Solution hinzugefügt (keine Ahnung ob du das brauchst)
2026-01-30 12:23:51 +01:00
a5418de3ac obj Ordner Entfernt
obj Ordner Entfernt
2026-01-30 12:18:32 +01:00
db79b5c426 Altes Projekt entfernt
Alle Verweise auf das alte Ticket_System entfernt
2026-01-30 11:54:59 +01:00
690987eb8f Änderung aller Features auf API
Ticket_System wurde zu TicketSystem in TicketSystem ist nun eine API.WEB Core anwendung. Implementierung von /signin, /user/create, /ticket/create, /ticket/show/all, /ticket/show/{ticketID}
2026-01-30 11:51:31 +01:00
07b2a8ae0f Start der Backend Implementierung
Projekt für die Implementierung des Backends hinzugefügt. Klasse Logger --> Dient zum Loggen in die Datenbank. Klasse Ticket_System --> Hauptklasse für das die Backendanwendung. Auth Client hinzugefügt. Token stuff hinzugefügt.
2026-01-28 14:19:27 +01:00
442 changed files with 8657 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
Ticket_System/.vs/Ticket_System.slnx/FileContentIndex/0feacb2f-8a75-4aea-a458-71b4bcd73a3a.vsidx
Ticket_System/.vs/Ticket_System.slnx/FileContentIndex/ec0e104f-1dbc-4210-8c14-8ddf7754c5bd.vsidx
Ticket_System/.vs/Ticket_System.slnx/FileContentIndex/37c5788e-c610-48cc-80fe-81ac644a485a.vsidx
Ticket_System/obj

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": ""
}
]
}
]
}
]
}

18
TicketSystem/Logger.cs Normal file
View File

@@ -0,0 +1,18 @@
using System;
using MySqlConnector;
namespace Ticket_System
{
public class Logger
{
public void Log(string message, string userID)
{
string sql = $"insert into Log (LogID, ErrorMessage, datetime, User) values ((select max LogID from Log) + 1), {message}, {DateTime.Now},{userID})";
MySqlCommand cmd = new MySqlCommand(sql);
cmd.ExecuteNonQuery();
}
}
}

987
TicketSystem/Program.cs Normal file
View File

@@ -0,0 +1,987 @@
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);
var connectionString = builder.Configuration.GetConnectionString("Default");
var jwtSecret = builder.Configuration["Jwt:Secret"] ?? "CHANGE_ME_TO_A_LONG_RANDOM_SECRET";
var jwtIssuer = builder.Configuration["Jwt:Issuer"] ?? "Ticket-System";
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("/webrtc", StringComparison.OrdinalIgnoreCase)
|| path.Equals("/user/create", StringComparison.OrdinalIgnoreCase))
{
await next();
return;
}
if (!context.Request.Headers.TryGetValue("Authorization", out var authHeaderValues))
{
context.Response.StatusCode = StatusCodes.Status403Forbidden;
await context.Response.WriteAsJsonAsync(new { error = "Please add the JWT token to the header" });
return;
}
var authHeader = authHeaderValues.ToString();
var parts = authHeader.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length != 2 || !parts[0].Equals("Bearer", StringComparison.OrdinalIgnoreCase))
{
context.Response.StatusCode = StatusCodes.Status409Conflict;
await context.Response.WriteAsJsonAsync(new { error = "Invalid token specified" });
return;
}
var token = parts[1];
var principal = ValidateJwt(token, jwtSecret, jwtIssuer, jwtAudience);
if (principal == null)
{
context.Response.StatusCode = StatusCodes.Status403Forbidden;
await context.Response.WriteAsJsonAsync(new { error = "Invalid token specified" });
return;
}
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.user);
await using var reader = await cmd.ExecuteReaderAsync();
if (!await reader.ReadAsync())
return Results.Unauthorized();
var userId = reader.GetInt32("userID").ToString();
var username = reader.GetString("username");
var pwHash = reader.GetString("password");
var ok = BCrypt.Net.BCrypt.Verify(req.password, pwHash);
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);
}
});
#region web rtc
app.Map("/webrtc", async context =>
{
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) =>
{
var user = ctx.Items["user"]?.ToString() ?? "";
return Results.Ok(new { user });
});
app.MapPost("/user/create", async (RegisterRequest req, MySqlConnection conn) =>
{
await conn.OpenAsync();
var pwHash = BCrypt.Net.BCrypt.HashPassword(req.password);
var userId = Guid.NewGuid().ToString("N");
const string insertSql = """
INSERT INTO User (userID, username, password)
VALUES (@userID, @username, @password);
""";
await using var cmd = new MySqlCommand(insertSql, conn);
cmd.Parameters.AddWithValue("@userID", userId);
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.user, jwtSecret, jwtIssuer, jwtAudience, minutesValid: 120);
return Results.Created($"/user/{userId}", new ResponseToken(token));
});
app.MapGet("/user/show/all", 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 *
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,
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", 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 angelegt werden");
var ticketId = cmd.LastInsertedId;
return Results.Created($"/ticket/show/{ticketId}", new
{
ticketID = ticketId
});
});
app.MapGet("/ticket/show/all", 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
t.ticketID,
t.ticketname,
owner.username AS owner_name,
t.status,
t.priority,
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;
""";
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@userID", userId);
await using var reader = await cmd.ExecuteReaderAsync();
var tickets = new List<object>();
while (await reader.ReadAsync())
{
tickets.Add(new
{
ticketID = reader.GetInt64("ticketID"),
ticketname = reader.GetString("ticketname"),
username = reader.IsDBNull("owner_name") ? "" : reader.GetString("owner_name"),
status = reader.GetInt32("status"),
priority = reader.GetInt32("priority"),
categoryId = reader.IsDBNull("categoryId") ? 0 : Convert.ToInt32(reader.GetInt32("categoryId")),
});
}
return Results.Ok(tickets);
});
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,
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
LIMIT 1;
""";
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))
{
cmd.Parameters.AddWithValue("@ticketId", ticketId);
cmd.Parameters.AddWithValue("@userId", userId);
await using var reader = await cmd.ExecuteReaderAsync();
if (!await reader.ReadAsync())
return Results.NotFound("Ticket nicht gefunden");
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,
u.username AS senderUsername
FROM Messages m
LEFT JOIN User u ON u.userID = m.sender
WHERE m.ticketID = @ticketId
ORDER BY m.sequence ASC;
""";
var vmessages = new List<object>();
await using (var cmd = new MySqlCommand(messagesSql, conn))
{
cmd.Parameters.AddWithValue("@ticketId", ticketId);
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
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")
});
}
}
return Results.Ok(new
{
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));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Name, username),
};
var token = new JwtSecurityToken(
issuer: issuer,
audience: audience,
claims: claims,
notBefore: DateTime.UtcNow,
expires: DateTime.UtcNow.AddMinutes(minutesValid),
signingCredentials: creds
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
static ClaimsPrincipal? ValidateJwt(string token, string secret, string issuer, string audience)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));
var handler = new JwtSecurityTokenHandler();
try
{
var principal = handler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = issuer,
ValidateAudience = true,
ValidAudience = audience,
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromSeconds(30)
}, out _);
return principal;
}
catch
{
return null;
}
;
}
app.Run();
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 Ticket(
int status,
int priority,
string category,
string username,
string ticketname,
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

@@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"applicationUrl": "http://localhost:5278",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,26 @@
<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>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<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>
<ItemGroup>
<Folder Include="Controllers\" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<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

@@ -0,0 +1,7 @@
# @TicketSystem_HostAddress = http://10.204.192.64:3000/home
@TicketSystem_HostAddress =http://localhost:5278
GET {{TicketSystem_HostAddress}}/TicketSystem/
Accept: application/json
###

View File

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

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"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,181 @@
{
"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",
"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"
}
}
},
"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"
}
}
},
"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"
},
"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"
},
"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,19 @@
{
"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.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,10 @@
{
"ConnectionStrings": {
"Default": "Server=10.204.192.110;Port=3306;Database=ticket_sys;User Id=root;Password=example;SslMode=None;AllowPublicKeyRetrieval=True;",
},
"Jwt": {
"Secret": "CHANGE_ME_TO_A_LONG_RANDOM_SECRET_32+_CHARS",
"Issuer": "Ticket-System",
"Audience": "Ticket-System"
}
}

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