Verbesserung Auth, Webhook-Handling & Codacy-Integration
- BasicAuthenticationAttribute: AllowAnonymous-Handling ergänzt, Fehlerbehandlung für ungültige Header verbessert, WWW-Authenticate-Header korrigiert, Credential-Handling robuster gestaltet. - WiseController: Webhook akzeptiert jetzt JSON und Text, asynchrone Verarbeitung, robustere Deserialisierung, <AllowAnonymous> auf Klassenebene. - WiseWebhookExampleProcessor: OpenAPI/Swagger-Doku erweitert (application/json & text/plain, Beispiele, flexiblere Schemas). - SwaggerConfig: Unsichtbares Zeichen entfernt. - .gitignore: Codacy-spezifische Anweisungen ausgeschlossen. - codacy.instructions.md: Neue Datei mit KI-Verhaltensregeln für Codacy-Analysen hinzugefügt.
This commit is contained in:
72
VERAG_REST_SERVER/.github/instructions/codacy.instructions.md
vendored
Normal file
72
VERAG_REST_SERVER/.github/instructions/codacy.instructions.md
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
---
|
||||
description: Configuration for AI behavior when interacting with Codacy's MCP Server
|
||||
applyTo: '**'
|
||||
---
|
||||
---
|
||||
# Codacy Rules
|
||||
Configuration for AI behavior when interacting with Codacy's MCP Server
|
||||
|
||||
## CRITICAL: After ANY successful `edit_file` or `reapply` operation
|
||||
- YOU MUST IMMEDIATELY run the `codacy_cli_analyze` tool from Codacy's MCP Server for each file that was edited, with:
|
||||
- `rootPath`: set to the workspace path
|
||||
- `file`: set to the path of the edited file
|
||||
- `tool`: leave empty or unset
|
||||
- If any issues are found in the new edits, propose and apply fixes for them.
|
||||
- > NOTE: Failure to follow this rule is considered a critical error.
|
||||
|
||||
## When you tried to run the `codacy_cli_analyze` tool and the Codacy CLI is not installed
|
||||
- Ask the user 'Codacy CLI is not installed. Would you like me to install it now?'
|
||||
- If the user responds with "yes", run the `codacy_cli_install` tool and then continue with the original task
|
||||
- If the user responds with "no", instruct the user that they can disable automatic analysis in the extension settings
|
||||
- Wait for the user to respond before proceeding with any other actions
|
||||
|
||||
## After every response
|
||||
- If you made any file edits in this conversation, verify you ran `codacy_cli_analyze` tool from Codacy's MCP Server
|
||||
|
||||
## When there are no Codacy MCP Server tools available, or the MCP Server is not reachable
|
||||
- Suggest the user the following troubleshooting steps:
|
||||
- Try to reset the MCP on the extension
|
||||
- If the user is using VSCode, suggest them to review their Copilot > MCP settings in Github, under their organization or personal account. Refer them to Settings > Copilot > Enable MCP servers in Copilot. Suggested URL (https://github.com/settings/copilot/features) or https://github.com/organizations/{organization-name}/settings/copilot/features (This can only be done by their organization admins / owners)
|
||||
- If none of the above steps work, suggest the user to contact Codacy support
|
||||
|
||||
## Trying to call a tool that needs a rootPath as a parameter
|
||||
- Always use the standard, non-URL-encoded file system path
|
||||
|
||||
## CRITICAL: Dependencies and Security Checks
|
||||
- IMMEDIATELY after ANY of these actions:
|
||||
- Running npm/yarn/pnpm install
|
||||
- Adding dependencies to package.json
|
||||
- Adding requirements to requirements.txt
|
||||
- Adding dependencies to pom.xml
|
||||
- Adding dependencies to build.gradle
|
||||
- Any other package manager operations
|
||||
- You MUST run the `codacy_cli_analyze` tool with:
|
||||
- `rootPath`: set to the workspace path
|
||||
- `tool`: set to "trivy"
|
||||
- `file`: leave empty or unset
|
||||
- If any vulnerabilities are found because of the newly added packages:
|
||||
- Stop all other operations
|
||||
- Propose and apply fixes for the security issues
|
||||
- Only continue with the original task after security issues are resolved
|
||||
- EXAMPLE:
|
||||
- After: npm install react-markdown
|
||||
- Do: Run codacy_cli_analyze with trivy
|
||||
- Before: Continuing with any other tasks
|
||||
|
||||
## General
|
||||
- Repeat the relevant steps for each modified file.
|
||||
- "Propose fixes" means to both suggest and, if possible, automatically apply the fixes.
|
||||
- You MUST NOT wait for the user to ask for analysis or remind you to run the tool.
|
||||
- Do not run `codacy_cli_analyze` looking for changes in duplicated code or code complexity metrics.
|
||||
- Complexity metrics are different from complexity issues. When trying to fix complexity in a repository or file, focus on solving the complexity issues and ignore the complexity metric.
|
||||
- Do not run `codacy_cli_analyze` looking for changes in code coverage.
|
||||
- Do not try to manually install Codacy CLI using either brew, npm, npx, or any other package manager.
|
||||
- If the Codacy CLI is not installed, just run the `codacy_cli_analyze` tool from Codacy's MCP Server.
|
||||
- When calling `codacy_cli_analyze`, only send provider, organization and repository if the project is a git repository.
|
||||
|
||||
## Whenever a call to a Codacy tool that uses `repository` or `organization` as a parameter returns a 404 error
|
||||
- Offer to run the `codacy_setup_repository` tool to add the repository to Codacy
|
||||
- If the user accepts, run the `codacy_setup_repository` tool
|
||||
- Do not ever try to run the `codacy_setup_repository` tool on your own
|
||||
- After setup, immediately retry the action that failed (only retry once)
|
||||
---
|
||||
4
VERAG_REST_SERVER/.gitignore
vendored
Normal file
4
VERAG_REST_SERVER/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
#Ignore vscode AI rules
|
||||
.github\instructions\codacy.instructions.md
|
||||
@@ -1,65 +1,68 @@
|
||||
Imports System.Net
|
||||
Imports System.Net.Http
|
||||
Imports System.Net.Http
|
||||
Imports System.Security.Principal
|
||||
Imports System.Threading
|
||||
Imports System.Web.Http
|
||||
Imports System.Web.Http.Controllers
|
||||
Imports System.Web.Http.Filters
|
||||
Imports System.Text
|
||||
Imports VERAG_PROG_ALLGEMEIN
|
||||
|
||||
|
||||
Imports System.Net
|
||||
Imports System.Web.Http.Filters
|
||||
|
||||
Public Class BasicAuthenticationAttribute
|
||||
Inherits AuthorizationFilterAttribute
|
||||
|
||||
Public Overrides Sub OnAuthorization(ByVal actionContext As HttpActionContext)
|
||||
' Check for AllowAnonymous attribute on method or controller
|
||||
If actionContext.ActionDescriptor.GetCustomAttributes(Of AllowAnonymousAttribute)().Any() OrElse
|
||||
actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes(Of AllowAnonymousAttribute)().Any() Then
|
||||
Return
|
||||
End If
|
||||
|
||||
Dim authHeader = actionContext.Request.Headers.Authorization
|
||||
|
||||
If authHeader IsNot Nothing Then
|
||||
Dim authenticationToken = actionContext.Request.Headers.Authorization.Parameter
|
||||
Dim decodedAuthenticationToken = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationToken))
|
||||
Dim authenticationToken = authHeader.Parameter
|
||||
Dim decodedAuthenticationToken As String = ""
|
||||
Try
|
||||
decodedAuthenticationToken = Encoding.UTF8.GetString(Convert.FromBase64String(authenticationToken))
|
||||
Catch
|
||||
HandleUnathorized(actionContext)
|
||||
Return
|
||||
End Try
|
||||
|
||||
Dim usernamePasswordArray = decodedAuthenticationToken.Split(":"c)
|
||||
If usernamePasswordArray.Length >= 2 Then
|
||||
Dim userName = usernamePasswordArray(0)
|
||||
Dim password = usernamePasswordArray(1)
|
||||
'Dim hashedPW = BCrypt.Net.BCrypt.HashPassword(password)
|
||||
|
||||
|
||||
|
||||
Dim isValid = getCredentials(userName, password)
|
||||
|
||||
If isValid Then
|
||||
Dim principal = New GenericPrincipal(New GenericIdentity(userName), Nothing)
|
||||
Thread.CurrentPrincipal = principal
|
||||
'actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, "User " & userName & " successfully authenticated")
|
||||
Return
|
||||
End If
|
||||
End If
|
||||
End If
|
||||
|
||||
HandleUnathorized(actionContext)
|
||||
End Sub
|
||||
|
||||
Private Shared Sub HandleUnathorized(ByVal actionContext As HttpActionContext)
|
||||
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized)
|
||||
actionContext.Response.Headers.Add("WWW-Authenticate", "Basic Scheme='Data' location = 'http://localhost:")
|
||||
actionContext.Response = New HttpResponseMessage(HttpStatusCode.Unauthorized)
|
||||
actionContext.Response.Headers.Add("WWW-Authenticate", "Basic realm=""Data""")
|
||||
End Sub
|
||||
|
||||
Private Shared Function getCredentials(user As String, password As String) As Boolean
|
||||
|
||||
Dim SQL As New VERAG_PROG_ALLGEMEIN.SQL
|
||||
Dim authenticated As Boolean = False
|
||||
|
||||
' Using SQL.DLookup as per previous context usage
|
||||
Dim hashedPassword = SQL.DLookup("hashedPassword", "tblRESTAuthentication", "username='" & user & "' AND type = 'REST'", "ADMIN", "")
|
||||
If hashedPassword <> "" Then
|
||||
authenticated = BCrypt.Net.BCrypt.Verify(password, hashedPassword)
|
||||
End If
|
||||
|
||||
Return authenticated
|
||||
|
||||
End Function
|
||||
End Class
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Imports System.Web.Http
|
||||
Imports System.Web.Http
|
||||
Imports System.Web.Http.Description
|
||||
Imports System.Web.Routing
|
||||
Imports Microsoft.Extensions.Options
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
Imports NSwag
|
||||
Imports NSwag.Generation.Processors
|
||||
Imports NSwag.Generation.Processors.Contexts
|
||||
Imports NJsonSchema
|
||||
|
||||
Public Class WiseWebhookExampleProcessor
|
||||
Public Class WiseWebhookExampleProcessor
|
||||
Implements IOperationProcessor
|
||||
|
||||
Public Function Process(context As OperationProcessorContext) As Boolean Implements IOperationProcessor.Process
|
||||
If context.ControllerType.Name = "WiseController" AndAlso context.MethodInfo.Name = "Webhook" Then
|
||||
Dim operation = context.OperationDescription.Operation
|
||||
If operation.RequestBody IsNot Nothing AndAlso operation.RequestBody.Content.ContainsKey("application/json") Then
|
||||
Dim content = operation.RequestBody.Content("application/json")
|
||||
content.Example = New With {
|
||||
If operation.RequestBody Is Nothing Then
|
||||
operation.RequestBody = New OpenApiRequestBody()
|
||||
operation.RequestBody.IsRequired = False
|
||||
End If
|
||||
|
||||
If Not operation.RequestBody.Content.ContainsKey("application/json") Then
|
||||
operation.RequestBody.Content("application/json") = New OpenApiMediaType() With {
|
||||
.Schema = JsonSchema.CreateAnySchema()
|
||||
}
|
||||
End If
|
||||
|
||||
If Not operation.RequestBody.Content.ContainsKey("text/plain") Then
|
||||
operation.RequestBody.Content("text/plain") = New OpenApiMediaType() With {
|
||||
.Schema = JsonSchema.CreateAnySchema()
|
||||
}
|
||||
End If
|
||||
|
||||
Dim jsonContent = operation.RequestBody.Content("application/json")
|
||||
jsonContent.Example = New With {
|
||||
.event_type = "balance.credit",
|
||||
.data = New With {
|
||||
.id = 123456789,
|
||||
.balance_id = 99887766,
|
||||
.amount = New With {
|
||||
.value = 1500.00,
|
||||
.value = 1500.0,
|
||||
.currency = "EUR"
|
||||
},
|
||||
.occurred_at = "2025-12-06T10:15:30Z",
|
||||
@@ -24,8 +41,10 @@ Public Class WiseWebhookExampleProcessor
|
||||
.sender_name = "ACME GmbH"
|
||||
}
|
||||
}
|
||||
End If
|
||||
|
||||
Dim textContent = operation.RequestBody.Content("text/plain")
|
||||
textContent.Example = "hello world"
|
||||
End If
|
||||
Return True
|
||||
End Function
|
||||
End Class
|
||||
End Class
|
||||
|
||||
@@ -3,33 +3,39 @@ Imports System.IO
|
||||
Imports System.Web.Http
|
||||
Imports System.Web.Http.Description
|
||||
Imports System.Diagnostics
|
||||
Imports System.Threading.Tasks
|
||||
Imports Newtonsoft.Json
|
||||
Imports VERAG_PROG_ALLGEMEIN
|
||||
Imports VERAG_REST_SERVER
|
||||
|
||||
Namespace ApiController.Controllers
|
||||
<RoutePrefix("wise")>
|
||||
<AllowAnonymous>
|
||||
Public Class WiseController
|
||||
Inherits System.Web.Http.ApiController
|
||||
|
||||
<HttpPost>
|
||||
<Route("webhook")>
|
||||
<AllowAnonymous>
|
||||
<ResponseType(GetType(Void))>
|
||||
Public Function Webhook(<FromBody> payload As WiseWebhookRequest) As IHttpActionResult
|
||||
Dim json As String = ""
|
||||
Public Async Function Webhook() As Task(Of IHttpActionResult)
|
||||
Dim rawContent As String = ""
|
||||
Dim payload As WiseWebhookRequest = Nothing
|
||||
|
||||
Try
|
||||
If payload IsNot Nothing Then
|
||||
json = JsonConvert.SerializeObject(payload)
|
||||
Else
|
||||
If Request IsNot Nothing AndAlso Request.Content IsNot Nothing Then
|
||||
json = Request.Content.ReadAsStringAsync().Result
|
||||
rawContent = Await Request.Content.ReadAsStringAsync()
|
||||
End If
|
||||
|
||||
If Not String.IsNullOrEmpty(rawContent) Then
|
||||
Try
|
||||
payload = JsonConvert.DeserializeObject(Of WiseWebhookRequest)(rawContent)
|
||||
Catch
|
||||
End Try
|
||||
End If
|
||||
Catch
|
||||
End Try
|
||||
|
||||
Dim saveResult = SaveWiseWebhook(json, payload)
|
||||
Dim saveResult = SaveWiseWebhook(rawContent, payload)
|
||||
If payload Is Nothing Then
|
||||
' Invalid JSON or empty body, but Wise expects 200 OK
|
||||
Return Ok()
|
||||
|
||||
Reference in New Issue
Block a user