diff --git a/.github/workflows/Centos_build.yml b/.github/workflows/Centos_build.yml index 24f0c2ca..debcdf7c 100644 --- a/.github/workflows/Centos_build.yml +++ b/.github/workflows/Centos_build.yml @@ -3,7 +3,7 @@ name: centos build workflows on: push: branches: - - 'develop' + - 'develop1' paths: - 'XEngine_Source/**' - 'XEngine_Release/**' @@ -93,7 +93,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-CentOS_${{ matrix.version }}_${{ matrix.artifact }} path: XEngine_Release/ \ No newline at end of file diff --git a/.github/workflows/Rocky_build.yml b/.github/workflows/Rocky_build.yml index 96a5b7d3..0ff263d1 100644 --- a/.github/workflows/Rocky_build.yml +++ b/.github/workflows/Rocky_build.yml @@ -95,7 +95,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact with RockyLinux - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-RockyLinux_${{ matrix.version }}_${{ matrix.artifact }} path: XEngine_Release/ diff --git a/.github/workflows/Ubuntu_build.yml b/.github/workflows/Ubuntu_build.yml index 3eea97a5..c500ad31 100644 --- a/.github/workflows/Ubuntu_build.yml +++ b/.github/workflows/Ubuntu_build.yml @@ -102,28 +102,28 @@ jobs: - name: Upload folder as artifact with ubuntu22.04 if: matrix.os == 'ubuntu-22.04' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_22.04_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with ubuntu24.04 if: matrix.os == 'ubuntu-24.04' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_24.04_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with ubuntu24.04 arm64 if: matrix.os == 'ubuntu-24.04-arm' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_24.04_Arm64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with ubuntu22.04 arm64 if: matrix.os == 'ubuntu-22.04-arm' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Ubuntu_22.04_Arm64 path: XEngine_Release/ diff --git a/.github/workflows/agentics-maintenance.yml b/.github/workflows/agentics-maintenance.yml new file mode 100644 index 00000000..6bd015f5 --- /dev/null +++ b/.github/workflows/agentics-maintenance.yml @@ -0,0 +1,607 @@ +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by pkg/workflow/maintenance_workflow.go (v0.79.6). DO NOT EDIT. +# +# To regenerate this workflow, run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# Alternative regeneration methods: +# make recompile +# +# Or use the gh-aw CLI directly: +# ./gh-aw compile --validate --verbose +# +# The workflow is generated when any workflow uses the 'expires' field +# in create-discussions, create-issues, or create-pull-request safe-outputs configuration. +# Schedule frequency is automatically determined by the shortest expiration time. +# +name: Agentic Maintenance + +on: + schedule: + - cron: "37 0 * * *" # Daily (based on minimum expires: 30 days) + workflow_dispatch: + inputs: + operation: + description: 'Optional maintenance operation to run' + required: false + type: choice + default: '' + options: + - '' + - 'disable' + - 'enable' + - 'update' + - 'upgrade' + - 'safe_outputs' + - 'create_labels' + - 'activity_report' + - 'close_agentic_workflows_issues' + - 'clean_cache_memories' + - 'update_pull_request_branches' + - 'validate' + - 'forecast' + run_url: + description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.' + required: false + type: string + default: '' + workflow_call: + inputs: + operation: + description: 'Optional maintenance operation to run (disable, enable, update, upgrade, safe_outputs, create_labels, activity_report, close_agentic_workflows_issues, clean_cache_memories, update_pull_request_branches, validate, forecast)' + required: false + type: string + default: '' + run_url: + description: 'Run URL or run ID to replay safe outputs from (e.g. https://github.com/owner/repo/actions/runs/12345 or 12345). Required when operation is safe_outputs.' + required: false + type: string + default: '' + outputs: + operation_completed: + description: 'The maintenance operation that was completed (empty when none ran or a scheduled job ran)' + value: ${{ jobs.run_operation.outputs.operation || inputs.operation }} + applied_run_url: + description: 'The run URL that safe outputs were applied from' + value: ${{ jobs.apply_safe_outputs.outputs.run_url }} + +permissions: {} + +jobs: + close-expired-entities: + if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '') }} + runs-on: ubuntu-slim + permissions: + discussions: write + issues: write + pull-requests: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Close expired discussions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_discussions.cjs'); + await main(); + + - name: Close expired issues + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_issues.cjs'); + await main(); + + - name: Close expired pull requests + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_expired_pull_requests.cjs'); + await main(); + + cleanup-cache-memory: + if: ${{ (!(github.event.repository.fork)) && github.event_name != 'push' && (github.event_name != 'workflow_dispatch' && github.event_name != 'workflow_call' || inputs.operation == '' || inputs.operation == 'clean_cache_memories') }} + runs-on: ubuntu-slim + permissions: + actions: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Cleanup outdated cache-memory entries + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/cleanup_cache_memory.cjs'); + await main(); + + run_operation: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation != '' && inputs.operation != 'safe_outputs' && inputs.operation != 'create_labels' && inputs.operation != 'activity_report' && inputs.operation != 'close_agentic_workflows_issues' && inputs.operation != 'clean_cache_memories' && inputs.operation != 'update_pull_request_branches' && inputs.operation != 'validate' && inputs.operation != 'forecast' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + actions: write + contents: write + pull-requests: write + outputs: + operation: ${{ steps.record.outputs.operation }} + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Run operation + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_OPERATION: ${{ inputs.operation }} + GH_AW_CMD_PREFIX: gh aw + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/run_operation_update_upgrade.cjs'); + await main(); + + - name: Record outputs + id: record + run: echo "operation=${{ inputs.operation }}" >> "$GITHUB_OUTPUT" + + update_pull_request_branches: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'update_pull_request_branches' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + contents: write + pull-requests: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Update pull request branches + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/update_pull_request_branches.cjs'); + await main(); + + apply_safe_outputs: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'safe_outputs' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + actions: read + contents: write + discussions: write + issues: write + pull-requests: write + outputs: + run_url: ${{ steps.record.outputs.run_url }} + steps: + - name: Checkout actions folder + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + sparse-checkout: | + actions + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Apply Safe Outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_RUN_URL: ${{ inputs.run_url }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/apply_safe_outputs_replay.cjs'); + await main(); + + - name: Record outputs + id: record + run: echo "run_url=${{ inputs.run_url }}" >> "$GITHUB_OUTPUT" + + create_labels: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'create_labels' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Create missing labels + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_CMD_PREFIX: gh aw + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/create_labels.cjs'); + await main(); + + activity_report: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'activity_report' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + timeout-minutes: 120 + permissions: + actions: read + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Restore activity report logs cache + id: activity_report_logs_cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.cache/gh-aw/activity-report-logs + key: ${{ runner.os }}-activity-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-activity-report-logs-${{ github.repository }}- + ${{ runner.os }}-activity-report-logs- + - name: Download activity report logs + timeout-minutes: 20 + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_CMD_PREFIX: gh aw + run: | + ${GH_AW_CMD_PREFIX} logs \ + --repo "${{ github.repository }}" \ + --start-date -1w \ + --count 100 \ + --output ./.cache/gh-aw/activity-report-logs \ + --format markdown \ + > ./.cache/gh-aw/activity-report-logs/report.md + + - name: Save activity report logs cache + if: ${{ always() }} + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.cache/gh-aw/activity-report-logs + key: ${{ steps.activity_report_logs_cache.outputs.cache-primary-key }} + + - name: Generate activity report issue + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('node:fs'); + const reportPath = './.cache/gh-aw/activity-report-logs/report.md'; + if (!fs.existsSync(reportPath)) { + core.warning('Activity report markdown not found at ' + reportPath + '; skipping issue creation.'); + return; + } + let reportBody = ''; + try { + reportBody = fs.readFileSync(reportPath, 'utf8').trim(); + } catch (error) { + core.warning('Failed to read activity report markdown at ' + reportPath + ': ' + error.message); + return; + } + if (!reportBody) { + core.warning('Activity report markdown is empty at ' + reportPath + '; skipping issue creation.'); + return; + } + const repoSlug = context.repo.owner + '/' + context.repo.repo; + const body = [ + '### Agentic workflow activity report', + '', + 'Repository: ' + repoSlug, + 'Generated at: ' + new Date().toISOString(), + '', + reportBody, + ].join('\n'); + const createdIssue = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '[aw] agentic status report', + body, + labels: ['agentic-workflows'], + }); + core.info('Created issue #' + createdIssue.data.number + ': ' + createdIssue.data.html_url); + + forecast_report: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'forecast' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + timeout-minutes: 60 + permissions: + actions: read + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Restore forecast report logs cache + id: forecast_report_logs_cache + uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.github/aw/logs + key: ${{ runner.os }}-forecast-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }} + restore-keys: | + ${{ runner.os }}-forecast-report-logs-${{ github.repository }}- + ${{ runner.os }}-forecast-report-logs- + + - name: Generate forecast report + id: generate_forecast_report + timeout-minutes: 30 + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DEBUG: "*" + GH_AW_CMD_PREFIX: gh aw + run: | + mkdir -p ./.cache/gh-aw/forecast + set +e + ${GH_AW_CMD_PREFIX} forecast --repo "${{ github.repository }}" --timeout 30 --verbose --json > ./.cache/gh-aw/forecast/report.json + forecast_exit_code=$? + set -e + if [ "${forecast_exit_code}" -eq 124 ]; then + echo '{"outcome":"timeout","message":"Forecast computation timed out after 30 minutes."}' > ./.cache/gh-aw/forecast/error.json + echo "::error::Forecast computation timed out after 30 minutes." + exit 1 + fi + if [ "${forecast_exit_code}" -ne 0 ]; then + echo '{"outcome":"error","message":"Forecast computation failed before producing a report."}' > ./.cache/gh-aw/forecast/error.json + echo "::error::Forecast computation failed with exit code ${forecast_exit_code}." + exit 1 + fi + + - name: Debug forecast logs folder + if: ${{ always() }} + shell: bash + run: | + if [ ! -d ./.github/aw/logs ]; then + echo "Logs directory not found: ./.github/aw/logs" + exit 0 + fi + echo "Files under ./.github/aw/logs:" + find ./.github/aw/logs -type f | sort + + - name: Save forecast report logs cache + if: ${{ always() }} + uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: ./.github/aw/logs + key: ${{ runner.os }}-forecast-report-logs-${{ github.repository }}-${{ github.ref_name }}-${{ github.run_id }} + + - name: Generate forecast issue + if: ${{ always() }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + FORECAST_STEP_OUTCOME: ${{ steps.generate_forecast_report.outcome }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/create_forecast_issue.cjs'); + await main(); + + close_agentic_workflows_issues: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'close_agentic_workflows_issues' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-slim + permissions: + issues: write + steps: + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Close no-repro agentic-workflows issues + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/close_agentic_workflows_issues.cjs'); + await main(); + + validate_workflows: + if: ${{ (github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_call') && inputs.operation == 'validate' && (!(github.event.repository.fork)) }} + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Setup Scripts + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + + - name: Check admin/maintainer permissions + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_team_member.cjs'); + await main(); + + - name: Install gh-aw + uses: github/gh-aw-actions/setup-cli@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + version: v0.79.6 + + - name: Validate workflows and file issue on findings + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_CMD_PREFIX: gh aw + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/run_validate_workflows.cjs'); + await main(); diff --git a/.github/workflows/auto-code.lock.yml b/.github/workflows/auto-code.lock.yml new file mode 100644 index 00000000..2a10a786 --- /dev/null +++ b/.github/workflows/auto-code.lock.yml @@ -0,0 +1,1327 @@ +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"2db2d71c8e339e852eac5725e4d115b95a5f802b476179caca5c78d07e99d221","body_hash":"f4631eca0387739bc44c8ad08d5c0670c98c72198743c2ea9240d97915dca04e","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.79.6). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - GH_AW_CI_TRIGGER_TOKEN +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# - OPENAI_API_KEY +# +# Custom actions used: +# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 +# +# Container images used: +# - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + +name: "自动处理 Issue" +on: + issues: + types: + - labeled + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" + +run-name: "自动处理 Issue" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + env: + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + outputs: + body: ${{ steps.sanitized.outputs.body }} + comment_id: "" + comment_repo: "" + daily_effective_workflow_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_exceeded == 'true' }} + daily_effective_workflow_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_threshold || '' }} + daily_effective_workflow_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_total_effective_tokens || '' }} + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }} + safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Generate agentic run info + id: generate_aw_info + env: + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_CLI_VERSION: "v0.79.6" + GH_AW_INFO_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "false" + GH_AW_INFO_AWF_VERSION: "" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "" + GH_AW_COMPILED_STRICT: "false" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Check daily workflow token guardrail + id: daily-effective-workflow-guardrail + if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_ID: "auto-code" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} + GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + .antigravity + .claude + .codex + .crush + .gemini + .opencode + .pi + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_FILE: "auto-code.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_COMPILED_VERSION: "v0.79.6" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' + + GH_AW_PROMPT_791c723be483e095_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' + + Tools: add_comment, create_pull_request, missing_tool, missing_data, noop + GH_AW_PROMPT_791c723be483e095_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' + + GH_AW_PROMPT_791c723be483e095_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' + + The following GitHub context information is available for this workflow: + {{#if github.actor}} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if github.repository}} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if github.workspace}} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}} + - **issue-number**: #__GH_AW_EXPR_802A9F6A__ + {{/if}} + {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} + - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ + {{/if}} + {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}} + - **pull-request-number**: #__GH_AW_EXPR_463A214A__ + {{/if}} + {{#if github.event.comment.id || github.aw.context.comment_id}} + - **comment-id**: __GH_AW_EXPR_FF1D34CE__ + {{/if}} + {{#if github.run_id}} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_791c723be483e095_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_791c723be483e095_EOF' + + {{#runtime-import .github/workflows/auto-code.md}} + GH_AW_PROMPT_791c723be483e095_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, + GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + include-hidden-files: true + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/model_multipliers.json + /tmp/gh-aw/models.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/prompt-template.txt + /tmp/gh-aw/aw-prompts/prompt-import-tree.json + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + /tmp/gh-aw/.github/agents + /tmp/gh-aw/.github/skills + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true' + runs-on: ubuntu-latest + permissions: + contents: read + copilot-requests: write + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: autocode + outputs: + agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} + ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} + aic: ${{ steps.parse-mcp-gateway.outputs.aic }} + ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }} + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Set runtime paths + id: set-runtime-paths + run: | + { + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" + } >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" + - name: Configure gh CLI for GitHub Enterprise + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" + env: + GH_TOKEN: ${{ github.token }} + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com + - name: Parse integrity filter lists + id: parse-guard-vars + env: + GH_AW_BLOCKED_USERS_VAR: ${{ vars.GH_AW_GITHUB_BLOCKED_USERS || '' }} + GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} + GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" + - name: Restore inline sub-agents from activation artifact + env: + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.md" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh" + - name: Restore inline skills from activation artifact + env: + GH_AW_SKILL_DIR: ".github/skills" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + - name: Generate Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_b5dafa3335f30723_EOF' + {"add_comment":{"max":1},"create_pull_request":{"base_branch":"develop","max":1,"max_patch_files":100,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"protected_files_policy":"allowed"},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_b5dafa3335f30723_EOF + - name: Generate Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", + "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "create_pull_request": { + "defaultMax": 1, + "fields": { + "base": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "branch": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "draft": { + "type": "boolean" + }, + "labels": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + }, + "title": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="localhost" + export MCP_GATEWAY_HOST_DOMAIN="localhost" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + case "${DOCKER_HOST:-}" in + unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; + /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; + * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; + esac + DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + + mkdir -p /home/runner/.copilot + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_f41962abaffbda74_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v1.1.2", + "env": { + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "min-integrity": "none", + "repos": "all", + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_f41962abaffbda74_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + # --allow-tool shell(cat) + # --allow-tool shell(date) + # --allow-tool shell(echo) + # --allow-tool shell(git add:*) + # --allow-tool shell(git branch:*) + # --allow-tool shell(git checkout:*) + # --allow-tool shell(git commit:*) + # --allow-tool shell(git merge:*) + # --allow-tool shell(git rm:*) + # --allow-tool shell(git status) + # --allow-tool shell(git switch:*) + # --allow-tool shell(grep) + # --allow-tool shell(head) + # --allow-tool shell(ls) + # --allow-tool shell(printf) + # --allow-tool shell(pwd) + # --allow-tool shell(safeoutputs:*) + # --allow-tool shell(sort) + # --allow-tool shell(tail) + # --allow-tool shell(uniq) + # --allow-tool shell(wc) + # --allow-tool shell(yq) + # --allow-tool write + timeout-minutes: 20 + run: | + set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --allow-tool 'shell(cat)' --allow-tool 'shell(date)' --allow-tool 'shell(echo)' --allow-tool 'shell(git add:*)' --allow-tool 'shell(git branch:*)' --allow-tool 'shell(git checkout:*)' --allow-tool 'shell(git commit:*)' --allow-tool 'shell(git merge:*)' --allow-tool 'shell(git rm:*)' --allow-tool 'shell(git status)' --allow-tool 'shell(git switch:*)' --allow-tool 'shell(grep)' --allow-tool 'shell(head)' --allow-tool 'shell(ls)' --allow-tool 'shell(printf)' --allow-tool 'shell(pwd)' --allow-tool 'shell(safeoutputs:*)' --allow-tool 'shell(sort)' --allow-tool 'shell(tail)' --allow-tool 'shell(uniq)' --allow-tool 'shell(wc)' --allow-tool 'shell(yq)' --allow-tool write --allow-all-paths --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_MODEL: doubao-seed-evolving + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_TIMEOUT_MINUTES: 20 + GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true + XDG_CONFIG_HOME: /home/runner + - name: Detect agent errors + if: always() + id: detect-agent-errors + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs" + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Write agent output placeholder if missing + if: always() + run: | + if [ ! -f /tmp/gh-aw/agent_output.json ]; then + echo '{"items":[]}' > /tmp/gh-aw/agent_output.json + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + /tmp/gh-aw/aw-*.patch + /tmp/gh-aw/aw-*.bundle + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_effective_workflow_exceeded == 'true') + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-auto-code" + cancel-in-progress: false + queue: max + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Collect usage artifact files + if: always() + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection + echo "Usage artifact source file status:" + for file in /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do + [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file" + done + [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true + [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true + [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl + [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl + find /tmp/gh-aw/usage -type f -print | sort + - name: Upload usage artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/detection/token_usage.jsonl + if-no-files-found: ignore + - name: Process no-op messages + id: noop + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_WORKFLOW_ID: "auto-code" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "auto-code" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" + GH_AW_ENGINE_ID: "copilot" + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} + GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} + GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} + GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} + GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }} + GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }} + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_effective_workflow_total_effective_tokens }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_THRESHOLD: ${{ needs.activation.outputs.daily_effective_workflow_threshold }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + if: (!cancelled()) && needs.agent.result != 'skipped' + runs-on: ubuntu-slim + permissions: + contents: write + discussions: write + issues: write + pull-requests: write + timeout-minutes: 45 + env: + GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/auto-code" + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" + GH_AW_WORKFLOW_ID: "auto-code" + GH_AW_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/auto-code.md" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }} + created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "自动处理 Issue" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/auto-code.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Download patch artifact + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Extract base branch from agent output + id: extract-base-branch + if: steps.download-agent-output.outcome == 'success' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/extract_base_branch_from_agent_output.cjs'); + await main(); + - name: Checkout repository (trusted default branch for comment events) + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && (github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment') + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + ref: ${{ github.event.repository.default_branch }} + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Checkout repository + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') && github.event_name != 'issue_comment' && github.event_name != 'pull_request_review_comment' + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + ref: develop + token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + persist-credentials: false + fetch-depth: 1 + - name: Configure Git credentials + if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input. + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"create_pull_request\":{\"base_branch\":\"develop\",\"max\":1,\"max_patch_files\":100,\"max_patch_size\":1024,\"protect_top_level_dot_folders\":true,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"CODEOWNERS\",\"DESIGN.md\",\"README.md\",\"CONTRIBUTING.md\",\"CHANGELOG.md\",\"SECURITY.md\",\"CODE_OF_CONDUCT.md\",\"AGENTS.md\",\"CLAUDE.md\",\"GEMINI.md\"],\"protected_files_policy\":\"allowed\"},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/auto-code.md b/.github/workflows/auto-code.md new file mode 100644 index 00000000..f73bb475 --- /dev/null +++ b/.github/workflows/auto-code.md @@ -0,0 +1,123 @@ +--- +on: + issues: + types: [labeled] + +engine: + id: copilot + env: + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} + COPILOT_MODEL: doubao-seed-evolving + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses + +features: + dangerously-disable-sandbox-agent: "controlled environment for issue triage automation" +sandbox: + agent: false +strict: false + +network: + allowed: + - defaults + - ark.cn-beijing.volces.com + +tools: + github: + min-integrity: none + +permissions: + contents: read + issues: read + pull-requests: read + copilot-requests: write + +safe-outputs: + threat-detection: false + create-pull-request: + base-branch: develop + protected-files: allowed + add-comment: + max: 1 +--- + +# 自动处理 Issue + +当 Issue 被打上 `bug` 或 `enhancement` 或 `feature` 标签时触发。其他标签直接退出,不做任何操作。 + +## 判断任务类型 + +读取 Issue #${{ github.event.issue.number }} 当前的标签: +- 如果包含 `bug` 标签 → 执行【Bug 修复流程】 +- 如果包含 `feature` 标签 → 执行【新功能开发流程】 +- 如果包含 `enhancement` 标签 → 执行【功能改进开发流程】 +- 其他情况 → 直接退出 + +## 任务执行限制 +- 根据需求查找相对应的可能关联的代码文件 +- 尽量只读取相关代码文件和文档,不去操作无关代码和文件 +- 尽量减少操作时间和步骤,减少TOKEN和时间消耗 + +--- + + +## Bug 修复流程 + +1. 阅读 Issue 的完整标题和正文,理解问题现象 +2. 浏览仓库相关代码和文档,定位问题所在的文件和函数 +3. 分析根本原因 +4. 实现修复方案,注意: + - 保持与现有代码风格一致 + - 只修改必要的部分,不做无关改动 +5. 创建 Pull Request,标题格式:`fix: `,描述中说明: + - 问题根因 + - 修复方式 + - 如何验证 +6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR 及修复思路 + +如果问题过于复杂或信息不足,在 Issue 下用中文说明原因,不创建 PR。 + +--- + +## 新功能开发流程 + +1. 阅读 Issue 的完整标题和正文,理解需求目标 +2. 浏览仓库相关代码结构和文档,找到最相关的模块和文件 +3. 制定实现方案: + - 需要新增哪些文件或函数 + - 需要修改哪些现有文件 +4. 按方案实现代码,注意: + - 保持与现有代码风格一致 + - 新增函数/类需要添加注释 + - 如果涉及接口变更,同步更新相关调用方 +5. 创建 Pull Request,标题格式:`feat: `,描述中说明: + - 实现了哪些功能 + - 涉及哪些文件改动 + - 如何验证/测试 +6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR、实现思路和测试建议 + +如果需求描述不清晰或实现风险过大,在 Issue 下用中文说明原因,不创建 PR。 + +--- + +## 功能改进开发流程 + +1. 阅读 Issue 的完整标题和正文,明确功能改进与优化的具体目标(如性能提升、代码结构重构、用户体验优化等)。 +2. 浏览仓库相关代码,评估受影响的范围,定位需要进行优化或重构的核心文件及函数。 +3. 制定改进方案,需特别注意: + - **向下兼容性**:确保本次改进不会破坏现有的公开接口(API)和已有功能。 + - **防御性编程**:优化逻辑的同时,不能降低代码的健壮性。 +4. 按照方案实施代码改动,注意: + - 保持与现有代码风格高度一致。 + - 仅针对性能、可读性或结构进行局部优化,严禁引入未经需求的无关大范围改动。 +5. 创建 Pull Request,根据改进的核心侧重点选择标题格式: + - 侧重于代码重构/可读性优化:`refactor: ` + - 侧重于运行运行效率/性能优化:`perf: ` + 在 PR 描述中说明: + - 优化的动机与改进点 + - 改进前后的对比或预期收益 + - 验证优化是否生效的测试方法 +6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR、优化思路及预期的提升效果。 + +如果功能改进可能带来重大的破坏性变更(Breaking Changes)或者现有代码结构不支持盲目优化,在 Issue 下用中文说明原因,保持维持原状,不创建 PR。 \ No newline at end of file diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml new file mode 100644 index 00000000..98ab97f9 --- /dev/null +++ b/.github/workflows/codeql-to-commit.yml @@ -0,0 +1,194 @@ +name: Auto Copilot Autofix (High & Medium Only) + +on: + workflow_dispatch: + workflow_run: + workflows: ["CodeQL Advanced"] + types: [completed] + +jobs: + auto-fix: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' }} + permissions: + security-events: read + contents: write + pull-requests: write + + steps: + - name: Trigger Autofix for High & Medium alerts + env: + GH_TOKEN: ${{ secrets.AUTOFIX_TOKEN }} + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + run: | + set +e + DEFAULT_BRANCH=$(gh api /repos/$OWNER/$REPO --jq '.default_branch') + echo "Default branch: $DEFAULT_BRANCH" + + ALERTS=$(gh api "/repos/$OWNER/$REPO/code-scanning/alerts?state=open&per_page=100" \ + --jq '[.[] | select(.rule.security_severity_level == "critical" or .rule.security_severity_level == "high" or .rule.security_severity_level == "medium" or .rule.severity == "warning") | {number: .number, level: (.rule.security_severity_level // .rule.severity)}]') + + COUNT=$(echo $ALERTS | jq 'length') + echo "Found $COUNT alerts with high / medium / warning" + echo "$ALERTS" | jq -r '.[] | " Alert #\(.number) [\(.level)]"' + + if [ "$COUNT" -eq 0 ]; then + echo "No alerts to process, exiting." + exit 0 + fi + + for ROW in $(echo $ALERTS | jq -r '.[] | @base64'); do + _jq() { echo "$ROW" | base64 -d | jq -r "$1"; } + + NUMBER=$(_jq '.number') + SEC_LEVEL=$(_jq '.level') + BRANCH="autofix/${SEC_LEVEL}/alert-${NUMBER}" + + echo "--- Alert #$NUMBER [$SEC_LEVEL] ---" + + # 检查是否已有 autofix + EXISTING=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.status' 2>/dev/null || echo "none") + + if [ "$EXISTING" = "success" ]; then + echo "✅ Fix already exists" + else + echo "⏳ Generating fix..." + gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix || { + echo "⚠️ Failed to trigger autofix for #$NUMBER, skipping" + continue + } + + for i in 1 2 3; do + sleep 30 + EXISTING=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.status' 2>/dev/null || echo "none") + echo " Attempt $i: status = $EXISTING" + [ "$EXISTING" = "success" ] && break + done + fi + + if [ "$EXISTING" != "success" ]; then + echo "⚠️ Autofix not available for alert #$NUMBER (status: $EXISTING), skipping" + continue + fi + + # 检查分支是否已存在 + BRANCH_STATUS=$(gh api \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH \ + --silent 2>/dev/null && echo "exists" || echo "not_found") + echo "DEBUG branch status: $BRANCH_STATUS" + + if [ "$BRANCH_STATUS" = "not_found" ]; then + # 创建分支 + SHA=$(gh api /repos/$OWNER/$REPO/git/refs/heads/$DEFAULT_BRANCH \ + --jq '.object.sha') + + gh api -X POST /repos/$OWNER/$REPO/git/refs \ + -f ref="refs/heads/$BRANCH" \ + -f sha="$SHA" 2>/dev/null || true + echo "🌿 Created branch: $BRANCH" + + # 提交 fix + COMMIT_RESULT=$(gh api -X POST \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix/commits \ + -f target_ref="$BRANCH" 2>&1) + echo "DEBUG commit result: $COMMIT_RESULT" + + if echo "$COMMIT_RESULT" | grep -q "target_ref"; then + echo "✅ Committed fix to branch: $BRANCH" + else + echo "⚠️ No code changes generated, deleting branch and skipping" + gh api -X DELETE \ + /repos/$OWNER/$REPO/git/refs/heads/$BRANCH 2>/dev/null || true + continue + fi + else + # 分支已存在,检查是否已有 open PR + EXISTING_PR=$(gh pr list \ + --repo "$OWNER/$REPO" \ + --head "$BRANCH" \ + --state open \ + --json number \ + --jq '.[0].number // empty') + + if [ -n "$EXISTING_PR" ]; then + echo "⏭️ PR #$EXISTING_PR already exists, skipping" + continue + fi + + echo "🌿 Branch exists, creating PR with existing branch" + fi + + # 获取 alert 详情 + ALERT_INFO=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER) + + ALERT_TITLE=$(echo $ALERT_INFO | jq -r '.rule.description') + ALERT_HELP=$(echo $ALERT_INFO | jq -r '.rule.help // "暂无详细说明"' | head -c 800) + ALERT_TAGS=$(echo $ALERT_INFO | jq -r '.rule.tags // [] | join(", ")') + ALERT_FILE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.path // "未知文件"') + ALERT_LINE=$(echo $ALERT_INFO | jq -r '.most_recent_instance.location.start_line // "未知行"') + ALERT_URL=$(echo $ALERT_INFO | jq -r '.html_url') + CWE_TAGS=$(echo $ALERT_INFO | jq -r '[.rule.tags[] | select(startswith("external/cwe/"))] | join(", ")') + + AUTOFIX_DESC=$(gh api \ + /repos/$OWNER/$REPO/code-scanning/alerts/$NUMBER/autofix \ + --jq '.description // "暂无 AI 修复说明"') + + # 创建 Draft PR + gh pr create \ + --repo "$OWNER/$REPO" \ + --base "$DEFAULT_BRANCH" \ + --head "$BRANCH" \ + --draft \ + --title "[Autofix][$SEC_LEVEL] Alert #$NUMBER: $ALERT_TITLE" \ + --body "## 🤖 Copilot Autofix 自动修复报告 + + --- + + ### 📋 基本信息 + + | 字段 | 内容 | + |------|------| + | **Alert ID** | [#$NUMBER]($ALERT_URL) | + | **安全级别** | $SEC_LEVEL | + | **规则名称** | $ALERT_TITLE | + | **问题文件** | \`$ALERT_FILE\` 第 $ALERT_LINE 行 | + | **CWE 分类** | $CWE_TAGS | + | **规则标签** | $ALERT_TAGS | + + --- + + ### 🔍 问题说明 + + $ALERT_HELP + + --- + + ### 🤖 AI 修复思路 + + $AUTOFIX_DESC + + --- + + ### ✅ Review 检查清单 + + - [ ] 理解了漏洞的成因和影响范围 + - [ ] 确认 AI 修复逻辑正确,没有遗漏边界情况 + - [ ] 确认修复没有改变原有业务逻辑 + - [ ] 确认没有引入新的安全问题 + - [ ] CI / 单元测试全部通过 + - [ ] 如有必要,已补充对应的测试用例 + + --- + + > 此 PR 由 GitHub Copilot Autofix 自动生成,请仔细审核后再 merge。" && \ + echo "🎉 PR created for alert #$NUMBER" || \ + echo "❌ Failed to create PR for alert #$NUMBER" + + done diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 603dd33a..598759b4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -11,7 +11,7 @@ on: jobs: analyze: - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest permissions: security-events: write packages: read @@ -23,6 +23,7 @@ jobs: matrix: include: - language: c-cpp + build-mode: manual steps: - name: Checkout repository uses: actions/checkout@v6 @@ -42,22 +43,29 @@ jobs: - name: Set TERM variable run: echo "TERM=xterm" >> $GITHUB_ENV - + - name: Set up Dependency Environment run: | cd libxengine chmod +x ./XEngine_LINEnv.sh sudo ./XEngine_LINEnv.sh -i 3 + - name: make pre + run: | + cd XEngine_Source + make BUILDTYPE=1 + - name: Initialize CodeQL uses: github/codeql-action/init@v4 with: languages: ${{ matrix.language }} + build-mode: manual + queries: security-and-quality - - name: make + - name: make check run: | cd XEngine_Source - make + make BUILDTYPE=2 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/cppcheck.yml b/.github/workflows/cppcheck.yml deleted file mode 100644 index 0a6eb20c..00000000 --- a/.github/workflows/cppcheck.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: cpp check workflows - -on: - push: - branches: - - 'develop' - paths: - - 'XEngine_Source/**' - - 'XEngine_Release/**' - - '.github/**' - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout main repository code - uses: actions/checkout@v6 - with: - ref: 'develop' - - - name: Create static_analysis directory - run: mkdir -p static_analysis - - - name: Run Cppcheck - run: | - sudo apt-get install -y cppcheck - cppcheck --enable=all --language=c++ --std=c++20 ./XEngine_Source/ --output-file=static_analysis/log.xml --xml - continue-on-error: true - - - name: Upload Cppcheck Results - uses: actions/upload-artifact@v6 - with: - name: cppcheck_results - path: static_analysis/log.xml \ No newline at end of file diff --git a/.github/workflows/debian_build.yml b/.github/workflows/debian_build.yml index b7bd871f..3b39b1b6 100644 --- a/.github/workflows/debian_build.yml +++ b/.github/workflows/debian_build.yml @@ -81,7 +81,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Debian_${{ matrix.version }}_x86-64 path: XEngine_Release/ diff --git a/.github/workflows/fedora_build.yml b/.github/workflows/fedora_build.yml index 22966aa2..494e8476 100644 --- a/.github/workflows/fedora_build.yml +++ b/.github/workflows/fedora_build.yml @@ -21,6 +21,11 @@ jobs: strategy: matrix: include: + - arch: amd64 + runner: ubuntu-24.04 + platform: linux/amd64 + fedora-version: 43 + artifact: x86-64 - arch: amd64 runner: ubuntu-24.04 platform: linux/amd64 @@ -82,7 +87,7 @@ jobs: ./XEngine_AuthorizeService -t - name: Upload folder as artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Fedora_${{ matrix.fedora-version }}_${{ matrix.artifact }} path: XEngine_Release/ diff --git a/.github/workflows/issue-translator.yml b/.github/workflows/issue-translator.yml deleted file mode 100644 index d9fdac8f..00000000 --- a/.github/workflows/issue-translator.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Issue Translator -on: - issue_comment: - types: [created] - issues: - types: [opened] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: usthe/issues-translate-action@v2.7 - with: - IS_MODIFY_TITLE: false - CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. \ No newline at end of file diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml new file mode 100644 index 00000000..c4c7adb3 --- /dev/null +++ b/.github/workflows/issue-triage.lock.yml @@ -0,0 +1,1223 @@ +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"01651461ea771a40a1d9a25bbf950f25e913d6b556796467343b77b45eabdd15","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}} +# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]} +# ___ _ _ +# / _ \ | | (_) +# | |_| | __ _ ___ _ __ | |_ _ ___ +# | _ |/ _` |/ _ \ '_ \| __| |/ __| +# | | | | (_| | __/ | | | |_| | (__ +# \_| |_/\__, |\___|_| |_|\__|_|\___| +# __/ | +# _ _ |___/ +# | | | | / _| | +# | | | | ___ _ __ _ __| |_| | _____ ____ +# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___| +# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \ +# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/ +# +# This file was automatically generated by gh-aw (v0.79.6). DO NOT EDIT. +# +# To update this file, edit the corresponding .md file and run: +# gh aw compile +# Not all edits will cause changes to this file. +# +# For more information: https://github.github.com/gh-aw/introduction/overview/ +# +# +# Secrets used: +# - GH_AW_GITHUB_MCP_SERVER_TOKEN +# - GH_AW_GITHUB_TOKEN +# - GITHUB_TOKEN +# - OPENAI_API_KEY +# +# Custom actions used: +# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 +# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 +# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 +# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 +# - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 +# +# Container images used: +# - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + +name: "Issue 自动分类与回复" +on: + issues: + types: + - opened + - reopened + +permissions: {} + +concurrency: + group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number || github.run_id }}" + +run-name: "Issue 自动分类与回复" + +jobs: + activation: + needs: pre_activation + if: needs.pre_activation.outputs.activated == 'true' + runs-on: ubuntu-slim + permissions: + actions: read + contents: read + env: + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + outputs: + body: ${{ steps.sanitized.outputs.body }} + comment_id: "" + comment_repo: "" + daily_effective_workflow_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_exceeded == 'true' }} + daily_effective_workflow_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_threshold || '' }} + daily_effective_workflow_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_total_effective_tokens || '' }} + engine_id: ${{ steps.generate_aw_info.outputs.engine_id }} + lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }} + model: ${{ steps.generate_aw_info.outputs.model }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }} + text: ${{ steps.sanitized.outputs.text }} + title: ${{ steps.sanitized.outputs.title }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }} + safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Generate agentic run info + id: generate_aw_info + env: + GH_AW_INFO_ENGINE_ID: "copilot" + GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI" + GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_AGENT_VERSION: "1.0.60" + GH_AW_INFO_CLI_VERSION: "v0.79.6" + GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_INFO_EXPERIMENTAL: "false" + GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true" + GH_AW_INFO_STAGED: "false" + GH_AW_INFO_ALLOWED_DOMAINS: '["defaults","ark.cn-beijing.volces.com"]' + GH_AW_INFO_FIREWALL_ENABLED: "false" + GH_AW_INFO_AWF_VERSION: "" + GH_AW_INFO_AWMG_VERSION: "" + GH_AW_INFO_FIREWALL_TYPE: "" + GH_AW_COMPILED_STRICT: "false" + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs'); + await main(core, context); + - name: Check daily workflow token guardrail + id: daily-effective-workflow-guardrail + if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_ID: "issue-triage" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }} + GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs'); + await main(); + - name: Checkout .github and .agents folders + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + sparse-checkout: | + .github + .agents + .antigravity + .claude + .codex + .crush + .gemini + .opencode + .pi + sparse-checkout-cone-mode: true + fetch-depth: 1 + - name: Save agent config folders for base branch restoration + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh" + - name: Check workflow lock file + id: check-lock-file + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_WORKFLOW_FILE: "issue-triage.lock.yml" + GH_AW_CONTEXT_WORKFLOW_REF: "${{ github.workflow_ref }}" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs'); + await main(); + - name: Check compile-agentic version + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_COMPILED_VERSION: "v0.79.6" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_version_updates.cjs'); + await main(); + - name: Compute current body text + id: sanitized + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/compute_text.cjs'); + await main(); + - name: Create prompt with built-in context + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + # poutine:ignore untrusted_checkout_exec + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" + { + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' + + GH_AW_PROMPT_72243dd344875363_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" + cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' + + Tools: add_comment, add_labels, missing_tool, missing_data, noop + + GH_AW_PROMPT_72243dd344875363_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' + + The following GitHub context information is available for this workflow: + {{#if github.actor}} + - **actor**: __GH_AW_GITHUB_ACTOR__ + {{/if}} + {{#if github.repository}} + - **repository**: __GH_AW_GITHUB_REPOSITORY__ + {{/if}} + {{#if github.workspace}} + - **workspace**: __GH_AW_GITHUB_WORKSPACE__ + {{/if}} + {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}} + - **issue-number**: #__GH_AW_EXPR_802A9F6A__ + {{/if}} + {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}} + - **discussion-number**: #__GH_AW_EXPR_1A3A194A__ + {{/if}} + {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}} + - **pull-request-number**: #__GH_AW_EXPR_463A214A__ + {{/if}} + {{#if github.event.comment.id || github.aw.context.comment_id}} + - **comment-id**: __GH_AW_EXPR_FF1D34CE__ + {{/if}} + {{#if github.run_id}} + - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__ + {{/if}} + + + GH_AW_PROMPT_72243dd344875363_EOF + cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" + cat << 'GH_AW_PROMPT_72243dd344875363_EOF' + + {{#runtime-import .github/workflows/issue-triage.md}} + GH_AW_PROMPT_72243dd344875363_EOF + } > "$GH_AW_PROMPT" + - name: Interpolate variables and render templates + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_ENGINE_ID: "copilot" + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs'); + await main(); + - name: Substitute placeholders + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }} + GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }} + GH_AW_GITHUB_ACTOR: ${{ github.actor }} + GH_AW_GITHUB_REPOSITORY: ${{ github.repository }} + GH_AW_GITHUB_RUN_ID: ${{ github.run_id }} + GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }} + GH_AW_MCP_CLI_SERVERS_LIST: '- `safeoutputs` — run `safeoutputs --help` to see available tools' + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: ${{ needs.pre_activation.outputs.activated }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + + const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs'); + + // Call the substitution function + return await substitutePlaceholders({ + file: process.env.GH_AW_PROMPT, + substitutions: { + GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A, + GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A, + GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A, + GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE, + GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR, + GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY, + GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID, + GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE, + GH_AW_MCP_CLI_SERVERS_LIST: process.env.GH_AW_MCP_CLI_SERVERS_LIST, + GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED: process.env.GH_AW_NEEDS_PRE_ACTIVATION_OUTPUTS_ACTIVATED + } + }); + - name: Validate prompt placeholders + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh" + - name: Print prompt + env: + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + # poutine:ignore untrusted_checkout_exec + run: bash "${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh" + - name: Upload activation artifact + if: success() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: activation + include-hidden-files: true + path: | + /tmp/gh-aw/aw_info.json + /tmp/gh-aw/model_multipliers.json + /tmp/gh-aw/models.json + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/aw-prompts/prompt-template.txt + /tmp/gh-aw/aw-prompts/prompt-import-tree.json + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/base + /tmp/gh-aw/.github/agents + /tmp/gh-aw/.github/skills + if-no-files-found: ignore + retention-days: 1 + + agent: + needs: activation + if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true' + runs-on: ubuntu-latest + permissions: + contents: read + copilot-requests: write + issues: read + pull-requests: read + env: + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + GH_AW_ASSETS_ALLOWED_EXTS: "" + GH_AW_ASSETS_BRANCH: "" + GH_AW_ASSETS_MAX_SIZE_KB: 0 + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + GH_AW_WORKFLOW_ID_SANITIZED: issuetriage + outputs: + agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }} + ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }} + aic: ${{ steps.parse-mcp-gateway.outputs.aic }} + ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }} + checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }} + effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }} + has_patch: ${{ steps.collect_output.outputs.has_patch }} + inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }} + mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }} + model: ${{ needs.activation.outputs.model }} + model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }} + output: ${{ steps.collect_output.outputs.output }} + output_types: ${{ steps.collect_output.outputs.output_types }} + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Set runtime paths + id: set-runtime-paths + run: | + { + echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" + echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" + echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" + } >> "$GITHUB_OUTPUT" + - name: Checkout repository + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + - name: Create gh-aw temp directory + run: bash "${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh" + - name: Configure gh CLI for GitHub Enterprise + run: bash "${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh" + env: + GH_TOKEN: ${{ github.token }} + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Checkout PR branch + id: checkout-pr + if: | + github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + with: + github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs'); + await main(); + - name: Install GitHub Copilot CLI + run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60 + env: + GH_HOST: github.com + - name: Parse integrity filter lists + id: parse-guard-vars + env: + GH_AW_BLOCKED_USERS_VAR: ${{ vars.GH_AW_GITHUB_BLOCKED_USERS || '' }} + GH_AW_TRUSTED_USERS_VAR: ${{ vars.GH_AW_GITHUB_TRUSTED_USERS || '' }} + GH_AW_APPROVAL_LABELS_VAR: ${{ vars.GH_AW_GITHUB_APPROVAL_LABELS || '' }} + run: bash "${RUNNER_TEMP}/gh-aw/actions/parse_guard_list.sh" + - name: Download activation artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: activation + path: /tmp/gh-aw + - name: Restore agent config folders from base branch + if: steps.checkout-pr.outcome == 'success' + env: + GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi" + GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh" + - name: Restore inline sub-agents from activation artifact + env: + GH_AW_SUB_AGENT_DIR: ".github/agents" + GH_AW_SUB_AGENT_EXT: ".agent.md" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh" + - name: Restore inline skills from activation artifact + env: + GH_AW_SKILL_DIR: ".github/skills" + run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh" + - name: Download container images + run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c + - name: Generate Safe Outputs Config + run: | + mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" + mkdir -p /tmp/gh-aw/safeoutputs + mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_33a8e71ee9b45c67_EOF' + {"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}} + GH_AW_SAFE_OUTPUTS_CONFIG_33a8e71ee9b45c67_EOF + - name: Generate Safe Outputs Tools + env: + GH_AW_TOOLS_META_JSON: | + { + "description_suffixes": { + "add_comment": " CONSTRAINTS: Maximum 1 comment(s) can be added. Supports reply_to_id for discussion threading.", + "add_labels": " CONSTRAINTS: Only these labels are allowed: [\"bug\" \"feature\" \"enhancement\" \"documentation\" \"question\" \"duplicate\" \"invalid\"]." + }, + "repo_params": {}, + "dynamic_tools": [] + } + GH_AW_VALIDATION_JSON: | + { + "add_comment": { + "defaultMax": 1, + "fields": { + "body": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "item_number": { + "issueOrPRNumber": true + }, + "reply_to_id": { + "type": "string", + "maxLength": 256 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "add_labels": { + "defaultMax": 5, + "fields": { + "item_number": { + "issueNumberOrTemporaryId": true + }, + "labels": { + "required": true, + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 128 + }, + "repo": { + "type": "string", + "maxLength": 256 + } + } + }, + "missing_data": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "context": { + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "data_type": { + "type": "string", + "sanitize": true, + "maxLength": 128 + }, + "reason": { + "type": "string", + "sanitize": true, + "maxLength": 256 + } + } + }, + "missing_tool": { + "defaultMax": 20, + "fields": { + "alternatives": { + "type": "string", + "sanitize": true, + "maxLength": 512 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 256 + }, + "tool": { + "type": "string", + "sanitize": true, + "maxLength": 128 + } + } + }, + "noop": { + "defaultMax": 1, + "fields": { + "message": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 65000 + } + } + }, + "report_incomplete": { + "defaultMax": 5, + "fields": { + "details": { + "type": "string", + "sanitize": true, + "maxLength": 65000 + }, + "reason": { + "required": true, + "type": "string", + "sanitize": true, + "maxLength": 1024 + } + } + } + } + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_safe_outputs_tools.cjs'); + await main(); + - name: Generate Safe Outputs MCP Server Config + id: safe-outputs-config + run: | + # Generate a secure random API key (360 bits of entropy, 40+ chars) + # Mask immediately to prevent timing vulnerabilities + API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${API_KEY}" + + PORT=3001 + + # Set outputs for next steps + { + echo "safe_outputs_api_key=${API_KEY}" + echo "safe_outputs_port=${PORT}" + } >> "$GITHUB_OUTPUT" + + echo "Safe Outputs MCP server will run on port ${PORT}" + + - name: Start Safe Outputs MCP HTTP Server + id: safe-outputs-start + env: + DEBUG: '*' + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }} + GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json + GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json + GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs + run: | + # Environment variables are set above to prevent template injection + export DEBUG + export GH_AW_SAFE_OUTPUTS + export GH_AW_SAFE_OUTPUTS_PORT + export GH_AW_SAFE_OUTPUTS_API_KEY + export GH_AW_SAFE_OUTPUTS_TOOLS_PATH + export GH_AW_SAFE_OUTPUTS_CONFIG_PATH + export GH_AW_MCP_LOG_DIR + + bash "${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh" + + - name: Start MCP Gateway + id: start-mcp-gateway + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }} + GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + run: | + set -eo pipefail + mkdir -p "${RUNNER_TEMP}/gh-aw/mcp-config" + + # Export gateway environment variables for MCP config and gateway script + export MCP_GATEWAY_PORT="8080" + export MCP_GATEWAY_DOMAIN="localhost" + export MCP_GATEWAY_HOST_DOMAIN="localhost" + MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=') + echo "::add-mask::${MCP_GATEWAY_API_KEY}" + export MCP_GATEWAY_API_KEY + export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads" + mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}" + export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288" + export DEBUG="*" + + export GH_AW_ENGINE="copilot" + MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0') + MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0') + case "${DOCKER_HOST:-}" in + unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;; + /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;; + * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;; + esac + DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0') + export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25' + + mkdir -p /home/runner/.copilot + GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) + cat << GH_AW_MCP_CONFIG_f41962abaffbda74_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + { + "mcpServers": { + "github": { + "type": "stdio", + "container": "ghcr.io/github/github-mcp-server:v1.1.2", + "env": { + "GITHUB_HOST": "\${GITHUB_SERVER_URL}", + "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", + "GITHUB_TOOLSETS": "context,repos,issues,pull_requests" + }, + "guard-policies": { + "allow-only": { + "approval-labels": ${{ steps.parse-guard-vars.outputs.approval_labels }}, + "blocked-users": ${{ steps.parse-guard-vars.outputs.blocked_users }}, + "min-integrity": "none", + "repos": "all", + "trusted-users": ${{ steps.parse-guard-vars.outputs.trusted_users }} + } + } + }, + "safeoutputs": { + "type": "http", + "url": "http://localhost:$GH_AW_SAFE_OUTPUTS_PORT", + "headers": { + "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}" + }, + "guard-policies": { + "write-sink": { + "accept": [ + "*" + ] + } + } + } + }, + "gateway": { + "port": $MCP_GATEWAY_PORT, + "domain": "${MCP_GATEWAY_DOMAIN}", + "apiKey": "${MCP_GATEWAY_API_KEY}", + "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" + } + } + GH_AW_MCP_CONFIG_f41962abaffbda74_EOF + - name: Mount MCP servers as CLIs + id: mount-mcp-clis + continue-on-error: true + env: + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + MCP_GATEWAY_DOMAIN: ${{ steps.start-mcp-gateway.outputs.gateway-domain }} + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io); + const { main } = require('${{ runner.temp }}/gh-aw/actions/mount_mcp_as_cli.cjs'); + await main(); + - name: Clean credentials + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh" + - name: Audit pre-agent workspace + id: pre_agent_audit + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/audit_pre_agent_workspace.sh" + - name: Execute GitHub Copilot CLI + id: agentic_execution + # Copilot CLI tool arguments (sorted): + # --allow-tool github + # --allow-tool safeoutputs + timeout-minutes: 20 + run: | + set -o pipefail + printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt + touch /tmp/gh-aw/agent-step-summary.md + (umask 177 && touch /tmp/gh-aw/agent-stdio.log) + trap 'rm -f /home/runner/.copilot/settings.json' EXIT + mkdir -p /home/runner/.copilot + printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json + mkdir -p /tmp/ + mkdir -p /tmp/gh-aw/ + mkdir -p /tmp/gh-aw/agent/ + mkdir -p /tmp/gh-aw/sandbox/agent/logs/ + GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log + env: + COPILOT_AGENT_RUNNER_TYPE: STANDALONE + COPILOT_MODEL: doubao-seed-evolving + COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3 + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses + GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }} + GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json + GH_AW_PHASE: agent + GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_TIMEOUT_MINUTES: 20 + GH_AW_VERSION: v0.79.6 + GITHUB_API_URL: ${{ github.api_url }} + GITHUB_AW: true + GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows + GITHUB_HEAD_REF: ${{ github.head_ref }} + GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md + GITHUB_WORKSPACE: ${{ github.workspace }} + RUNNER_TEMP: ${{ runner.temp }} + S2STOKENS: true + XDG_CONFIG_HOME: /home/runner + - name: Detect agent errors + if: always() + id: detect-agent-errors + continue-on-error: true + run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs" + - name: Configure Git credentials + env: + REPO_NAME: ${{ github.repository }} + SERVER_URL: ${{ github.server_url }} + GITHUB_TOKEN: ${{ github.token }} + run: | + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git config --global am.keepcr true + # Re-authenticate git with GitHub token + SERVER_URL_STRIPPED="${SERVER_URL#https://}" + git remote set-url origin "https://x-access-token:${GITHUB_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git" + echo "Git configured with standard GitHub Actions identity" + - name: Copy Copilot session state files to logs + if: always() + continue-on-error: true + run: bash "${RUNNER_TEMP}/gh-aw/actions/copy_copilot_session_state.sh" + - name: Stop MCP Gateway + if: always() + continue-on-error: true + env: + MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }} + MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }} + GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }} + run: | + bash "${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh" "$GATEWAY_PID" + - name: Redact secrets in logs + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs'); + await main(); + env: + GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY' + SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }} + SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }} + SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SECRET_OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + - name: Append agent step summary + if: always() + run: bash "${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh" + - name: Copy Safe Outputs + if: always() + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + run: | + mkdir -p /tmp/gh-aw + cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true + - name: Ingest agent output + id: collect_output + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs'); + await main(); + - name: Parse agent logs for step summary + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/ + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs'); + await main(); + - name: Parse MCP Gateway logs for step summary + if: always() + id: parse-mcp-gateway + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + with: + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs'); + await main(); + - name: Write agent output placeholder if missing + if: always() + run: | + if [ ! -f /tmp/gh-aw/agent_output.json ]; then + echo '{"items":[]}' > /tmp/gh-aw/agent_output.json + fi + - name: Upload agent artifacts + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: agent + path: | + /tmp/gh-aw/aw-prompts/prompt.txt + /tmp/gh-aw/sandbox/agent/logs/ + /tmp/gh-aw/redacted-urls.log + /tmp/gh-aw/mcp-logs/ + /tmp/gh-aw/proxy-logs/ + !/tmp/gh-aw/proxy-logs/proxy-tls/ + /tmp/gh-aw/agent-stdio.log + /tmp/gh-aw/pre-agent-audit.txt + /tmp/gh-aw/agent/ + /tmp/gh-aw/github_rate_limits.jsonl + /tmp/gh-aw/safeoutputs.jsonl + /tmp/gh-aw/agent_output.json + if-no-files-found: ignore + + conclusion: + needs: + - activation + - agent + - safe_outputs + if: > + always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' || + needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_effective_workflow_exceeded == 'true') + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + pull-requests: write + concurrency: + group: "gh-aw-conclusion-issue-triage" + cancel-in-progress: false + queue: max + outputs: + incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }} + noop_message: ${{ steps.noop.outputs.noop_message }} + tools_reported: ${{ steps.missing_tool.outputs.tools_reported }} + total_count: ${{ steps.missing_tool.outputs.total_count }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Collect usage artifact files + if: always() + continue-on-error: true + run: | + mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection + echo "Usage artifact source file status:" + for file in /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do + [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file" + done + [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true + [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true + [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true + [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl + [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl + find /tmp/gh-aw/usage -type f -print | sort + - name: Upload usage artifact + if: always() + continue-on-error: true + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usage + path: | + /tmp/gh-aw/usage/aw-info.jsonl + /tmp/gh-aw/usage/agent_usage.jsonl + /tmp/gh-aw/usage/detection_usage.jsonl + /tmp/gh-aw/usage/agent/token_usage.jsonl + /tmp/gh-aw/usage/detection/token_usage.jsonl + if-no-files-found: ignore + - name: Process no-op messages + id: noop + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_NOOP_MAX: "1" + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_NOOP_REPORT_AS_ISSUE: "true" + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_WORKFLOW_ID: "issue-triage" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs'); + await main(); + - name: Record missing tool + id: missing_tool + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_MISSING_TOOL_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs'); + await main(); + - name: Record incomplete + id: report_incomplete + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true" + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/report_incomplete_handler.cjs'); + await main(); + - name: Handle agent failure + id: handle_agent_failure + if: always() + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" + GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }} + GH_AW_WORKFLOW_ID: "issue-triage" + GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168" + GH_AW_ENGINE_ID: "copilot" + GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }} + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }} + GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }} + GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }} + GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }} + GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }} + GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }} + GH_AW_MODEL_NOT_SUPPORTED_ERROR: ${{ needs.agent.outputs.model_not_supported_error }} + GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com" + GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }} + GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_effective_workflow_total_effective_tokens }} + GH_AW_DAILY_EFFECTIVE_WORKFLOW_THRESHOLD: ${{ needs.activation.outputs.daily_effective_workflow_threshold }} + GH_AW_GROUP_REPORTS: "false" + GH_AW_FAILURE_REPORT_AS_ISSUE: "true" + GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true" + GH_AW_MISSING_DATA_REPORT_AS_FAILURE: "true" + GH_AW_TIMEOUT_MINUTES: "20" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs'); + await main(); + + pre_activation: + runs-on: ubuntu-slim + outputs: + activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }} + matched_command: '' + setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }} + setup-span-id: ${{ steps.setup.outputs.span-id }} + setup-trace-id: ${{ steps.setup.outputs.trace-id }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Check team membership for workflow + id: check_membership + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_REQUIRED_ROLES: "admin,maintainer,write" + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/check_membership.cjs'); + await main(); + + safe_outputs: + needs: + - activation + - agent + if: (!cancelled()) && needs.agent.result != 'skipped' + runs-on: ubuntu-slim + permissions: + contents: read + discussions: write + issues: write + pull-requests: write + timeout-minutes: 45 + env: + GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AIC: ${{ needs.agent.outputs.aic }} + GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }} + GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage" + GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }} + GH_AW_ENGINE_ID: "copilot" + GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }} + GH_AW_ENGINE_VERSION: "1.0.60" + GH_AW_WORKFLOW_ID: "issue-triage" + GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md" + outputs: + code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }} + code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }} + comment_id: ${{ steps.process_safe_outputs.outputs.comment_id }} + comment_url: ${{ steps.process_safe_outputs.outputs.comment_url }} + create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }} + create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }} + process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }} + process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }} + steps: + - name: Setup Scripts + id: setup + uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6 + with: + destination: ${{ runner.temp }}/gh-aw/actions + job-name: ${{ github.job }} + trace-id: ${{ needs.activation.outputs.setup-trace-id }} + parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }} + env: + GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复" + GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }} + GH_AW_INFO_VERSION: "1.0.60" + GH_AW_INFO_ENGINE_ID: "copilot" + - name: Download agent output artifact + id: download-agent-output + continue-on-error: true + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: agent + path: /tmp/gh-aw/ + - name: Setup agent output environment variable + id: setup-agent-output-env + if: steps.download-agent-output.outcome == 'success' + run: | + mkdir -p /tmp/gh-aw/ + find "/tmp/gh-aw/" -type f -print + echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT" + - name: Configure GH_HOST for enterprise compatibility + id: ghes-host-config + shell: bash + # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input. + run: | + # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct + # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op. + GH_HOST="${GITHUB_SERVER_URL#https://}" + GH_HOST="${GH_HOST#http://}" + echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV" + - name: Process Safe Outputs + id: process_safe_outputs + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }} + GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }} + GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" + GITHUB_SERVER_URL: ${{ github.server_url }} + GITHUB_API_URL: ${{ github.api_url }} + GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"add_comment\":{\"max\":1},\"add_labels\":{\"allowed\":[\"bug\",\"feature\",\"enhancement\",\"documentation\",\"question\",\"duplicate\",\"invalid\"]},\"create_report_incomplete_issue\":{},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"},\"report_incomplete\":{}}" + with: + github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} + script: | + const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs'); + setupGlobals(core, github, context, exec, io, getOctokit); + const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs'); + await main(); + - name: Upload Safe Outputs Items + if: always() + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: safe-outputs-items + path: | + /tmp/gh-aw/safe-output-items.jsonl + /tmp/gh-aw/temporary-id-map.json + if-no-files-found: ignore + diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md new file mode 100644 index 00000000..ae117408 --- /dev/null +++ b/.github/workflows/issue-triage.md @@ -0,0 +1,72 @@ +--- +on: + issues: + types: [opened, reopened] + +engine: + id: copilot + env: + COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3" + COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }} + COPILOT_MODEL: doubao-seed-evolving + COPILOT_PROVIDER_TYPE: openai + COPILOT_PROVIDER_WIRE_API: responses + +features: + dangerously-disable-sandbox-agent: "controlled environment for issue triage automation" +sandbox: + agent: false +strict: false + +network: + allowed: + - defaults + - ark.cn-beijing.volces.com + +tools: + github: + min-integrity: none + +permissions: + issues: read + contents: read + pull-requests: read + copilot-requests: write + +safe-outputs: + threat-detection: false + add-comment: + max: 1 + add-labels: + allowed: + - bug + - feature + - enhancement + - documentation + - question + - duplicate + - invalid +--- + +# Issue 自动分类与回复 + +分析仓库 ${{ github.repository }} 中新开的 Issue。 + +## 任务 + +1. 阅读 Issue 的标题和正文 +2. 判断类型,添加合适的标签: + - `bug`:程序出错、功能异常 + - `feature`:新功能请求 + - `enhancement`:改进现有功能 + - `documentation`:文档问题 + - `question`:使用疑问 + - `duplicate`:与已有 Issue 重复 + - `invalid`:信息不完整或无效 + +3. 使用用户提问的语言回复一条友好的评论,包含: + - 感谢用户提交 Issue + - 说明你打的标签和原因 + - 如果是 bug,请用户补充:复现步骤、环境信息、错误日志 + - 如果是 question,尝试根据仓库代码和文档给出初步解答 + - 预计处理时间(普通问题 3 个工作日内) \ No newline at end of file diff --git a/.github/workflows/macbuild.yml b/.github/workflows/macbuild.yml index 911b9418..f026f4b1 100644 --- a/.github/workflows/macbuild.yml +++ b/.github/workflows/macbuild.yml @@ -85,14 +85,14 @@ jobs: - name: Upload folder as artifact with mac x64 if: matrix.os == 'macos-15-intel' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Mac_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with mac arm if: matrix.os == 'macos-15' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Mac_Arm64 path: XEngine_Release/ diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml index 55ff8d28..ce077eca 100644 --- a/.github/workflows/msbuild.yml +++ b/.github/workflows/msbuild.yml @@ -16,7 +16,7 @@ jobs: matrix: configuration: [Debug ,Release] platform: [x86 ,x64 ,ARM64] - runs-on: windows-latest # 最新的 Windows 环境 + runs-on: windows-2025-vs2026 steps: # 检出您的主仓库代码 @@ -110,21 +110,21 @@ jobs: - name: Upload folder as artifact with x86 if: matrix.configuration == 'Release' && matrix.platform == 'x86' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Windows_x86-32 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with x64 if: matrix.configuration == 'Release' && matrix.platform == 'x64' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Windows_x86-64 path: XEngine_Release/ retention-days: 1 - name: Upload folder as artifact with Arm64 if: matrix.configuration == 'Release' && matrix.platform == 'Arm64' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: XEngine_AuthorizeService-Windows_Arm64 path: XEngine_Release/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 87617504..d06224fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,15 +79,6 @@ jobs: skip_unpack: true if_no_artifact_found: fail path: ./XRelease/ - - name: Download CentOS - uses: dawidd6/action-download-artifact@v16 - with: - workflow: Centos_build.yml - workflow_conclusion: success - check_artifacts: false - skip_unpack: true - if_no_artifact_found: fail - path: ./XRelease/ - name: Display structure of downloaded files run: ls -al ./XRelease/ diff --git a/CHANGELOG b/CHANGELOG index b9b36782..c2b92b7f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,29 @@ +XEngine_Authorize V3.23.0.1001 + +ci:add agentic workflows for issue triage and auto fix +ci:delete cppcheck.yml and issue-translator.yml +added:email notify after user pay +added:user online time of count +added:insert create user name for serial created +added:serial create user and user token and time count management app support +update:vs to 2026 +modify:pay user auto adjust level +modify:warning and scan code problem +modify:token of session module instead depend session module +delete:get notice of task code and modify notice permission + +ci:增加了新的issue问题分类和处理工作流 +ci:删除了多余的工作流 +增加:用户充值邮件通知 +增加:用户在线时间统计 +增加:序列号增加用户创建字段 +增加:用户列表用户时间字段和TOKEN字段 +更新:VS编译器支持2026 +修改:用户注册后自动调整等级 +修改:通过scan扫描的代码问题 +修改:使用依赖库的会话模块替代自身的TOKEN模块 +删除:多余的通知消息 +================================================================ XEngine_Authorize V3.22.0.1001 ci:更新库依赖环境 diff --git a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp index 8834b959..6f0b7651 100644 --- a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp +++ b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.cpp @@ -40,14 +40,14 @@ using namespace std; bool bRun = true; bool bLogin = true; bool bTimeOut = true; -bool bEncrypto = false; +bool bEncrypto = true; bool bHeart = true; XNETHANDLE xhToken = 0; int nDYCode = 0; XSOCKET m_Socket = 0; LPCXSTR lpszUser = _X("123123aa"); -LPCXSTR lpszPass = _X("123123"); +LPCXSTR lpszPass = _X("123123aa"); LPCXSTR lpszHWCode = _X("2FDWAD02JD2091"); LPCXSTR lpszSerial = _X("Y5V0Y-03O2L-E7G8Y-NX1DR-3EGVO-UDIRQ-GBBKO-FGX0C"); LPCXSTR lpszEmail = _X("486179@qq.com"); @@ -66,13 +66,11 @@ XHTHREAD AuthClient_Thread() memset(&st_ProtocolHdr, '\0', sizeof(XENGINE_PROTOCOLHDR)); if (XClient_TCPSelect_RecvPkt(m_Socket, &ptszMsgBuffer, &nMsgLen, &st_ProtocolHdr)) { - XCHAR tszMsgBuffer[4096]; - memset(tszMsgBuffer, '\0', sizeof(tszMsgBuffer)); - + XCHAR tszMsgBuffer[4096] = {}; if (nMsgLen > 0 && bEncrypto) { //只有有后续数据的情况才需要解密 - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszMsgBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszMsgBuffer, &nMsgLen, lpszPass, ENUM_XENGINE_CRYPTION_SYMMETRIC_AES128); } else { @@ -161,10 +159,10 @@ int AuthClient_Register() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_Register:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -197,10 +195,10 @@ int AuthClient_Pay() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_Pay:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -228,7 +226,7 @@ int AuthClient_DynamicCode() { XCHAR tszDEBuffer[2048] = {}; - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); if (!pSt_JsonReader->parse(tszDEBuffer, tszDEBuffer + nMsgLen, &st_JsonRoot, &st_JsonError)) { return 0; @@ -297,8 +295,7 @@ int AuthClient_Login() memset(tszCodecBuffer, '\0', sizeof(tszCodecBuffer)); st_ProtocolHdr.wCrypto = ENUM_XENGINE_PROTOCOLHDR_CRYPTO_TYPE_XCRYPT; - Cryption_XCrypto_Encoder((LPCXSTR)&st_AuthUser, (int*)&st_ProtocolHdr.unPacketSize, (XBYTE*)tszCodecBuffer, lpszPass); - + Cryption_Api_CryptEncodec((LPCXBTR)&st_AuthUser, (XBYTE*)tszCodecBuffer, (int*)&st_ProtocolHdr.unPacketSize, lpszPass); memcpy(tszMsgBuffer, &st_ProtocolHdr, sizeof(XENGINE_PROTOCOLHDR)); memcpy(tszMsgBuffer + sizeof(XENGINE_PROTOCOLHDR), tszCodecBuffer, st_ProtocolHdr.unPacketSize); @@ -341,7 +338,7 @@ int AuthClient_Notice() { XCHAR tszDEBuffer[2048] = {}; - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); if (!pSt_JsonReader->parse(tszDEBuffer, tszDEBuffer + nMsgLen, &st_JsonRoot, &st_JsonError)) { return 0; @@ -406,10 +403,10 @@ int AuthClient_GetPass() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_GetPass:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -453,10 +450,10 @@ int AuthClient_GetTime() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("GET"), tszURLStr, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_GetTime:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } @@ -502,10 +499,10 @@ int AuthClient_Delete() XCHAR tszDEBuffer[2048] = {}; nMsgLen = st_JsonRoot.toStyledString().length(); - Cryption_XCrypto_Encoder(st_JsonRoot.toStyledString().c_str(), &nMsgLen, (XBYTE*)tszENBuffer, lpszPass); + Cryption_Api_CryptEncodec((LPCXBTR)st_JsonRoot.toStyledString().c_str(), (XBYTE*)tszENBuffer, &nMsgLen, lpszPass); APIClient_Http_Request(_X("POST"), lpszUrl, tszENBuffer, NULL, &ptszMsgBuffer, &nMsgLen); - Cryption_XCrypto_Decoder(ptszMsgBuffer, &nMsgLen, tszDEBuffer, lpszPass); + Cryption_Api_CryptDecodec((LPCXBTR)ptszMsgBuffer, (XBYTE*)tszDEBuffer, &nMsgLen, lpszPass); printf("AuthClient_Delete:\n%s\n", tszDEBuffer); BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } diff --git a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj index a1404cd6..4f71e6bc 100644 --- a/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj +++ b/XEngine_Apps/Authorize_APPClient/Authorize_APPClient.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj b/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj index e9a4b822..df6bf489 100644 --- a/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj +++ b/XEngine_Apps/Authorize_APPLocal/Authorize_APPLocal.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/Authorize_APPWebClient.html b/XEngine_Apps/Authorize_APPWebClient.html new file mode 100644 index 00000000..2cba92da --- /dev/null +++ b/XEngine_Apps/Authorize_APPWebClient.html @@ -0,0 +1,614 @@ + + + + + +XEngine Authorize - Web 客户端示例 + + + +
+

🔐 XEngine Authorize Web 客户端示例

+ +
+

服务器配置

+
+ + + + + + +
+
+ + +
+ + +
+
+ + +
+
+
+ +
+

连接状态

+
+
+ + WebSocket: 未连接 +
+
+ + 登录状态: 未登录 +
+
+ Token: - +
+
+ 心跳间隔: 2s +
+
+ 在线时长: 0s +
+
+
+ + +
+
+ +
+
+
登录认证
+
用户注册
+
HTTP API
+
用户信息
+
+ +
+
+ + + + +
+
+ + + + + + +
+
+ + + +
+
+ +
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ +
+
+ +
+
+ + + +
+
+ + + +
+
+ +
+
+
用户名
-
+
Token
-
+
设备类型
-
+
登录时间
-
+
在线时长
-
+
连接地址
-
+
+
+
+ +
+

运行日志

+
+
+ +
+
+
+ + + + diff --git a/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj b/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj index fd661dbc..a26a0645 100644 --- a/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj +++ b/XEngine_Apps/Authorize_CDKeyNetVer/Authorize_CDKeyNetVer.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp index 6131e491..b703f600 100644 --- a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp +++ b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.cpp @@ -14,6 +14,7 @@ #include using namespace std; #include +#include #include "../../XEngine_Source/XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Define.h" #include "../../XEngine_Source/XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Error.h" diff --git a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj index 2ce2a8f9..f1638110 100644 --- a/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj +++ b/XEngine_Apps/Authorize_ClientModule/Authorize_ClientModule.vcxproj @@ -29,26 +29,26 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Apps/README.md b/XEngine_Apps/README.md index 11e0c290..e0f5e41c 100644 --- a/XEngine_Apps/README.md +++ b/XEngine_Apps/README.md @@ -1 +1,15 @@ -appclient just only x86 and x64 debug compile on windows \ No newline at end of file +appclient just only x86 and x64 debug compile on windows + +## Authorize_APPWebClient +Web client example (`Authorize_APPWebClient.html`): A browser-based client that demonstrates WebSocket authentication with the XEngine Authorize server. Features include: +- WebSocket long connection to port 5301 with configurable server address +- User login with optional MD5 password encryption +- Heartbeat keep-alive (every 2 seconds) +- Session expiration/timeout notification (AUTH_EXPIRED) with automatic disconnection +- HTTP API support (register, recharge, query time, get announcements, token renewal) +- Dynamic verification code flow +- Auto-reconnect on unexpected disconnect +- Real-time log display + +Open the HTML file directly in any modern browser (Chrome/Firefox/Edge/Safari). No build required. +Default credentials: admin / 123123aa \ No newline at end of file diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx index dc9ebac0..9a988725 100644 Binary files a/XEngine_Docment/Docment_en.docx and b/XEngine_Docment/Docment_en.docx differ diff --git a/XEngine_Docment/Docment_zh.docx b/XEngine_Docment/Docment_zh.docx index b7884fdd..420c88cc 100644 Binary files a/XEngine_Docment/Docment_zh.docx and b/XEngine_Docment/Docment_zh.docx differ diff --git a/XEngine_Release/APPVer.key b/XEngine_Release/APPVer.key index 25fbd019..d9af837d 100644 Binary files a/XEngine_Release/APPVer.key and b/XEngine_Release/APPVer.key differ diff --git a/XEngine_Release/XEngine_Config/XEngine_Config.json b/XEngine_Release/XEngine_Config/XEngine_Config.json index 955e13e9..ceaff53d 100644 --- a/XEngine_Release/XEngine_Config/XEngine_Config.json +++ b/XEngine_Release/XEngine_Config/XEngine_Config.json @@ -82,6 +82,15 @@ "nLogType": 17, "bLogStorage": true }, + "XNotify": { + "XEmail": { + "bEnable": false, + "tszServiceAddr": "smtp://smtp.163.com", + "tszUser": "ggqytgodlove@163.com", + "tszPass": "1", + "tszSendAddr": "486179@qq.com" + } + }, "XReport": { "bEnable": true, "tszServiceName": "XEngine_Authorize", diff --git a/XEngine_SQL/mysql.sql b/XEngine_SQL/mysql.sql index 4944cb66..d0c64199 100644 --- a/XEngine_SQL/mysql.sql +++ b/XEngine_SQL/mysql.sql @@ -3,15 +3,15 @@ Source Server : QQCloud Source Server Type : MySQL - Source Server Version : 80043 (8.0.43-0ubuntu0.24.04.1) + Source Server Version : 80046 (8.0.46-0ubuntu0.24.04.2) Source Host : 118.25.14.242:3306 Source Schema : authorize Target Server Type : MySQL - Target Server Version : 80043 (8.0.43-0ubuntu0.24.04.1) + Target Server Version : 80046 (8.0.46-0ubuntu0.24.04.2) File Encoding : 65001 - Date: 20/08/2025 11:17:20 + Date: 30/06/2026 10:05:45 */ SET NAMES utf8mb4; @@ -86,13 +86,14 @@ CREATE TABLE `Authorize_Login` ( DROP TABLE IF EXISTS `Authorize_Serial`; CREATE TABLE `Authorize_Serial` ( `ID` int NOT NULL AUTO_INCREMENT, - `UserName` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, - `SerialNumber` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, - `MaxTime` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, - `CardSerialType` int NULL DEFAULT NULL, - `bIsUsed` tinyint(1) NULL DEFAULT NULL, - `CreateTime` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, - `ExpiredTime` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL, + `UserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '使用者', + `SerialNumber` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '序列号', + `MaxTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '最大时间', + `CardSerialType` int NOT NULL COMMENT '卡类型', + `bIsUsed` tinyint(1) NOT NULL COMMENT '是否使用', + `CreateTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, + `CreateUser` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '创建用户', + `ExpiredTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '过期时间', PRIMARY KEY (`ID`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; @@ -126,6 +127,7 @@ CREATE TABLE `Authorize_User` ( `ID` int NOT NULL AUTO_INCREMENT, `UserName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名', `Password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码', + `Token` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'Token', `LeftTime` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '剩余时间', `EmailAddr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '电子邮件', `HardCode` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '设备SN', @@ -133,14 +135,15 @@ CREATE TABLE `Authorize_User` ( `PhoneNumber` bigint NOT NULL COMMENT '电话号码', `IDCard` bigint NOT NULL COMMENT '身份证', `nUserLevel` int NOT NULL COMMENT '用户等级,数字越小越高', + `CountTime` bigint NOT NULL COMMENT '时间统计', `UPTime` datetime NULL DEFAULT NULL COMMENT '登录时间', `CreateTime` datetime NOT NULL COMMENT '注册时间', PRIMARY KEY (`ID`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; +) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of Authorize_User -- ---------------------------- -INSERT INTO `Authorize_User` VALUES (1, 'admin', '123123aa', '0', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); +INSERT INTO `Authorize_User` VALUES (1, 'admin', '123123aa', '0', '0', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); SET FOREIGN_KEY_CHECKS = 1; diff --git a/XEngine_SQL/sqlite.sql b/XEngine_SQL/sqlite.sql index 79cc011b..7d868a4f 100644 --- a/XEngine_SQL/sqlite.sql +++ b/XEngine_SQL/sqlite.sql @@ -10,7 +10,7 @@ Target Server Version : 3045000 (3.45.0) File Encoding : 65001 - Date: 22/12/2025 11:12:05 + Date: 30/06/2026 10:05:03 */ PRAGMA foreign_keys = false; @@ -83,12 +83,13 @@ DROP TABLE IF EXISTS "Authorize_Serial"; CREATE TABLE "Authorize_Serial" ( "ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "UserName" TEXT, - "SerialNumber" TEXT, - "MaxTime" TEXT, - "CardSerialType" integer, - "bIsUsed" boolean, + "SerialNumber" TEXT NOT NULL, + "MaxTime" TEXT NOT NULL, + "CardSerialType" integer NOT NULL, + "bIsUsed" boolean NOT NULL, "CreateTime" TEXT NOT NULL, - "ExpiredTime" DATE + "CreateUser" TEXT NOT NULL, + "ExpiredTime" text ); -- ---------------------------- @@ -120,6 +121,7 @@ CREATE TABLE "Authorize_User" ( "ID" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "UserName" TEXT NOT NULL, "Password" TEXT NOT NULL, + "Token" TEXT NOT NULL, "LeftTime" TEXT NOT NULL, "EmailAddr" TEXT NOT NULL, "HardCode" TEXT, @@ -127,6 +129,7 @@ CREATE TABLE "Authorize_User" ( "PhoneNumber" integer NOT NULL, "IDCard" integer NOT NULL, "nUserLevel" integer NOT NULL, + "CountTime" integer NOT NULL, "UPTime" DATE, "CreateTime" DATE NOT NULL ); @@ -134,7 +137,7 @@ CREATE TABLE "Authorize_User" ( -- ---------------------------- -- Records of Authorize_User -- ---------------------------- -INSERT INTO "Authorize_User" VALUES (1, 'admin', '123123aa', '5', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); +INSERT INTO "Authorize_User" VALUES (1, 'admin', '123123aa', '0', '5', '486179@qq.com', 'DAFD2A2DAD', 1, 13699430000, 511025198881118888, 0, 0, '2022-09-21 15:06:45', '2022-09-21 15:06:45'); -- ---------------------------- -- Table structure for sqlite_sequence @@ -148,31 +151,31 @@ CREATE TABLE "sqlite_sequence" ( -- ---------------------------- -- Records of sqlite_sequence -- ---------------------------- -INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedUser', 0); -INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedAddr', 0); -INSERT INTO "sqlite_sequence" VALUES ('Authorize_TempVer', 0); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedUser', 1); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_BannedAddr', 1); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_TempVer', 1); +INSERT INTO "sqlite_sequence" VALUES ('Authorize_Serial', 1); INSERT INTO "sqlite_sequence" VALUES ('Authorize_User', 1); -INSERT INTO "sqlite_sequence" VALUES ('Authorize_Serial', 0); -- ---------------------------- -- Auto increment value for Authorize_BannedAddr -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_BannedAddr'; +UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_BannedAddr'; -- ---------------------------- -- Auto increment value for Authorize_BannedUser -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_BannedUser'; +UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_BannedUser'; -- ---------------------------- -- Auto increment value for Authorize_Serial -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_Serial'; +UPDATE "sqlite_sequence" SET seq = 1 WHERE name = 'Authorize_Serial'; -- ---------------------------- -- Auto increment value for Authorize_TempVer -- ---------------------------- -UPDATE "sqlite_sequence" SET seq = 0 WHERE name = 'Authorize_TempVer'; +UPDATE "sqlite_sequence" SET seq = 41 WHERE name = 'Authorize_TempVer'; -- ---------------------------- -- Auto increment value for Authorize_User diff --git a/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj b/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj index 4fcbc8a7..59deec7a 100644 --- a/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj +++ b/XEngine_Source/AuthorizeModule_Configure/AuthorizeModule_Configure.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Configure/Config_Define.h b/XEngine_Source/AuthorizeModule_Configure/Config_Define.h index 08015036..59dbbb1e 100644 --- a/XEngine_Source/AuthorizeModule_Configure/Config_Define.h +++ b/XEngine_Source/AuthorizeModule_Configure/Config_Define.h @@ -122,6 +122,17 @@ typedef struct int nLogType; //日志类型 bool bLogStorage; //强日志 }st_XLog; + struct + { + struct + { + bool bEnable; + XCHAR tszServiceAddr[XPATH_MAX]; + XCHAR tszUser[128]; + XCHAR tszPass[128]; + XCHAR tszSendAddr[128]; + }st_EMailNotify; + }st_XNotify; struct { bool bEnable; diff --git a/XEngine_Source/AuthorizeModule_Configure/Config_Error.h b/XEngine_Source/AuthorizeModule_Configure/Config_Error.h index 25f1a8a3..15f7e27b 100644 --- a/XEngine_Source/AuthorizeModule_Configure/Config_Error.h +++ b/XEngine_Source/AuthorizeModule_Configure/Config_Error.h @@ -21,4 +21,5 @@ #define ERROR_AUTHORIZE_MODULE_CONFIGURE_MALLOC 0x0010009 #define ERROR_AUTHORIZE_MODULE_CONFIGURE_REPORT 0x0010010 #define ERROR_AUTHORIZE_MODULE_CONFIGURE_XTIME 0x0010011 -#define ERROR_AUTHORIZE_MODULE_CONFIGURE_XAPIVER 0x0010012 \ No newline at end of file +#define ERROR_AUTHORIZE_MODULE_CONFIGURE_XAPIVER 0x0010012 +#define ERROR_AUTHORIZE_MODULE_CONFIGURE_NOTIFY 0x0010013 \ No newline at end of file diff --git a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp index 904cea7d..3039b57f 100644 --- a/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp +++ b/XEngine_Source/AuthorizeModule_Configure/ModuleConfigure_Json/ModuleConfigure_Json.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include "ModuleConfigure_Json.h" +#include /******************************************************************** // Created: 2021/12/02 16:14:11 // File Name: D:\XEngine_ServiceApp\XEngine_Source\XEngine_ModuleConfigure\ModuleConfigure_Json\ModuleConfigure_Json.cpp @@ -204,6 +205,20 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_File(LPCXSTR lpszConfigFile, XE pSt_ServerConfig->st_XLog.bLogStorage = st_JsonXLog["bLogStorage"].asBool(); _tcsxcpy(pSt_ServerConfig->st_XLog.tszLogFile, st_JsonXLog["tszLogFile"].asCString()); _tcsxcpy(pSt_ServerConfig->st_XLog.tszKeyFile, st_JsonXLog["tszKeyFile"].asCString()); + //信息通知 + if (st_JsonRoot["XNotify"].empty()) + { + Config_IsErrorOccur = true; + Config_dwErrorCode = ERROR_AUTHORIZE_MODULE_CONFIGURE_NOTIFY; + return false; + } + Json::Value st_JsonXNotify = st_JsonRoot["XNotify"]; + Json::Value st_JsonXEmail = st_JsonXNotify["XEmail"]; + pSt_ServerConfig->st_XNotify.st_EMailNotify.bEnable = st_JsonXEmail["bEnable"].asBool(); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszServiceAddr, st_JsonXEmail["tszServiceAddr"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszUser, st_JsonXEmail["tszUser"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszPass, st_JsonXEmail["tszPass"].asCString()); + _tcsxcpy(pSt_ServerConfig->st_XNotify.st_EMailNotify.tszSendAddr, st_JsonXEmail["tszSendAddr"].asCString()); if (st_JsonRoot["XReport"].empty() || (3 != st_JsonRoot["XReport"].size())) { @@ -284,7 +299,7 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_Versions(LPCXSTR lpszConfigFile return false; } Json::Value st_JsonXVer = st_JsonRoot["XVer"]; - pSt_ServerConfig->st_XVer.pStl_ListVer = new list; + pSt_ServerConfig->st_XVer.pStl_ListVer = new (std::nothrow) list; if (NULL == pSt_ServerConfig->st_XVer.pStl_ListVer) { Config_IsErrorOccur = true; diff --git a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def index 07a2227f..e6c50ca0 100644 --- a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def +++ b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.def @@ -14,6 +14,7 @@ EXPORTS DBModule_SQLite_UserSet DBModule_SQLite_UserList DBModule_SQLite_UserLogin + DBModule_SQLite_UserTime DBModule_SQLite_QueryLogin DBModule_SQLite_SerialInsert @@ -49,6 +50,7 @@ EXPORTS DBModule_MySQL_UserSet DBModule_MySQL_UserList DBModule_MySQL_UserLogin + DBModule_MySQL_UserTime DBModule_MySQL_QueryLogin DBModule_MySQL_SerialInsert diff --git a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj index 9fc66506..05b07435 100644 --- a/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj +++ b/XEngine_Source/AuthorizeModule_Database/AuthorizeModule_Database.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp index 800e8477..27fe7003 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.cpp @@ -123,7 +123,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserRegister(AUTHREG_USERTABLE* pSt_UserInf SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); + _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_User`(UserName, Password, Token, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','0','%s','%s','%s','%d',%lld,%lld,%d,0,NOW())"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { SQLPacket_IsErrorOccur = true; @@ -202,14 +202,18 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE { _tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserName, pptszResult[nFliedValue]); } - //密码 nFliedValue++; if (NULL != pptszResult[nFliedValue]) { _tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserPass, pptszResult[nFliedValue]); } - + //TOKEN + nFliedValue++; + if (NULL != pptszResult[nFliedValue]) + { + pSt_UserInfo->st_UserInfo.xhToken = _ttxoll(pptszResult[nFliedValue]); + } //过期时间 nFliedValue++; if (NULL != pptszResult[nFliedValue]) @@ -258,7 +262,12 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE { pSt_UserInfo->st_UserInfo.nUserLevel = _ttxoi(pptszResult[nFliedValue]); } - + //总时间 + nFliedValue++; + if (NULL != pptszResult[nFliedValue]) + { + pSt_UserInfo->nTimeCount = _ttxoll(pptszResult[nFliedValue]); + } //登录日期 nFliedValue++; if (NULL != pptszResult[nFliedValue] && _tcsxlen(pptszResult[nFliedValue]) > 0) @@ -297,6 +306,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserQuery(LPCXSTR lpszUserName, AUTHREG_USE bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszSerialName) { SQLPacket_IsErrorOccur = false; + const int nVipUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_VIP; AUTHREG_SERIALTABLE st_SerialTable; AUTHREG_USERTABLE st_UserTable; @@ -361,6 +371,14 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszS SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_NOTSUPPORT; return false; } + //充值成功后自动升级为可登录等级 + _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET nUserLevel = '%d' WHERE UserName = '%s'"), nVipUserLevel, lpszUserName); + if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_Serial` SET UserName = '%s',bIsUsed = '1' WHERE SerialNumber = '%s'"), lpszUserName, lpszSerialName); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { @@ -386,6 +404,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszS bool CDBModule_MySQL::DBModule_MySQL_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimeProtocol) { SQLPacket_IsErrorOccur = false; + const int nNormalUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_USER; XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); @@ -426,6 +445,16 @@ bool CDBModule_MySQL::DBModule_MySQL_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimePr SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; return false; } + if (pSt_TimeProtocol->nTimeLeft <= 0) + { + _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET nUserLevel = '%d' WHERE UserName = '%s'"), nNormalUserLevel, pSt_TimeProtocol->tszUserName); + if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } + } return true; } /******************************************************************** @@ -448,7 +477,7 @@ bool CDBModule_MySQL::DBModule_MySQL_UserSet(AUTHREG_USERTABLE* pSt_UserTable) XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); - _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET Password = '%s',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',UPTime = NOW(),CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel/*, pSt_UserTable->st_UserInfo.tszLoginTime*/, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); + _xstprintf(tszSQLStatement, _X("UPDATE `Authorize_User` SET Password = '%s',Token = '%lld',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->st_UserInfo.xhToken, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); //更新用户剩余时间 if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) @@ -528,6 +557,9 @@ bool CDBModule_MySQL::DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInf //密码 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->st_UserInfo.tszUserPass, ppszResult[nFliedValue]); + //TOKEN + nFliedValue++; + (*pppSt_UserInfo)[i]->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]); //过期时间 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->tszLeftTime, ppszResult[nFliedValue]); @@ -549,6 +581,9 @@ bool CDBModule_MySQL::DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInf //用户级别 -1表示封禁 nFliedValue++; (*pppSt_UserInfo)[i]->st_UserInfo.nUserLevel = _ttxoi(ppszResult[nFliedValue]); + //总时间 + nFliedValue++; + (*pppSt_UserInfo)[i]->nTimeCount = _ttxoll(ppszResult[nFliedValue]); //登录日期 nFliedValue++; if (NULL != ppszResult[nFliedValue] && _tcsxlen(ppszResult[nFliedValue]) > 0) @@ -600,6 +635,38 @@ bool CDBModule_MySQL::DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lps return true; } /******************************************************************** +函数名称:DBModule_MySQL_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +bool CDBModule_MySQL::DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + SQLPacket_IsErrorOccur = false; + XCHAR tszSQLStatement[1024] = {}; + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_Login SET CountTime = CountTime + %lld WHERE UserName = '%s'"), nTime, lpszUserName); + + if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_ISFAILED; + return false; + } + return true; +} +/******************************************************************** 函数名称:DBModule_MySQL_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName @@ -672,7 +739,7 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialInsert(AUTHREG_SERIALTABLE* pSt_Seria SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_Serial` values(NULL,'%s','%s','%s',%d,%d,'%s','%s')"), pSt_SerialTable->tszUserName, pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszExpiredTime); + _xstprintf(tszSQLStatement, _X("INSERT INTO `Authorize_Serial` values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszCreateUser, pSt_SerialTable->tszExpiredTime); if (!DataBase_MySQL_Execute(xhData, tszSQLStatement)) { @@ -776,9 +843,12 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialQuery(LPCXSTR lpszSerialNumber, LPAUT //是否已经使用 nFliedValue++; pSt_SerialTable->bIsUsed = _ttxoi(ppszResult[nFliedValue]); - //超时时间 + //创建时间 nFliedValue++; _tcsxcpy(pSt_SerialTable->tszCreateTime, ppszResult[nFliedValue]); + //创建用户 + nFliedValue++; + _tcsxcpy(pSt_SerialTable->tszCreateUser, ppszResult[nFliedValue]); //过期时间 nFliedValue++; if (NULL != ppszResult[nFliedValue]) @@ -874,6 +944,9 @@ bool CDBModule_MySQL::DBModule_MySQL_SerialQueryAll(AUTHREG_SERIALTABLE*** pppSt //创建时间 _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateTime, ppszResult[nFliedValue]); nFliedValue++; + //创建用户 + _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateUser, ppszResult[nFliedValue]); + nFliedValue++; //过期时间 if (NULL != ppszResult[nFliedValue]) { @@ -2015,4 +2088,3 @@ bool CDBModule_MySQL::DBModule_MySQL_UserPayTime(LPCXSTR lpszUserName, LPCXSTR l } return true; } - diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h index 71f85531..9945666c 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_MySQL/DBModule_MySQL.h @@ -31,6 +31,7 @@ class CDBModule_MySQL bool DBModule_MySQL_UserSet(AUTHREG_USERTABLE* pSt_UserTable); //设置用户信息 bool DBModule_MySQL_UserList(AUTHREG_USERTABLE*** pppSt_UserInfo, int* pInt_ListCount, int nPosStart, int nPosEnd); //获取用户列表 bool DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); + bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime); bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); public: bool DBModule_MySQL_SerialInsert(AUTHREG_SERIALTABLE* pSt_SerialTable); //插入序列卡 diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp index 2de361b8..30c43e64 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.cpp @@ -126,7 +126,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserRegister(AUTHREG_USERTABLE* pSt_UserI SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CreateTime) values('%s','%s','%s','%s','%s','%d',%lld,%lld,%d,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); + _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_User(UserName, Password, Token, LeftTime, EmailAddr, HardCode, CardSerialType, PhoneNumber, IDCard, nUserLevel, CountTime, CreateTime) values('%s','%s','0','%s','%s','%s','%d',%lld,%lld,%d,0,datetime('now', 'localtime'))"), pSt_UserInfo->st_UserInfo.tszUserName, pSt_UserInfo->st_UserInfo.tszUserPass, pSt_UserInfo->tszLeftTime, pSt_UserInfo->st_UserInfo.tszEMailAddr, pSt_UserInfo->tszHardCode, pSt_UserInfo->enSerialType, pSt_UserInfo->st_UserInfo.nPhoneNumber, pSt_UserInfo->st_UserInfo.nIDNumber, pSt_UserInfo->st_UserInfo.nUserLevel); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { SQLPacket_IsErrorOccur = true; @@ -201,6 +201,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U //密码 nFliedValue++; _tcsxcpy(pSt_UserInfo->st_UserInfo.tszUserPass, ppszResult[nFliedValue]); + //TOKEN + nFliedValue++; + pSt_UserInfo->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]); //过期时间 nFliedValue++; _tcsxcpy(pSt_UserInfo->tszLeftTime, ppszResult[nFliedValue]); @@ -222,6 +225,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U //用户级别 -1表示封禁 nFliedValue++; pSt_UserInfo->st_UserInfo.nUserLevel = _ttxoi(ppszResult[nFliedValue]); + //总共时间 + nFliedValue++; + pSt_UserInfo->nTimeCount = _ttxoll(ppszResult[nFliedValue]); //登录日期 nFliedValue++; if (NULL != ppszResult[nFliedValue] && _tcsxlen(ppszResult[nFliedValue]) > 0) @@ -257,6 +263,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserQuery(LPCXSTR lpszUserName, AUTHREG_U bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lpszSerialName) { SQLPacket_IsErrorOccur = false; + const int nVipUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_VIP; AUTHREG_SERIALTABLE st_SerialTable; AUTHREG_USERTABLE st_UserTable; @@ -321,6 +328,14 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lps SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_NOTSUPPORT; return false; } + //充值成功后自动升级为可登录等级 + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET nUserLevel = '%d' WHERE UserName = '%s'"), nVipUserLevel, lpszUserName); + if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } _xstprintf(tszSQLStatement, _X("UPDATE Authorize_Serial SET UserName = '%s',bIsUsed = '1' WHERE SerialNumber = '%s'"), lpszUserName, lpszSerialName); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { @@ -346,6 +361,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPay(LPCXSTR lpszUserName, LPCXSTR lps bool CDBModule_SQLite::DBModule_SQLite_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_TimeProtocol) { SQLPacket_IsErrorOccur = false; + const int nNormalUserLevel = ENUM_XENGINE_PROTOCOLHDR_LEVEL_TYPE_USER; XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); @@ -385,6 +401,16 @@ bool CDBModule_SQLite::DBModule_SQLite_UserLeave(AUTHREG_PROTOCOL_TIME* pSt_Time SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; return false; } + if (pSt_TimeProtocol->nTimeLeft <= 0) + { + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET nUserLevel = '%d' WHERE UserName = '%s'"), nNormalUserLevel, pSt_TimeProtocol->tszUserName); + if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_UPDATA; + return false; + } + } return true; } /******************************************************************** @@ -407,7 +433,7 @@ bool CDBModule_SQLite::DBModule_SQLite_UserSet(AUTHREG_USERTABLE* pSt_UserTable) XCHAR tszSQLStatement[1024]; //SQL语句 memset(tszSQLStatement, '\0', 1024); - _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET Password = '%s',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',UPTime = '%s',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->st_UserInfo.tszLoginTime, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_User SET Password = '%s',Token = '%lld',LeftTime = '%s',EmailAddr = '%s',HardCode = '%s',CardSerialType = '%d',PhoneNumber = '%lld',IDCard = '%lld',nUserLevel = '%d',CountTime = '%lld',CreateTime = '%s' WHERE UserName = '%s'"), pSt_UserTable->st_UserInfo.tszUserPass, pSt_UserTable->st_UserInfo.xhToken, pSt_UserTable->tszLeftTime, pSt_UserTable->st_UserInfo.tszEMailAddr, pSt_UserTable->tszHardCode, pSt_UserTable->enSerialType, pSt_UserTable->st_UserInfo.nPhoneNumber, pSt_UserTable->st_UserInfo.nIDNumber, pSt_UserTable->st_UserInfo.nUserLevel, pSt_UserTable->nTimeCount, pSt_UserTable->st_UserInfo.tszCreateTime, pSt_UserTable->st_UserInfo.tszUserName); //更新用户剩余时间 if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { @@ -480,6 +506,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserI //密码 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->st_UserInfo.tszUserPass, ppszResult[nFliedValue]); + //TOKEN + nFliedValue++; + (*pppSt_UserInfo)[i]->st_UserInfo.xhToken = _ttxoll(ppszResult[nFliedValue]); //过期时间 nFliedValue++; _tcsxcpy((*pppSt_UserInfo)[i]->tszLeftTime, ppszResult[nFliedValue]); @@ -501,6 +530,9 @@ bool CDBModule_SQLite::DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserI //用户级别 -1表示封禁 nFliedValue++; (*pppSt_UserInfo)[i]->st_UserInfo.nUserLevel = _ttxoi(ppszResult[nFliedValue]); + //总共时间 + nFliedValue++; + (*pppSt_UserInfo)[i]->nTimeCount = _ttxoll(ppszResult[nFliedValue]); //登录日期 nFliedValue++; if (NULL != ppszResult[nFliedValue] && _tcsxlen(ppszResult[nFliedValue]) > 0) @@ -551,6 +583,38 @@ bool CDBModule_SQLite::DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR l return true; } /******************************************************************** +函数名称:DBModule_SQLite_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +bool CDBModule_SQLite::DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + SQLPacket_IsErrorOccur = false; + + XCHAR tszSQLStatement[1024] = {}; + _xstprintf(tszSQLStatement, _X("UPDATE Authorize_Login SET CountTime = CountTime + %lld WHERE UserName = '%s'"), nTime, lpszUserName); + if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) + { + SQLPacket_IsErrorOccur = true; + SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_INSERT; + return false; + } + return true; +} +/******************************************************************** 函数名称:DBModule_SQLite_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName @@ -623,7 +687,7 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialInsert(AUTHREG_SERIALTABLE *pSt_Ser SQLPacket_dwErrorCode = ERROR_AUTHORIZE_MODULE_DATABASE_EXIST; return false; } - _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_Serial values(NULL,'%s','%s','%s',%d,%d,'%s','%s')"), pSt_SerialTable->tszUserName, pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszExpiredTime); + _xstprintf(tszSQLStatement, _X("INSERT INTO Authorize_Serial values(NULL,'NOT','%s','%s',%d,%d,'%s','%s','%s')"), pSt_SerialTable->tszSerialNumber, pSt_SerialTable->tszMaxTime, pSt_SerialTable->enSerialType, pSt_SerialTable->bIsUsed, pSt_SerialTable->tszCreateTime, pSt_SerialTable->tszCreateUser, pSt_SerialTable->tszExpiredTime); if (!DataBase_SQLite_Exec(xhData, tszSQLStatement)) { @@ -722,9 +786,12 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialQuery(LPCXSTR lpszSerialNumber, LPA //是否已经使用 nFliedValue++; pSt_SerialTable->bIsUsed = _ttxoi(ppszResult[nFliedValue]); - //超时时间 + //创建时间 nFliedValue++; _tcsxcpy(pSt_SerialTable->tszCreateTime, ppszResult[nFliedValue]); + //创建用户 + nFliedValue++; + _tcsxcpy(pSt_SerialTable->tszCreateUser, ppszResult[nFliedValue]); //过期时间 nFliedValue++; if (NULL != ppszResult[nFliedValue]) @@ -813,6 +880,9 @@ bool CDBModule_SQLite::DBModule_SQLite_SerialQueryAll(AUTHREG_SERIALTABLE*** ppp nFliedValue++; //创建时间 _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateTime, ppszResult[nFliedValue]); + nFliedValue++; + //创建用户 + _tcsxcpy((*pppSt_SerialTable)[i]->tszCreateUser, ppszResult[nFliedValue]); nFliedValue++; //过期时间 if (NULL != ppszResult[nFliedValue]) @@ -1875,4 +1945,4 @@ bool CDBModule_SQLite::DBModule_SQLite_UserPayTime(LPCXSTR lpszUserName, LPCXSTR return false; } return true; -} \ No newline at end of file +} diff --git a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h index 7ce8482d..065d0979 100644 --- a/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h +++ b/XEngine_Source/AuthorizeModule_Database/DBModule_SQLite/DBModule_SQLite.h @@ -31,6 +31,7 @@ class CDBModule_SQLite bool DBModule_SQLite_UserSet(AUTHREG_USERTABLE* pSt_UserTable); bool DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserInfo, int* pInt_ListCount, int nPosStart, int nPosEnd); bool DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); + bool DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime); bool DBModule_SQLite_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); public: bool DBModule_SQLite_SerialInsert(AUTHREG_SERIALTABLE* pSt_SerialTable); //插入序列卡 diff --git a/XEngine_Source/AuthorizeModule_Database/Database_Define.h b/XEngine_Source/AuthorizeModule_Database/Database_Define.h index 4b3aa74d..e024ac4b 100644 --- a/XEngine_Source/AuthorizeModule_Database/Database_Define.h +++ b/XEngine_Source/AuthorizeModule_Database/Database_Define.h @@ -193,6 +193,25 @@ extern "C" bool DBModule_SQLite_UserList(AUTHREG_USERTABLE*** pppSt_UserInfo, in *********************************************************************/ extern "C" bool DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); /******************************************************************** +函数名称:DBModule_SQLite_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" bool DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime); +/******************************************************************** 函数名称:DBModule_SQLite_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName @@ -1032,6 +1051,25 @@ extern "C" bool DBModule_MySQL_AnnouncementList(AUTHREG_ANNOUNCEMENT*** ppppSt_A *********************************************************************/ extern "C" bool DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr); /******************************************************************** +函数名称:DBModule_MySQL_UserTime +函数功能:增加用户在线时间 + 参数.一:lpszUserName + In/Out:In + 类型:常量字符指针 + 可空:N + 意思:用户名 + 参数.二:nTime + In/Out:In + 类型:整数型 + 可空:N + 意思:增加的时间 +返回值 + 类型:逻辑型 + 意思:是否成功 +备注: +*********************************************************************/ +extern "C" bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime); +/******************************************************************** 函数名称:DBModule_MySQL_QueryLogin 函数功能:用户登录记录查询 参数.一:lpszUserName diff --git a/XEngine_Source/AuthorizeModule_Database/pch.cpp b/XEngine_Source/AuthorizeModule_Database/pch.cpp index 4260df94..fab208bb 100644 --- a/XEngine_Source/AuthorizeModule_Database/pch.cpp +++ b/XEngine_Source/AuthorizeModule_Database/pch.cpp @@ -71,6 +71,10 @@ extern "C" bool DBModule_SQLite_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUser { return m_DBSQLite.DBModule_SQLite_UserLogin(lpszUserName, lpszUserAddr); } +extern "C" bool DBModule_SQLite_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + return m_DBSQLite.DBModule_SQLite_UserTime(lpszUserName, nTime); +} extern "C" bool DBModule_SQLite_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr) { return m_DBSQLite.DBModule_SQLite_QueryLogin(lpszUserName, lpszUserAddr); @@ -262,6 +266,10 @@ extern "C" bool DBModule_MySQL_UserLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserA { return m_DBMySQL.DBModule_MySQL_UserLogin(lpszUserName, lpszUserAddr); } +extern "C" bool DBModule_MySQL_UserTime(LPCXSTR lpszUserName, __int64x nTime) +{ + return m_DBMySQL.DBModule_MySQL_UserTime(lpszUserName, nTime); +} extern "C" bool DBModule_MySQL_QueryLogin(LPCXSTR lpszUserName, LPCXSTR lpszUserAddr) { return m_DBMySQL.DBModule_MySQL_QueryLogin(lpszUserName, lpszUserAddr); diff --git a/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj b/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj index 2d8e1b60..2c016fbb 100644 --- a/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj +++ b/XEngine_Source/AuthorizeModule_Help/AuthorizeModule_Help.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj index 693e0fd2..429463c4 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj +++ b/XEngine_Source/AuthorizeModule_Protocol/AuthorizeModule_Protocol.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp index 310dfb85..b41367b1 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Packet/Protocol_Packet.cpp @@ -405,6 +405,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientInfo(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = pSt_UserTable->st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = pSt_UserTable->st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = (Json::Value::Int64)pSt_UserTable->st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = pSt_UserTable->st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = pSt_UserTable->st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = pSt_UserTable->st_UserInfo.tszCreateTime; @@ -412,6 +413,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientInfo(XCHAR* ptszMsgBuffer, int* st_JsonUser["nIDNumber"] = (Json::Value::UInt64)pSt_UserTable->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = pSt_UserTable->st_UserInfo.nUserLevel; st_JsonUser["nUserState"] = 0; + st_JsonUser["nTimeCount"] = (Json::Value::Int64)pSt_UserTable->nTimeCount; st_JsonObject["tszLeftTime"] = pSt_UserTable->tszLeftTime; st_JsonObject["tszHardCode"] = pSt_UserTable->tszHardCode; @@ -485,6 +487,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = (Json::Value::Int64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.tszCreateTime; @@ -492,6 +495,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OnClient)[i]->st_UserTable.st_UserInfo.nUserLevel; st_JsonUser["nUserState"] = 1; + st_JsonUser["nTimeCount"] = (Json::Value::Int64)(*pppSt_OnClient)[i]->st_UserTable.nTimeCount; st_JsonObject["tszClientAddr"] = (*pppSt_OnClient)[i]->tszClientAddr; st_JsonObject["tszLeftTime"] = (*pppSt_OnClient)[i]->tszLeftTime; @@ -525,12 +529,14 @@ bool CProtocol_Packet::Protocol_Packet_HttpClientList(XCHAR* ptszMsgBuffer, int* st_JsonUser["tszUserName"] = (*pppSt_OffClient)[i]->st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = (*pppSt_OffClient)[i]->st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = (Json::Value::Int64)(*pppSt_OffClient)[i]->st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = (*pppSt_OffClient)[i]->st_UserInfo.tszEMailAddr; st_JsonUser["tszLoginTime"] = (*pppSt_OffClient)[i]->st_UserInfo.tszLoginTime; st_JsonUser["tszCreateTime"] = (*pppSt_OffClient)[i]->st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = (Json::Value::UInt64)(*pppSt_OffClient)[i]->st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = (Json::Value::UInt64)(*pppSt_OffClient)[i]->st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = (*pppSt_OffClient)[i]->st_UserInfo.nUserLevel; + st_JsonUser["nTimeCount"] = (Json::Value::Int64)(*pppSt_OffClient)[i]->nTimeCount; st_JsonUser["nUserState"] = 0; st_JsonObject["tszLeftTime"] = (*pppSt_OffClient)[i]->tszLeftTime; @@ -599,6 +605,7 @@ bool CProtocol_Packet::Protocol_Packet_HttpSerialList(XCHAR* ptszMsgBuffer, int* st_JsonObject["enSerialType"] = (*pppSt_SerialList)[i]->enSerialType; st_JsonObject["bIsUsed"] = (*pppSt_SerialList)[i]->bIsUsed; st_JsonObject["tszCreateTime"] = (*pppSt_SerialList)[i]->tszCreateTime; + st_JsonObject["tszCreateUser"] = (*pppSt_SerialList)[i]->tszCreateUser; st_JsonObject["tszExpiredTime"] = (*pppSt_SerialList)[i]->tszExpiredTime; st_JsonArray.append(st_JsonObject); } diff --git a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp index 8211cec2..40a5ed70 100644 --- a/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp +++ b/XEngine_Source/AuthorizeModule_Protocol/Protocol_Parse/Protocol_Parse.cpp @@ -487,6 +487,14 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseTable(LPCXSTR lpszMsgBuffer, int n { _tcsxcpy(pSt_UserTable->st_UserInfo.tszUserPass, st_UserInfo["tszUserPass"].asCString()); } + if (!st_UserInfo["xhToken"].isNull()) + { + pSt_UserTable->st_UserInfo.xhToken = st_UserInfo["xhToken"].asInt64(); + } + if (!st_UserInfo["nTimeCount"].isNull()) + { + pSt_UserTable->nTimeCount = st_UserInfo["nTimeCount"].asInt(); + } if (!st_UserInfo["tszEMailAddr"].isNull()) { _tcsxcpy(pSt_UserTable->st_UserInfo.tszEMailAddr, st_UserInfo["tszEMailAddr"].asCString()); @@ -515,6 +523,7 @@ bool CProtocol_Parse::Protocol_Parse_HttpParseTable(LPCXSTR lpszMsgBuffer, int n { pSt_UserTable->st_UserInfo.nUserState = st_UserInfo["nUserState"].asInt(); } + return true; } /******************************************************************** diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def index 467624a6..be950a99 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.def @@ -1,7 +1,7 @@ LIBRARY EXPORTS - Session_GetLastError + AuthSession_GetLastError Session_Authorize_Init Session_Authorize_GetClient @@ -9,13 +9,4 @@ EXPORTS Session_Authorize_CloseAddr Session_Authorize_Destroy Session_Authorize_Insert - Session_Authorize_SetUser - - Session_Token_Init - Session_Token_Destroy - Session_Token_Insert - Session_Token_Delete - Session_Token_UPDate - Session_Token_Get - Session_Token_GetUser - Session_Token_RenewalTime \ No newline at end of file + Session_Authorize_SetUser \ No newline at end of file diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj index 68c2dfa0..5dd11d2b 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj @@ -37,39 +37,39 @@ DynamicLibrary true - v143 + v145 Unicode DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary true - v143 + v145 MultiByte DynamicLibrary false - v143 + v145 true Unicode DynamicLibrary false - v143 + v145 true Unicode @@ -253,7 +253,6 @@ - @@ -266,7 +265,6 @@ Create - diff --git a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters index a46b6995..3b6482ba 100644 --- a/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters +++ b/XEngine_Source/AuthorizeModule_Session/AuthorizeModule_Session.vcxproj.filters @@ -19,12 +19,6 @@ {98019e80-6680-48fa-a755-702b5b3aab78} - - {5ad6d359-09c2-4995-82f6-e5f2e32a14c1} - - - {0b721944-f23e-4671-81dc-beb1970fe840} - @@ -42,9 +36,6 @@ 头文件\Session_Authorize - - 头文件\Session_Token - @@ -56,9 +47,6 @@ 源文件\Session_Authorize - - 源文件\Session_Token - diff --git a/XEngine_Source/AuthorizeModule_Session/Makefile b/XEngine_Source/AuthorizeModule_Session/Makefile index b25b0a9c..7d462870 100644 --- a/XEngine_Source/AuthorizeModule_Session/Makefile +++ b/XEngine_Source/AuthorizeModule_Session/Makefile @@ -6,7 +6,7 @@ LOADHDR = -I ./ LOADSO = LIB = -lXEngine_BaseLib LIBEX = -OBJECTS = Session_Authorize.o Session_Token.o pch.o +OBJECTS = Session_Authorize.o pch.o ifeq ($(RELEASE),1) FLAGS = -c -D _RELEASE @@ -51,8 +51,6 @@ all:$(OBJECTS) Session_Authorize.o:./Session_Authorize/Session_Authorize.cpp $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./Session_Authorize/Session_Authorize.cpp -Session_Token.o:./Session_Token/Session_Token.cpp - $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./Session_Token/Session_Token.cpp pch.o:pch.cpp $(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) pch.cpp diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Define.h b/XEngine_Source/AuthorizeModule_Session/Session_Define.h index 8192c686..c81115f7 100644 --- a/XEngine_Source/AuthorizeModule_Session/Session_Define.h +++ b/XEngine_Source/AuthorizeModule_Session/Session_Define.h @@ -30,7 +30,7 @@ typedef void(XCALLBACK* CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS)(XNETHAN ////////////////////////////////////////////////////////////////////////// // 导出的函数 ////////////////////////////////////////////////////////////////////////// -extern "C" XLONG Session_GetLastError(int *pInt_SysError = NULL); +extern "C" XLONG AuthSession_GetLastError(int *pInt_SysError = NULL); /************************************************************************/ /* 网络验证导出函数 */ /************************************************************************/ @@ -161,149 +161,4 @@ extern "C" bool Session_Authorize_Insert(LPCXSTR lpszClientAddr, AUTHREG_USERTAB 意思:是否成功 备注: *********************************************************************/ -extern "C" bool Session_Authorize_SetUser(AUTHREG_USERTABLE* pSt_UserTable); -/************************************************************************/ -/* TOKEN会话导出函数 */ -/************************************************************************/ -/******************************************************************** -函数名称:Session_Token_Init -函数功能:初始化会话 - 参数.一:nTimeout - In/Out:In - 类型:整数型 - 可空:N - 意思:超时时间,单位秒 - 参数.二:fpCall_AuthEvent - In/Out:In/Out - 类型:回调函数 - 可空:N - 意思:TOKEN登录的客户端连接超时回调 - 参数.三:lParam - In/Out:In/Out - 类型:无类型指针 - 可空:Y - 意思:回调函数自定义参数 -返回值 - 类型:逻辑型 - 意思:是否初始化成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam = NULL); -/******************************************************************** -函数名称:Session_Token_Destroy -函数功能:销毁服务 -返回值 - 类型:逻辑型 - 意思:是否销毁成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Destroy(); -/******************************************************************** -函数名称:Session_Authorize_Insert -函数功能:用户登陆协议分析 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:In - 类型:数据结构指针 - 可空:N - 意思:用户信息表 -返回值 - 类型:逻辑型 - 意思:是否允许登陆 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable); -/******************************************************************** -函数名称:Session_Token_Delete -函数功能:移除一个客户端 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否移除成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Delete(XNETHANDLE xhToken); -/******************************************************************** -函数名称:Session_Token_UPDate -函数功能:更新一个客户端的TOKEN时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_UPDate(XNETHANDLE xhToken); -/******************************************************************** -函数名称:Session_Token_Get -函数功能:获取客户端信息 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:Out - 类型:数据结构指针 - 可空:Y - 意思:输出TOKEN对应的信息 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable = NULL); -/******************************************************************** -函数名称:Session_Token_GetUser -函数功能:获取用户是否存在 - 参数.一:lpszUser - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:用户名 - 参数.二:lpszPass - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:密码 - 参数.三:pxhToken - In/Out:Out - 类型:句柄 - 可空:N - 意思:导出获取到的句柄 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE * pxhToken); -/******************************************************************** -函数名称:Session_Token_RenewalTime -函数功能:续期时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:输入要操作的TOKEN - 参数.二:pInt_RenewalTime - In/Out:Out - 类型:整数型指针 - 可空:N - 意思:输出续期的次数 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -extern "C" bool Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime); \ No newline at end of file +extern "C" bool Session_Authorize_SetUser(AUTHREG_USERTABLE* pSt_UserTable); \ No newline at end of file diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp b/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp deleted file mode 100644 index 5e6f7430..00000000 --- a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.cpp +++ /dev/null @@ -1,375 +0,0 @@ -#include "pch.h" -#include "Session_Token.h" -/******************************************************************** -// Created: 2022/08/18 14:43:33 -// File Name: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token\Session_Token.cpp -// File Path: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token -// File Base: Session_Token -// File Ext: cpp -// Project: XEngine(网络通信引擎) -// Author: qyt -// Purpose: TOKEN会话管理 -// History: -*********************************************************************/ -CSession_Token::CSession_Token() -{ - bIsRun = false; -} -CSession_Token::~CSession_Token() -{ -} -////////////////////////////////////////////////////////////////////////// -// 公有函数 -////////////////////////////////////////////////////////////////////////// -/******************************************************************** -函数名称:Session_Token_Init -函数功能:初始化会话 - 参数.一:nTimeout - In/Out:In - 类型:整数型 - 可空:N - 意思:超时时间,单位秒 - 参数.二:fpCall_AuthEvent - In/Out:In/Out - 类型:回调函数 - 可空:N - 意思:TOKEN登录的客户端连接超时回调 - 参数.三:lParam - In/Out:In/Out - 类型:无类型指针 - 可空:Y - 意思:回调函数自定义参数 -返回值 - 类型:逻辑型 - 意思:是否初始化成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam /* = NULL */) -{ - Session_IsErrorOccur = false; - - if (NULL == fpCall_AuthEvent) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - return false; - } - m_nTimeout = nTimeout; - m_lParam = lParam; - lpCall_AuthregEvents = fpCall_AuthEvent; - - bIsRun = true; - //创建线程 - pSTDThread_hActive = make_shared(Session_Token_Thread, this); - if (!pSTDThread_hActive->joinable()) - { - bIsRun = false; - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_CREATETHREAD; - return false; - } - return true; -} -/******************************************************************** -函数名称:Session_Token_Destroy -函数功能:销毁服务 -返回值 - 类型:逻辑型 - 意思:是否销毁成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Destroy() -{ - Session_IsErrorOccur = false; - - bIsRun = false; - //结束线程 - if (NULL != pSTDThread_hActive) - { - pSTDThread_hActive->join(); - } - //释放客户端资源 - st_Locker.lock(); - stl_MapToken.clear(); - st_Locker.unlock(); - return true; -} -/******************************************************************** -函数名称:Session_Authorize_Insert -函数功能:用户登陆协议分析 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:In - 类型:数据结构指针 - 可空:N - 意思:用户信息表 -返回值 - 类型:逻辑型 - 意思:是否允许登陆 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable) -{ - Session_IsErrorOccur = false; - - if (NULL == pSt_UserTable) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - return false; - } - AUTHSESSION_TOKENCLIENT st_TokenClient; - memset(&st_TokenClient,'\0',sizeof(AUTHSESSION_TOKENCLIENT)); - - BaseLib_Time_GetSysTime(&st_TokenClient.st_LibTimer); - memcpy(&st_TokenClient.st_UserTable, pSt_UserTable, sizeof(AUTHREG_USERTABLE)); - - st_Locker.lock(); - stl_MapToken.insert(make_pair(xhToken, st_TokenClient)); - st_Locker.unlock(); - return true; -} -/******************************************************************** -函数名称:Session_Token_Delete -函数功能:移除一个客户端 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否移除成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Delete(XNETHANDLE xhToken) -{ - Session_IsErrorOccur = false; - - st_Locker.lock(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator != stl_MapToken.end()) - { - //移除元素 - stl_MapToken.erase(stl_MapIterator); - } - st_Locker.unlock(); - return true; -} -/******************************************************************** -函数名称:Session_Token_UPDate -函数功能:更新一个客户端的TOKEN时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_UPDate(XNETHANDLE xhToken) -{ - Session_IsErrorOccur = false; - - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator == stl_MapToken.end()) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - st_Locker.unlock_shared(); - return false; - } - BaseLib_Time_GetSysTime(&stl_MapIterator->second.st_LibTimer); - st_Locker.unlock_shared(); - return true; -} -/******************************************************************** -函数名称:Session_Token_Get -函数功能:获取客户端信息 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:要操作的客户端 - 参数.二:pSt_UserTable - In/Out:Out - 类型:数据结构指针 - 可空:Y - 意思:输出TOKEN对应的信息 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable /* = NULL */) -{ - Session_IsErrorOccur = false; - - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator == stl_MapToken.end()) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_NOTFOUND; - st_Locker.unlock_shared(); - return false; - } - if (NULL != pSt_UserTable) - { - *pSt_UserTable = stl_MapIterator->second.st_UserTable; - } - st_Locker.unlock_shared(); - return true; -} -/******************************************************************** -函数名称:Session_Token_GetUser -函数功能:获取用户的TOKEN - 参数.一:lpszUser - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:用户名 - 参数.二:lpszPass - In/Out:In - 类型:常量字符指针 - 可空:N - 意思:密码 - 参数.三:pxhToken - In/Out:Out - 类型:句柄 - 可空:N - 意思:导出获取到的句柄 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE* pxhToken) -{ - Session_IsErrorOccur = false; - - if ((NULL == lpszUser) || (NULL == lpszPass)) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - return false; - } - bool bFound = false; - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.begin(); - for (; stl_MapIterator != stl_MapToken.end(); stl_MapIterator++) - { - //用户名 - if (0 == _tcsxncmp(lpszUser, stl_MapIterator->second.st_UserTable.st_UserInfo.tszUserName, _tcsxlen(lpszUser))) - { - //密码,验证密码防治冲突 - if (0 == _tcsxncmp(lpszPass, stl_MapIterator->second.st_UserTable.st_UserInfo.tszUserPass, _tcsxlen(lpszPass))) - { - *pxhToken = stl_MapIterator->first; - bFound = true; - break; - } - } - } - st_Locker.unlock_shared(); - if (!bFound) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_NOTFOUND; - return false; - } - return true; -} -/******************************************************************** -函数名称:Session_Token_RenewalTime -函数功能:续期时间 - 参数.一:xhToken - In/Out:In - 类型:句柄 - 可空:N - 意思:输入要操作的TOKEN - 参数.二:pInt_RenewalTime - In/Out:Out - 类型:整数型指针 - 可空:N - 意思:输出续期的次数 -返回值 - 类型:逻辑型 - 意思:是否成功 -备注: -*********************************************************************/ -bool CSession_Token::Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime) -{ - Session_IsErrorOccur = false; - - st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = stl_MapToken.find(xhToken); - if (stl_MapIterator == stl_MapToken.end()) - { - Session_IsErrorOccur = true; - Session_dwErrorCode = ERROR_AUTHORIZE_MODULE_SESSION_PARAMENT; - st_Locker.unlock_shared(); - return false; - } - stl_MapIterator->second.nRenewalTime++; - *pInt_RenewalTime = stl_MapIterator->second.nRenewalTime; - st_Locker.unlock_shared(); - return true; -} -////////////////////////////////////////////////////////////////////////// -// 线程函数 -////////////////////////////////////////////////////////////////////////// -XHTHREAD CSession_Token::Session_Token_Thread(XPVOID lParam) -{ - CSession_Token *pClass_This = (CSession_Token *)lParam; - XENGINE_LIBTIME st_LibTimer; - list stl_ListNotify; - - while (pClass_This->bIsRun) - { - //开始轮训用户 - pClass_This->st_Locker.lock_shared(); - unordered_map::iterator stl_MapIterator = pClass_This->stl_MapToken.begin(); - for (; stl_MapIterator != pClass_This->stl_MapToken.end(); stl_MapIterator++) - { - BaseLib_Time_GetSysTime(&st_LibTimer); //获取现在的系统时间 - __int64x nOnlineSpan = 0; //在线时间 - //用户登录了多少秒 - BaseLib_TimeSpan_GetForStu(&stl_MapIterator->second.st_LibTimer, &st_LibTimer, &nOnlineSpan, ENUM_XENGINE_BASELIB_TIME_TYPE_SECOND); - if (stl_MapIterator->second.nTimeout > 0) - { - if (nOnlineSpan > stl_MapIterator->second.nTimeout) - { - stl_ListNotify.push_back(stl_MapIterator->first); - } - } - else - { - if (nOnlineSpan > pClass_This->m_nTimeout) - { - stl_ListNotify.push_back(stl_MapIterator->first); - } - } - } - pClass_This->st_Locker.unlock_shared(); - //判断是否有需要关闭的客户端 - if (!stl_ListNotify.empty()) - { - list::iterator stl_ListIterator = stl_ListNotify.begin(); - for (; stl_ListIterator != stl_ListNotify.end(); stl_ListIterator++) - { - pClass_This->lpCall_AuthregEvents(*stl_ListIterator, pClass_This->m_lParam); - } - stl_ListNotify.clear(); //清理元素 - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - return 0; -} diff --git a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h b/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h deleted file mode 100644 index 9ab54a2f..00000000 --- a/XEngine_Source/AuthorizeModule_Session/Session_Token/Session_Token.h +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -/******************************************************************** -// Created: 2022/08/18 14:29:38 -// File Name: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token\Session_Token.h -// File Path: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\Session_Token -// File Base: Session_Token -// File Ext: h -// Project: XEngine(网络通信引擎) -// Author: qyt -// Purpose: TOKEN会话 -// History: -*********************************************************************/ -typedef struct -{ - AUTHREG_USERTABLE st_UserTable; //用户表 - XENGINE_LIBTIME st_LibTimer; //登录时间结构 - int nTimeout; //单独指定超时 - int nRenewalTime; //自动续期次数 -}AUTHSESSION_TOKENCLIENT, * LPAUTHSESSION_TOKENCLIENT; -////////////////////////////////////////////////////////////////////////// -class CSession_Token -{ -public: - CSession_Token(); - ~CSession_Token(); -public: - bool Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam = NULL); - bool Session_Token_Destroy(); - bool Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable); - bool Session_Token_Delete(XNETHANDLE xhToken); - bool Session_Token_UPDate(XNETHANDLE xhToken); - bool Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE* pSt_UserTable = NULL); - bool Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE* pxhToken); - bool Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime); -protected: - static XHTHREAD Session_Token_Thread(XPVOID lParam); -private: - int m_nTimeout; - bool bIsRun; - shared_ptr pSTDThread_hActive; -private: - XPVOID m_lParam; - CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS lpCall_AuthregEvents; -private: - shared_mutex st_Locker; -private: - unordered_map stl_MapToken; -}; diff --git a/XEngine_Source/AuthorizeModule_Session/pch.cpp b/XEngine_Source/AuthorizeModule_Session/pch.cpp index 8082f0bc..7f968dc6 100644 --- a/XEngine_Source/AuthorizeModule_Session/pch.cpp +++ b/XEngine_Source/AuthorizeModule_Session/pch.cpp @@ -1,6 +1,5 @@ #include "pch.h" #include "Session_Authorize/Session_Authorize.h" -#include "Session_Token/Session_Token.h" /******************************************************************** // Created: 2022/05/26 10:53:58 // File Name: D:\XEngine_Authorize\XEngine_Source\AuthorizeModule_Session\pch.cpp @@ -16,11 +15,10 @@ bool Session_IsErrorOccur = false; XLONG Session_dwErrorCode = 0; ////////////////////////////////////////////////////////////////////////// CSession_Authorize m_SessionAuth; -CSession_Token m_SessionToken; ////////////////////////////////////////////////////////////////////////// // 导出的函数 ////////////////////////////////////////////////////////////////////////// -extern "C" XLONG Session_GetLastError(int* pInt_SysError) +extern "C" XLONG AuthSession_GetLastError(int* pInt_SysError) { if (NULL != pInt_SysError) { @@ -58,39 +56,4 @@ extern "C" bool Session_Authorize_Insert(LPCXSTR lpszClientAddr, AUTHREG_USERTAB extern "C" bool Session_Authorize_SetUser(AUTHREG_USERTABLE * pSt_UserTable) { return m_SessionAuth.Session_Authorize_SetUser(pSt_UserTable); -} -/************************************************************************/ -/* TOKEN会话导出函数 */ -/************************************************************************/ -extern "C" bool Session_Token_Init(int nTimeout, CALLBACK_XENGIEN_AUTHORIZE_SESSION_TOKEN_EVENTS fpCall_AuthEvent, XPVOID lParam) -{ - return m_SessionToken.Session_Token_Init(nTimeout, fpCall_AuthEvent, lParam); -} -extern "C" bool Session_Token_Destroy() -{ - return m_SessionToken.Session_Token_Destroy(); -} -extern "C" bool Session_Token_Insert(XNETHANDLE xhToken, AUTHREG_USERTABLE * pSt_UserTable) -{ - return m_SessionToken.Session_Token_Insert(xhToken, pSt_UserTable); -} -extern "C" bool Session_Token_Delete(XNETHANDLE xhToken) -{ - return m_SessionToken.Session_Token_Delete(xhToken); -} -extern "C" bool Session_Token_UPDate(XNETHANDLE xhToken) -{ - return m_SessionToken.Session_Token_UPDate(xhToken); -} -extern "C" bool Session_Token_Get(XNETHANDLE xhToken, AUTHREG_USERTABLE * pSt_UserTable) -{ - return m_SessionToken.Session_Token_Get(xhToken, pSt_UserTable); -} -extern "C" bool Session_Token_GetUser(LPCXSTR lpszUser, LPCXSTR lpszPass, XNETHANDLE * pxhToken) -{ - return m_SessionToken.Session_Token_GetUser(lpszUser, lpszPass, pxhToken); -} -extern "C" bool Session_Token_RenewalTime(XNETHANDLE xhToken, int* pInt_RenewalTime) -{ - return m_SessionToken.Session_Token_RenewalTime(xhToken, pInt_RenewalTime); } \ No newline at end of file diff --git a/XEngine_Source/Makefile b/XEngine_Source/Makefile index 91371280..93b9b217 100644 --- a/XEngine_Source/Makefile +++ b/XEngine_Source/Makefile @@ -1,11 +1,14 @@ RELEASE = 0 UNICODE = 0 PLATFORM=linux +BUILDTYPE=0 FLAGS= DEPEND_JSONCPP_PATH = ./XEngine_DependLibrary/XEngine_Module/jsoncpp DEPEND_REPORT_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport DEPEND_VERIFICATION_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_Verification +DEPEND_MSGNOTIFY_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify +DEPEND_TOKEN_PATH = ./XEngine_DependLibrary/XEngine_Module/XEngine_Token AUTH_SESSION_PATH = ./AuthorizeModule_Session AUTH_DATABASE_PATH = ./AuthorizeModule_Database @@ -21,9 +24,20 @@ else ifeq ($(PLATFORM),mac) FILEEXT = dylib endif -XENGINE_MODULES = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so \ - libAuthorizeModule_Session.so libAuthorizeModule_Database.so libAuthorizeModule_Protocol.so libAuthorizeModule_Configure.so libAuthorizeModule_Help.so \ - XEngine_AuthorizeApp.exe +# 第三方库模块 +MODULES_THIRD = libjsoncpp.so libXEngine_InfoReport.so libXEngine_Verification.so libXEngine_MSGNotify.so libXEngine_Token.so \ +# 业务模块 + 应用 +MODULES_APP = libAuthorizeModule_Session.so libAuthorizeModule_Database.so libAuthorizeModule_Protocol.so libAuthorizeModule_Configure.so libAuthorizeModule_Help.so \ + XEngine_AuthorizeApp.exe + +# 根据 BUILDTYPE 决定编译目标 +ifeq ($(BUILDTYPE),0) + XENGINE_MODULES = $(MODULES_THIRD) $(MODULES_APP) +else ifeq ($(BUILDTYPE),1) + XENGINE_MODULES = $(MODULES_THIRD) +else ifeq ($(BUILDTYPE),2) + XENGINE_MODULES = $(MODULES_APP) +endif .PHONY:MakeAll MakeAll:$(XENGINE_MODULES) @@ -47,6 +61,18 @@ ifeq ($(FLAGS), InstallAll) else make -C $(DEPEND_VERIFICATION_PATH) PLATFORM=$(PLATFORM) $(FLAGS) endif +libXEngine_MSGNotify.so: +ifeq ($(FLAGS), InstallAll) + cp $(DEPEND_MSGNOTIFY_PATH)/libXEngine_MSGNotify.$(FILEEXT) ../XEngine_Release/ +else + make -C $(DEPEND_MSGNOTIFY_PATH) PLATFORM=$(PLATFORM) $(FLAGS) +endif +libXEngine_Token.so: +ifeq ($(FLAGS), InstallAll) + cp $(DEPEND_TOKEN_PATH)/libXEngine_Token.$(FILEEXT) ../XEngine_Release/ +else + make -C $(DEPEND_TOKEN_PATH) PLATFORM=$(PLATFORM) $(FLAGS) +endif libAuthorizeModule_Session.so: make -C $(AUTH_SESSION_PATH) PLATFORM=$(PLATFORM) UNICODE=$(UNICODE) $(FLAGS) diff --git a/XEngine_Source/XAuth_Protocol.h b/XEngine_Source/XAuth_Protocol.h index 22c1d4d2..f72e3109 100644 --- a/XEngine_Source/XAuth_Protocol.h +++ b/XEngine_Source/XAuth_Protocol.h @@ -81,7 +81,8 @@ typedef struct tag_AuthReg_UserTable XCHAR tszADDInfo[2048]; //附加信息 XCHAR tszLeftTime[64]; //剩余日期 XCHAR tszHardCode[32]; //硬件码 - ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType; //充值卡类型 + __int64u nTimeCount; //在线时间 + ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType; //充值卡类型 ENUM_PROTOCOLDEVICE_TYPE enDeviceType; //设备类型 }AUTHREG_USERTABLE, * LPAUTHREG_USERTABLE; //注册序列号表 @@ -93,6 +94,7 @@ typedef struct tag_AuthReg_SerialTable ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType; //充值卡类型 int bIsUsed; //是否已经使用 XCHAR tszCreateTime[64]; //创建时间 + XCHAR tszCreateUser[64]; //创建用户 XCHAR tszExpiredTime[64]; //过期时间 }AUTHREG_SERIALTABLE, * LPAUTHREG_SERIALTABLE; //网络临时验证表 diff --git a/XEngine_Source/XEngine.sln b/XEngine_Source/XEngine.sln index 33e44b34..396adf12 100644 --- a/XEngine_Source/XEngine.sln +++ b/XEngine_Source/XEngine.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32519.379 +# Visual Studio Version 18 +VisualStudioVersion = 18.7.11911.148 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "XEngine_HDRFile", "XEngine_HDRFile", "{D3A33095-8584-4EFB-9411-EBC38407E7B9}" ProjectSection(SolutionItems) = preProject @@ -38,6 +38,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_AuthorizeService", {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} {AB3DB24C-E1B3-41CF-B2F4-6C12E13C2894} = {AB3DB24C-E1B3-41CF-B2F4-6C12E13C2894} {CB9138DF-789D-459F-AD43-4095B22A487F} = {CB9138DF-789D-459F-AD43-4095B22A487F} + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} = {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} + {E17E889F-D826-413F-854E-DBA6000B4DA7} = {E17E889F-D826-413F-854E-DBA6000B4DA7} {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} EndProjectSection @@ -73,6 +75,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Verification", "XEn {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_MSGNotify", "XEngine_DependLibrary\XEngine_Module\XEngine_MSGNotify\XEngine_MSGNotify.vcxproj", "{E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XEngine_Token", "XEngine_DependLibrary\XEngine_Module\XEngine_Token\XEngine_Token.vcxproj", "{E17E889F-D826-413F-854E-DBA6000B4DA7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -203,6 +209,30 @@ Global {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x64.Build.0 = Release|x64 {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x86.ActiveCfg = Release|Win32 {A8E43EC0-698A-4807-8A61-B2BE5FAB7256}.Release|x86.Build.0 = Release|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|ARM64.Build.0 = Debug|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x64.ActiveCfg = Debug|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x64.Build.0 = Debug|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x86.ActiveCfg = Debug|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Debug|x86.Build.0 = Debug|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|ARM64.ActiveCfg = Release|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|ARM64.Build.0 = Release|ARM64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x64.ActiveCfg = Release|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x64.Build.0 = Release|x64 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x86.ActiveCfg = Release|Win32 + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA}.Release|x86.Build.0 = Release|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|ARM64.Build.0 = Debug|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x64.ActiveCfg = Debug|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x64.Build.0 = Debug|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x86.ActiveCfg = Debug|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Debug|x86.Build.0 = Debug|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|ARM64.ActiveCfg = Release|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|ARM64.Build.0 = Release|ARM64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x64.ActiveCfg = Release|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x64.Build.0 = Release|x64 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x86.ActiveCfg = Release|Win32 + {E17E889F-D826-413F-854E-DBA6000B4DA7}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -213,6 +243,8 @@ Global {F1736B3F-03A2-4FC7-B045-A12BA8D724FB} = {6444F125-63DE-4120-98B3-DF097A9758FA} {F6520D2C-BB8E-45BB-964B-F5D6A4318A89} = {6444F125-63DE-4120-98B3-DF097A9758FA} {A8E43EC0-698A-4807-8A61-B2BE5FAB7256} = {6444F125-63DE-4120-98B3-DF097A9758FA} + {E1087BA3-1074-4C6A-B770-A53B7BA1F4EA} = {6444F125-63DE-4120-98B3-DF097A9758FA} + {E17E889F-D826-413F-854E-DBA6000B4DA7} = {6444F125-63DE-4120-98B3-DF097A9758FA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {E1F1DDE3-8949-41AF-84D6-03CB7CAA03AB} diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp index d59ee7f9..9110928e 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.cpp @@ -35,6 +35,8 @@ void CDialog_Modify::DoDataExchange(CDataExchange* pDX) DDX_Control(pDX, IDC_EDIT7, m_EditHardCode); DDX_Control(pDX, IDC_BUTTON2, m_BtnModify); DDX_Control(pDX, IDC_DATETIMEPICKER1, m_DateTimeRegister); + DDX_Control(pDX, IDC_EDIT9, m_EditUserToken); + DDX_Control(pDX, IDC_EDIT11, m_EditCountTime); } @@ -139,6 +141,8 @@ BOOL CDialog_Modify::OnInitDialog() m_EditUser.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszUserName"].asCString())); m_EditPass.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszUserPass"].asCString())); m_EditEMail.SetWindowText(A2W(st_JsonObject["st_UserInfo"]["tszEMailAddr"].asCString())); + m_EditUserToken.SetWindowText(std::to_wstring(st_JsonObject["st_UserInfo"]["xhToken"].asInt64()).c_str()); + m_EditCountTime.SetWindowText(std::to_wstring(st_JsonObject["st_UserInfo"]["nTimeCount"].asInt64()).c_str()); COleDateTime m_OleDTime; if (m_OleDTime.ParseDateTime(A2W(st_JsonObject["st_UserInfo"]["tszCreateTime"].asCString()))) { @@ -183,6 +187,12 @@ void CDialog_Modify::OnBnClickedButton2() m_EditPass.GetWindowText(m_StrUserInfo); strcpy(st_UserTable.st_UserInfo.tszUserPass, W2A(m_StrUserInfo.GetBuffer())); m_StrUserInfo.ReleaseBuffer(); + m_EditUserToken.GetWindowText(m_StrUserInfo); + st_UserTable.st_UserInfo.xhToken = _ttxoll(W2A(m_StrUserInfo.GetBuffer())); + m_StrUserInfo.ReleaseBuffer(); + m_EditCountTime.GetWindowText(m_StrUserInfo); + st_UserTable.nTimeCount = _ttxoll(W2A(m_StrUserInfo.GetBuffer())); + m_StrUserInfo.ReleaseBuffer(); m_EditEMail.GetWindowText(m_StrUserInfo); strcpy(st_UserTable.st_UserInfo.tszEMailAddr, W2A(m_StrUserInfo.GetBuffer())); m_StrUserInfo.ReleaseBuffer(); @@ -234,11 +244,14 @@ void CDialog_Modify::OnBnClickedButton2() st_JsonUser["tszUserName"] = st_UserTable.st_UserInfo.tszUserName; st_JsonUser["tszUserPass"] = st_UserTable.st_UserInfo.tszUserPass; + st_JsonUser["xhToken"] = st_UserTable.st_UserInfo.xhToken; st_JsonUser["tszEMailAddr"] = st_UserTable.st_UserInfo.tszEMailAddr; st_JsonUser["tszCreateTime"] = st_UserTable.st_UserInfo.tszCreateTime; st_JsonUser["nPhoneNumber"] = st_UserTable.st_UserInfo.nPhoneNumber; st_JsonUser["nIDNumber"] = st_UserTable.st_UserInfo.nIDNumber; st_JsonUser["nUserLevel"] = st_UserTable.st_UserInfo.nUserLevel; + st_JsonUser["nTimeCount"] = st_UserTable.nTimeCount; + st_JsonTable["tszLeftTime"] = st_UserTable.tszLeftTime; st_JsonTable["tszHardCode"] = st_UserTable.tszHardCode; st_JsonTable["enSerialType"] = st_UserTable.enSerialType; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h index c4546bd7..4da3954c 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Modify.h @@ -36,4 +36,6 @@ class CDialog_Modify : public CDialogEx CButton m_BtnModify; afx_msg void OnBnClickedButton3(); CDateTimeCtrl m_DateTimeRegister; + CEdit m_EditUserToken; + CEdit m_EditCountTime; }; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp index db6a8329..8b3b58d6 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_Serial.cpp @@ -53,13 +53,14 @@ BOOL CDialog_Serial::OnInitDialog() CDialogEx::OnInitDialog(); // TODO: 在此添加额外的初始化 - m_ListSerial.InsertColumn(0, _T("使用者"), LVCFMT_LEFT, 100); - m_ListSerial.InsertColumn(1, _T("序列号"), LVCFMT_LEFT, 450); + m_ListSerial.InsertColumn(0, _T("使用者"), LVCFMT_LEFT, 60); + m_ListSerial.InsertColumn(1, _T("序列号"), LVCFMT_LEFT, 350); m_ListSerial.InsertColumn(2, _T("时间/次数"), LVCFMT_LEFT, 90); m_ListSerial.InsertColumn(3, _T("卡类型"), LVCFMT_LEFT, 80); m_ListSerial.InsertColumn(4, _T("是否使用"), LVCFMT_LEFT, 80); - m_ListSerial.InsertColumn(5, _T("创建日期"), LVCFMT_LEFT, 120); - m_ListSerial.InsertColumn(6, _T("过期日期"), LVCFMT_LEFT, 120); + m_ListSerial.InsertColumn(5, _T("创建用户"), LVCFMT_LEFT, 60); + m_ListSerial.InsertColumn(6, _T("创建日期"), LVCFMT_LEFT, 120); + m_ListSerial.InsertColumn(7, _T("过期日期"), LVCFMT_LEFT, 120); m_ListSerial.SetExtendedStyle(LVS_EX_FULLROWSELECT); for (int i = 0; i < 5; i++) @@ -165,8 +166,9 @@ void CDialog_Serial::OnBnClickedButton1() { m_ListSerial.SetItemText(i, 4, _T("未使用")); } - m_ListSerial.SetItemText(i, 5, A2W(st_JsonArray["tszCreateTime"].asCString())); - m_ListSerial.SetItemText(i, 6, A2W(st_JsonArray["tszExpiredTime"].asCString())); + m_ListSerial.SetItemText(i, 5, A2W(st_JsonArray["tszCreateUser"].asCString())); + m_ListSerial.SetItemText(i, 6, A2W(st_JsonArray["tszCreateTime"].asCString())); + m_ListSerial.SetItemText(i, 7, A2W(st_JsonArray["tszExpiredTime"].asCString())); } BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); } diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp index faa5e5b7..fa596672 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/Authorize_Dialog/Dialog_User.cpp @@ -55,13 +55,15 @@ BOOL CDialog_User::OnInitDialog() // TODO: 在此添加额外的初始化 m_ListCtrlClient.InsertColumn(0, _T("序号"), LVCFMT_LEFT, 40); m_ListCtrlClient.InsertColumn(1, _T("用户名"), LVCFMT_LEFT, 120); - m_ListCtrlClient.InsertColumn(2, _T("IP地址"), LVCFMT_LEFT, 100); - m_ListCtrlClient.InsertColumn(3, _T("级别"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(4, _T("在线时间(秒钟)"), LVCFMT_LEFT, 150); - m_ListCtrlClient.InsertColumn(5, _T("剩余时间/过期时间"), LVCFMT_LEFT, 150); - m_ListCtrlClient.InsertColumn(6, _T("充值类型"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(7, _T("设备类型"), LVCFMT_LEFT, 80); - m_ListCtrlClient.InsertColumn(8, _T("是否在线"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(2, _T("TOKEN"), LVCFMT_LEFT, 60); + m_ListCtrlClient.InsertColumn(3, _T("IP地址"), LVCFMT_LEFT, 100); + m_ListCtrlClient.InsertColumn(4, _T("级别"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(5, _T("在线时间(秒钟)"), LVCFMT_LEFT, 150); + m_ListCtrlClient.InsertColumn(6, _T("剩余时间/过期时间"), LVCFMT_LEFT, 150); + m_ListCtrlClient.InsertColumn(7, _T("充值类型"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(8, _T("设备类型"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(9, _T("是否在线"), LVCFMT_LEFT, 80); + m_ListCtrlClient.InsertColumn(10, _T("总在线时长"), LVCFMT_LEFT, 80); m_ListCtrlClient.SetExtendedStyle(LVS_EX_FULLROWSELECT); m_EditFlushTime.SetWindowText(_T("10")); @@ -155,11 +157,12 @@ void CDialog_User::OnBnClickedButton1() m_ListCtrlClient.InsertItem(i, _T("")); m_ListCtrlClient.SetItemText(i, 0, tszIndex); m_ListCtrlClient.SetItemText(i, 1, A2W(st_JsonObject["tszUserName"].asCString())); + m_ListCtrlClient.SetItemText(i, 2, std::to_wstring(st_JsonObject["xhToken"].asInt64()).c_str()); if (!st_JsonArray["tszClientAddr"].isNull()) { - m_ListCtrlClient.SetItemText(i, 2, A2W(st_JsonArray["tszClientAddr"].asCString())); + m_ListCtrlClient.SetItemText(i, 3, A2W(st_JsonArray["tszClientAddr"].asCString())); } - m_ListCtrlClient.SetItemText(i, 3, A2W(lpszXLevelType[st_JsonObject["nUserLevel"].asInt() + 1])); + m_ListCtrlClient.SetItemText(i, 4, A2W(lpszXLevelType[st_JsonObject["nUserLevel"].asInt() + 1])); if (1 == st_JsonObject["nUserState"].asInt()) { @@ -168,12 +171,13 @@ void CDialog_User::OnBnClickedButton1() __int64x nTime = st_JsonArray["nOnlineTime"].asUInt64(); _stprintf(tszTimeStr, _T("%lld"), nTime); - m_ListCtrlClient.SetItemText(i, 4, tszTimeStr); + m_ListCtrlClient.SetItemText(i, 5, tszTimeStr); } - m_ListCtrlClient.SetItemText(i, 5, A2W(st_JsonArray["tszLeftTime"].asCString())); - m_ListCtrlClient.SetItemText(i, 6, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()])); - m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()])); - m_ListCtrlClient.SetItemText(i, 8, lpszStuType[st_JsonObject["nUserState"].asInt()]); + m_ListCtrlClient.SetItemText(i, 6, A2W(st_JsonArray["tszLeftTime"].asCString())); + m_ListCtrlClient.SetItemText(i, 7, A2W(lpszXSerialType[st_JsonArray["enSerialType"].asInt()])); + m_ListCtrlClient.SetItemText(i, 8, A2W(lpszXDevType[st_JsonArray["enDeviceType"].asInt()])); + m_ListCtrlClient.SetItemText(i, 9, lpszStuType[st_JsonObject["nUserState"].asInt()]); + m_ListCtrlClient.SetItemText(i, 10, std::to_wstring(st_JsonObject["nTimeCount"].asInt64()).c_str()); } BaseLib_Memory_FreeCStyle((XPPMEM)&ptszMsgBuffer); UpdateWindow(); diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngineAuthorizeApp.rc b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngineAuthorizeApp.rc index fbb7a2ad..23a539ac 100644 Binary files a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngineAuthorizeApp.rc and b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngineAuthorizeApp.rc differ diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj index 16cc6b90..5b1f6e3d 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeApp/XEngine_AuthorizeApp.vcxproj @@ -37,14 +37,14 @@ Application true - v143 + v145 Unicode Dynamic Application false - v143 + v145 true Unicode Static @@ -52,21 +52,21 @@ Application true - v143 + v145 Unicode Static Application true - v143 + v145 Unicode Static Application false - v143 + v145 true Unicode Static @@ -74,7 +74,7 @@ Application false - v143 + v145 true Unicode Static diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp index f0080dd1..1a8c843e 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_GetTask.cpp @@ -19,8 +19,8 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in memset(tszUserToken, '\0', sizeof(tszUserToken)); BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - AUTHREG_USERTABLE st_UserTable = {}; - if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserTable)) + XENGINE_PROTOCOL_USERINFO st_UserInfo = {}; + if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserInfo)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); @@ -29,17 +29,17 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in } int nListCount = 0; AUTHSESSION_NETCLIENT** ppSt_ListClient; - if (!Session_Authorize_GetClient(&ppSt_ListClient, &nListCount, st_UserTable.st_UserInfo.tszUserName)) + if (!Session_Authorize_GetClient(&ppSt_ListClient, &nListCount, st_UserInfo.tszUserName)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户名:%s,获取时间失败,无法继续,错误:%X"), lpszClientAddr, st_UserTable.st_UserInfo.tszUserName, Session_GetLastError()); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,用户名:%s,获取时间失败,无法继续,错误:%X"), lpszClientAddr, st_UserInfo.tszUserName, Session_GetLastError()); return false; } Protocol_Packet_UserTime(tszSDBuffer, &nSDLen, &ppSt_ListClient, nListCount); BaseLib_Memory_Free((XPPPMEM)&ppSt_ListClient, nListCount); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,用户名:%s,获取时间成功,用户同时在线数:%d"), lpszClientAddr, st_UserTable.st_UserInfo.tszUserName, nListCount); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,用户名:%s,获取时间成功,用户同时在线数:%d"), lpszClientAddr, st_UserInfo.tszUserName, nListCount); } else if (0 == _tcsxncmp(lpszAPIDCode, tszURLValue, _tcsxlen(lpszAPIDCode))) { @@ -58,22 +58,5 @@ bool XEngine_AuthorizeHTTP_GetTask(LPCXSTR lpszClientAddr, XCHAR** pptszList, in XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求获得动态验证码成功,TOKEN:%lld,验证码:%d"), lpszClientAddr, xhToken, nDCode); } - else if (0 == _tcsxncmp(lpszAPINotice, tszURLValue, _tcsxlen(lpszAPINotice))) - { - XCHAR tszUserToken[128]; - memset(tszUserToken, '\0', sizeof(tszUserToken)); - BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - - AUTHREG_USERTABLE st_UserTable = {}; - if (!Session_Token_Get(_ttxoll(tszUserToken), &st_UserTable)) - { - Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); - XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,获取通告失败,无法继续,错误:%X"), lpszClientAddr, Session_GetLastError()); - return false; - } - //http://app.xyry.org:5302/api?function=notice - XEngine_AuthorizeHTTP_Announcement(lpszClientAddr, _X("list"), NULL, 0); - } return true; } \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp index a5fdb8e6..eb5e9def 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Get/AuthorizeHTTP_Token.cpp @@ -18,16 +18,11 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int if (0 == _tcsxncmp(lpszAPILogin, tszURLValue, _tcsxlen(lpszAPILogin))) { //http://app.xyry.org:5302/api?function=login&user=123123aa&pass=123123&device=1 - XCHAR tszUserName[128]; - XCHAR tszUserPass[128]; - XCHAR tszDeviceType[128]; + XCHAR tszUserName[128] = {}; + XCHAR tszUserPass[128] = {}; + XCHAR tszDeviceType[128] = {}; XNETHANDLE xhToken = 0; - AUTHREG_USERTABLE st_UserTable; - - memset(tszUserName, '\0', sizeof(tszUserName)); - memset(tszUserPass, '\0', sizeof(tszUserPass)); - memset(tszDeviceType, '\0', sizeof(tszDeviceType)); - memset(&st_UserTable, '\0', sizeof(AUTHREG_USERTABLE)); + AUTHREG_USERTABLE st_UserTable = {}; if (nListCount < 4) { @@ -111,7 +106,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int { BaseLib_Handle_Create(&xhToken); } - Session_Token_Insert(xhToken, &st_UserTable); + Session_Token_Insert(xhToken, &st_UserTable.st_UserInfo); Protocol_Packet_HttpToken(tszSDBuffer, &nSDLen, xhToken, st_AuthConfig.st_XVerification.nTokenTimeout); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求登录获得TOKEN:%lld 成功,用户级别:%d"), lpszClientAddr, xhToken, st_UserTable.st_UserInfo.nUserLevel); @@ -124,7 +119,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); - if (!Session_Token_UPDate(_ttxoll(tszUserToken))) + if (!Session_Token_UPDateStr(tszUserToken)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "user not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); @@ -143,7 +138,7 @@ bool XEngine_AuthorizeHTTP_Token(LPCXSTR lpszClientAddr, XCHAR** pptszList, int BaseLib_String_GetKeyValue(pptszList[1], "=", tszURLKey, tszUserToken); //主动关闭 - Session_Token_Delete(_ttxoll(tszUserToken)); + Session_Token_DeleteStr(tszUserToken); Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求关闭TOKEN:%s 成功"), lpszClientAddr, tszUserToken); diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp index 308baf15..17dff3ab 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.cpp @@ -1,6 +1,15 @@ #include "../Authorize_Hdr.h" -bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen) +// Handle HTTP serial-number related APIs. +// Supported operations: +// 1) list : query serials by page/range and return packed HTTP response. +// 2) delete : parse serial list from request and delete each entry. +// 3) insert : parse and insert serial entries (handled in the insert branch below). +// Notes: +// - Database backend is selected by st_AuthConfig.st_XSql.nDBType. +// - Response data is sent back through XEngine_Client_TaskSend. +// - Dynamically allocated parse/query buffers must be released after use. +bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszClientUser, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen) { int nSDLen = 0; LPCXSTR lpszAPIList = _X("list"); @@ -8,6 +17,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L LPCXSTR lpszAPIDelete = _X("delete"); CHttpMemory_PoolEx m_MemoryPool(XENGINE_MEMORY_SIZE_MAX); + // list: parse paging range, query DB, package list response, then return to client. if (0 == _tcsxncmp(lpszAPIList, lpszAPIName, _tcsxlen(lpszAPIList))) { int nPosStart = 0; @@ -20,6 +30,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L } memset(ptszMsgBuffer, '\0', XENGINE_MEMORY_SIZE_MAX); + // Read list window from HTTP payload and limit single request size. Protocol_Parse_HttpParsePos(lpszMsgBuffer, nMsgLen, &nPosStart, &nPosEnd); if ((nPosEnd - nPosStart) > 100) { @@ -44,6 +55,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L ptszMsgBuffer = NULL; XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求序列号列表成功,个数:%d"), lpszClientAddr, nListCount); } + // delete: parse requested serials and delete one-by-one in configured DB backend. else if (0 == _tcsxncmp(lpszAPIDelete, lpszAPIName, _tcsxlen(lpszAPIDelete))) { int nListCount = 0; @@ -64,11 +76,13 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L DBModule_MySQL_SerialDelete(ppSt_SerialTable[i]->tszSerialNumber); } } + // Release parsed serial table and return common success response. BaseLib_Memory_Free((XPPPMEM)&ppSt_SerialTable, nListCount); Protocol_Packet_HttpComm(m_MemoryPool.get(), &nSDLen); XEngine_Client_TaskSend(lpszClientAddr, m_MemoryPool.get(), nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,请求删除序列号成功,删除个数:%d"), lpszClientAddr, nListCount); } + // insert: parse and insert serial data, then reply to client (implementation below). else if (0 == _tcsxncmp(lpszAPIInsert, lpszAPIName, _tcsxlen(lpszAPIInsert))) { int nSerialCount = 0; @@ -90,6 +104,7 @@ bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, L _tcsxcpy(st_SerialTable.tszCreateTime, tszCreateTime); _tcsxcpy(st_SerialTable.tszExpiredTime, tszExpiredTime); _tcsxcpy(st_SerialTable.tszMaxTime, tszMaxTime); + _tcsxcpy(st_SerialTable.tszCreateUser, lpszClientUser); Verification_XAuthKey_KeySerial(st_SerialTable.tszSerialNumber, nFieldCount, 0); if (0 == st_AuthConfig.st_XSql.nDBType) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h index c8aca15f..95af13a7 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_Serial.h @@ -1,3 +1,3 @@ #pragma once -bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen); \ No newline at end of file +bool XEngine_AuthorizeHTTP_Serial(LPCXSTR lpszClientAddr, LPCXSTR lpszClientUser, LPCXSTR lpszAPIName, LPCXSTR lpszMsgBuffer, int nMsgLen); \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp index 2d148832..88f20abf 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/AuthorizeHTTP_Post/AuthorizeHTTP_User.cpp @@ -156,11 +156,8 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX } else if (0 == _tcsxncmp(lpszAPIName, lpszAPIPay, _tcsxlen(lpszAPIName))) { - AUTHREG_PROTOCOL_USERPAY st_UserPay; - AUTHREG_USERTABLE st_UserInfo; - - memset(&st_UserInfo, '\0', sizeof(AUTHREG_USERTABLE)); - memset(&st_UserPay, '\0', sizeof(AUTHREG_PROTOCOL_USERPAY)); + AUTHREG_PROTOCOL_USERPAY st_UserPay = {}; + AUTHREG_USERTABLE st_UserInfo = {}; if (!st_FunSwitch.bSwitchPay) { @@ -176,7 +173,7 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_NOTFOUND, "serial number not found"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,充值序列卡:%s 不存在!"), lpszClientAddr, st_SerialTable.tszSerialNumber); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,充值序列卡:%s 不存在!"), lpszClientAddr, st_UserPay.tszSerialNumber); return false; } if (_tcsxlen(st_SerialTable.tszExpiredTime) > 1) @@ -189,7 +186,7 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_EXPIRED, "serial was expired"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,序列卡:%s 已经过期!"), lpszClientAddr, st_SerialTable.tszSerialNumber); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,充值失败,序列卡:%s 已经过期!"), lpszClientAddr, st_UserPay.tszSerialNumber); return false; } } @@ -221,6 +218,23 @@ bool XEngine_AuthorizeHTTP_User(XNETHANDLE xhToken, LPCXSTR lpszClientAddr, LPCX Session_Authorize_SetUser(&st_UserInfo); Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); + + if (st_AuthConfig.st_XNotify.st_EMailNotify.bEnable) + { + LPCXSTR lpszSubject = _X("XEngine_AuthorizeService User Pay notify!"); + XCHAR tszPayload[1024] = {}; + XCHAR tszTimeStr[128] = {}; + BaseLib_Time_TimeToStr(tszTimeStr); + _xstprintf(tszPayload, _X("http client:%s ,user name:%s ,user pay serial number:%s time on %s"), lpszClientAddr, st_UserPay.tszUserName, st_UserPay.tszSerialNumber, tszTimeStr); + if (MSGNotify_EMail_Send(st_AuthConfig.st_XNotify.st_EMailNotify.tszServiceAddr, st_AuthConfig.st_XNotify.st_EMailNotify.tszUser, st_AuthConfig.st_XNotify.st_EMailNotify.tszPass, st_AuthConfig.st_XNotify.st_EMailNotify.tszSendAddr, lpszSubject, tszPayload)) + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,消息通知发送成功"), lpszClientAddr); + } + else + { + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,消息通知发送失败,错误:%lX"), lpszClientAddr, MSGNotify_GetLastError()); + } + } XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_NOTICE, _X("HTTP客户端:%s,用户名:%s,充值成功,序列号:%s"), lpszClientAddr, st_UserPay.tszUserName, st_UserPay.tszSerialNumber); } else if (0 == _tcsxncmp(lpszAPIName, lpszAPIPass, _tcsxlen(lpszAPIName))) diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h index 150c60d5..c36870ca 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Hdr.h @@ -52,6 +52,10 @@ using namespace std; #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport/InfoReport_Error.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Define.h" #include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification/Verification_Error.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify/MSGNotify_Define.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify/MSGNotify_Error.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Token/Session_Define.h" +#include "../../XEngine_DependLibrary/XEngine_Module/XEngine_Token/Session_Error.h" #include "../../XAuth_Protocol.h" #include "../../AuthorizeModule_Configure/Config_Define.h" #include "../../AuthorizeModule_Configure/Config_Error.h" @@ -133,6 +137,8 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../x64/Debug/AuthorizeModule_Help.lib") #pragma comment(lib,"../../x64/Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../x64/Debug/XEngine_Verification.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../x64/Debug/XEngine_Token.lib") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Protocol.lib") @@ -141,6 +147,8 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../ARM64/Debug/AuthorizeModule_Help.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../ARM64/Debug/XEngine_Verification.lib") +#pragma comment(lib,"../../ARM64/Debug/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../ARM64/Debug/XEngine_Token.lib") #elif _M_IX86 #pragma comment(lib,"../../Debug/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../Debug/AuthorizeModule_Protocol.lib") @@ -149,6 +157,8 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../Debug/AuthorizeModule_Help.lib") #pragma comment(lib,"../../Debug/XEngine_InfoReport.lib") #pragma comment(lib,"../../Debug/XEngine_Verification.lib") +#pragma comment(lib,"../../Debug/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../Debug/XEngine_Token.lib") #endif #else #ifdef _M_X64 @@ -159,6 +169,8 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../x64/Release/AuthorizeModule_Help.lib") #pragma comment(lib,"../../x64/Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../x64/Release/XEngine_Verification.lib") +#pragma comment(lib,"../../x64/Release/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../x64/Release/XEngine_Token.lib") #elif _M_ARM64 #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Protocol.lib") @@ -167,6 +179,8 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../ARM64/Release/AuthorizeModule_Help.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../ARM64/Release/XEngine_Verification.lib") +#pragma comment(lib,"../../ARM64/Release/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../ARM64/Release/XEngine_Token.lib") #elif _M_IX86 #pragma comment(lib,"../../Release/AuthorizeModule_Configure.lib") #pragma comment(lib,"../../Release/AuthorizeModule_Protocol.lib") @@ -175,6 +189,8 @@ extern XENGINE_FUNCTIONSWITCH st_FunSwitch; #pragma comment(lib,"../../Release/AuthorizeModule_Help.lib") #pragma comment(lib,"../../Release/XEngine_InfoReport.lib") #pragma comment(lib,"../../Release/XEngine_Verification.lib") +#pragma comment(lib,"../../Release/XEngine_MSGNotify.lib") +#pragma comment(lib,"../../Release/XEngine_Token.lib") #endif #endif #endif \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp index 411c9b3a..79228126 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_HttpTask.cpp @@ -208,7 +208,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int //得到TOKEN if (Protocol_Parse_HttpParseToken(lpszMsgBuffer, nMsgLen, &xhToken)) { - if (!Session_Token_Get(xhToken, &st_UserTable)) + if (!Session_Token_Get(xhToken, &st_UserTable.st_UserInfo)) { Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "Unauthorized"); XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); @@ -238,7 +238,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求的API:%s 失败,因为TOKEN权限不足"), lpszClientAddr, pSt_HTTPParament->tszHttpUri); return false; } - XEngine_AuthorizeHTTP_Serial(lpszClientAddr, tszAPIName, lpszMsgBuffer, nMsgLen); + XEngine_AuthorizeHTTP_Serial(lpszClientAddr, st_UserTable.st_UserInfo.tszUserName, tszAPIName, lpszMsgBuffer, nMsgLen); } else if (0 == _tcsxncmp(lpszAPIVerSwitch, tszAPIVer, _tcsxlen(lpszAPIVerSwitch))) { @@ -269,10 +269,13 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int //验证权限 if (0 != st_UserTable.st_UserInfo.nUserLevel) { - Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "permission is failed"); - XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求的API:%s 失败,因为TOKEN权限不足"), lpszClientAddr, pSt_HTTPParament->tszHttpUri); - return false; + if (0 != _tcsxncmp(_X("list"), tszAPIName, 4)) + { + Protocol_Packet_HttpComm(tszSDBuffer, &nSDLen, ERROR_AUTHORIZE_PROTOCOL_UNAUTHORIZE, "permission is failed"); + XEngine_Client_TaskSend(lpszClientAddr, tszSDBuffer, nSDLen, XENGINE_AUTH_APP_NETTYPE_HTTP); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP客户端:%s,请求的API:%s 失败,因为TOKEN权限不足"), lpszClientAddr, pSt_HTTPParament->tszHttpUri); + return false; + } } XEngine_AuthorizeHTTP_Announcement(lpszClientAddr, tszAPIName, lpszMsgBuffer, nMsgLen); } @@ -327,7 +330,6 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int LPCXSTR lpszFuncName = _X("api"); LPCXSTR lpszAPIVerDCode = _X("dcode"); LPCXSTR lpszAPIVerTime = _X("time"); - LPCXSTR lpszAPIVerNotice = _X("notice"); memset(tszUrlName, '\0', sizeof(tszUrlName)); HttpProtocol_ServerHelp_GetParament(pSt_HTTPParament->tszHttpUri, &pptszList, &nListCount, tszUrlName); @@ -346,8 +348,7 @@ bool XEngine_Client_HttpTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int memset(tszURLValue, '\0', sizeof(tszURLValue)); BaseLib_String_GetKeyValue(pptszList[0], "=", tszURLKey, tszURLValue); - if (0 == _tcsxncmp(lpszAPIVerDCode, tszURLValue, _tcsxlen(lpszAPIVerDCode)) || 0 == _tcsxncmp(lpszAPIVerTime, tszURLValue, _tcsxlen(lpszAPIVerTime)) || - 0 == _tcsxncmp(lpszAPIVerNotice, tszURLValue, _tcsxlen(lpszAPIVerNotice))) + if (0 == _tcsxncmp(lpszAPIVerDCode, tszURLValue, _tcsxlen(lpszAPIVerDCode)) || 0 == _tcsxncmp(lpszAPIVerTime, tszURLValue, _tcsxlen(lpszAPIVerTime))) { XEngine_AuthorizeHTTP_GetTask(lpszClientAddr, pptszList, nListCount); } diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp index 204ecb90..3386eeda 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Net.cpp @@ -161,6 +161,15 @@ bool XEngine_CloseClient(LPCXSTR lpszClientAddr, int nLeaveType) _tcsxcpy(st_AuthTime.tszLeftTime, st_NETClient.tszLeftTime); _tcsxcpy(st_AuthTime.tszUserAddr, st_NETClient.tszClientAddr); + if (0 == st_AuthConfig.st_XSql.nDBType) + { + DBModule_SQLite_UserTime(st_NETClient.st_UserTable.st_UserInfo.tszUserName, st_NETClient.nOnlineTime); + } + else + { + DBModule_MySQL_UserTime(st_NETClient.st_UserTable.st_UserInfo.tszUserName, st_NETClient.nOnlineTime); + } + if (st_AuthConfig.st_XLogin.bPassAuth) { int nSDLen = 0; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp index e5b8d274..e6ef312d 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_TCPTask.cpp @@ -381,7 +381,7 @@ bool XEngine_Client_TCPTask(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n } if (st_FunSwitch.bSwitchTokenLogin) { - Session_Token_Insert(pSt_ProtocolHdr->xhToken, &st_UserTable); + Session_Token_Insert(pSt_ProtocolHdr->xhToken, &st_UserTable.st_UserInfo); } //记录每次登陆 XCHAR tszIPAddr[128] = {}; diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp index ab1114bf..1917b6e0 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.cpp @@ -61,19 +61,18 @@ void XCALLBACK XEngine_TaskEvent_Client(LPCXSTR lpszUserAddr, LPCXSTR lpszUserNa DBModule_MySQL_UserLeave(&st_AuthTime); } } -void XCALLBACK XEngine_TaskEvent_Token(XNETHANDLE xhToken, XPVOID lParam) +void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int nTimerenewal, XENGINE_LIBTIME* pSt_LibTime, XENGINE_PROTOCOL_USERINFO* pSt_UserInfo, XPVOID lParam) { bool bRemove = true; - AUTHREG_USERTABLE st_UserTable; - memset(&st_UserTable, '\0', sizeof(AUTHREG_USERTABLE)); + XENGINE_PROTOCOL_USERINFO st_UserInfo; - Session_Token_Get(xhToken, &st_UserTable); + Session_Token_GetStr(lpszTokenStr, &st_UserInfo); //自动续期? if (st_AuthConfig.st_XVerification.st_XToken.bAutoRenewal) { int nRenewalTime = 0; - Session_Token_RenewalTime(xhToken, &nRenewalTime); - + Session_Token_UPDateStr(lpszTokenStr); + Session_Token_GetTimeRenewalStr(lpszTokenStr, &nRenewalTime); if (-1 == st_AuthConfig.st_XVerification.st_XToken.nRenewalTime) { bRemove = false; @@ -89,7 +88,7 @@ void XCALLBACK XEngine_TaskEvent_Token(XNETHANDLE xhToken, XPVOID lParam) if (bRemove) { - Session_Token_Delete(xhToken); - XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%lld,用户名:%s,已经超时,权限级别:%d,被移除服务器"), xhToken, st_UserTable.st_UserInfo.tszUserName, st_UserTable.st_UserInfo.nUserLevel); + Session_Token_DeleteStr(lpszTokenStr); + XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Token:%s,用户名:%s,已经超时,权限级别:%d,被移除服务器"), lpszTokenStr, st_UserInfo.tszUserName, st_UserInfo.nUserLevel); } } \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h index c71acacd..84c11e56 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Authorize_Task.h @@ -1,4 +1,4 @@ #pragma once void XCALLBACK XEngine_TaskEvent_Client(LPCXSTR lpszUserAddr, LPCXSTR lpszUserName, __int64x nOnlineTimer, __int64x nLeftTimer, LPCXSTR lpszLeftDate, ENUM_VERIFICATION_MODULE_SERIAL_TYPE enSerialType, ENUM_PROTOCOLDEVICE_TYPE enDeviceType, int nNetType, XPVOID lParam); -void XCALLBACK XEngine_TaskEvent_Token(XNETHANDLE xhToken, XPVOID lParam); \ No newline at end of file +void XCALLBACK XEngine_TaskEvent_Token(LPCXSTR lpszTokenStr, int nTimeout, int nTimerenewal, XENGINE_LIBTIME* pSt_LibTime, XENGINE_PROTOCOL_USERINFO* pSt_UserInfo, XPVOID lParam); \ No newline at end of file diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile index 386b47b1..b3816500 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/Makefile @@ -3,9 +3,9 @@ PLATVER = FILEEXT = LIBFLAG = LOADHDR = -I ./ -LOADSO = -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification \ +LOADSO = -L ../../XEngine_DependLibrary/XEngine_Module/jsoncpp -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_InfoReport -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Verification -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_MSGNotify -L ../../XEngine_DependLibrary/XEngine_Module/XEngine_Token \ -L ../../AuthorizeModule_Session -L ../../AuthorizeModule_Database -L ../../AuthorizeModule_Protocol -L ../../AuthorizeModule_Configure -L ../../AuthorizeModule_Help -L ../../AuthorizeModule_CDKey -LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification \ +LIB = -lXEngine_InfoReport -ljsoncpp -lXEngine_Verification -lXEngine_MSGNotify -lXEngine_Token \ -lXEngine_BaseLib -lXEngine_Algorithm -lXEngine_Core -lXEngine_ManagePool -lXEngine_Cryption -lXClient_APIHelp -lNetHelp_APIAddr -lHelpComponents_Packets -lHelpComponents_DataBase -lHelpComponents_XLog -lRfcComponents_WSProtocol -lRfcComponents_HttpProtocol -lRfcComponents_MQTTProtocol -lXEngine_SystemApi \ -lAuthorizeModule_Session -lAuthorizeModule_Database -lAuthorizeModule_Protocol -lAuthorizeModule_Configure -lAuthorizeModule_Help LIBEX = diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp index 1cde9f1d..c4010b5a 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.cpp @@ -126,14 +126,31 @@ LONG WINAPI Coredump_ExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers) return EXCEPTION_EXECUTE_HANDLER; } #endif +/** + * @brief Authorize service process entry point. + * + * This function coordinates the full service lifecycle: + * 1) platform/runtime bootstrap (network stack, locale, crash handler), + * 2) configuration and parameter handling, + * 3) initialization of logging, protocol stacks, and worker components, + * 4) service run loop and signal-controlled shutdown, + * 5) orderly release of all allocated resources. + * + * Notes: + * - Platform-specific startup paths are guarded by compile-time macros. + * - Error paths return early to avoid continuing in a partially initialized state. + */ int main(int argc, char** argv) { #ifdef _WINDOWS + // Initialize Winsock for all subsequent socket-based modules. WSADATA st_WSAData; WSAStartup(MAKEWORD(2, 2), &st_WSAData); + // Register unhandled exception filter to generate a dump file on crash. SetUnhandledExceptionFilter(Coredump_ExceptionFilter); #ifndef _DEBUG + // Ensure UTF-8 locale in release builds for consistent text processing/logging. if (setlocale(LC_ALL, ".UTF8") == NULL) { fprintf(stderr, "Error setting locale.\n"); @@ -226,7 +243,7 @@ int main(int argc, char** argv) goto XENGINE_EXITAPP; } XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,初始化会话客户端服务成功")); - if (!Session_Token_Init(st_AuthConfig.st_XVerification.nTokenTimeout, XEngine_TaskEvent_Token)) + if (!Session_Token_Init(st_AuthConfig.st_XVerification.nTokenTimeout, true, XEngine_TaskEvent_Token)) { XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,初始化会话TOKEN服务失败,错误:%lX"), Session_GetLastError()); goto XENGINE_EXITAPP; @@ -452,6 +469,7 @@ int main(int argc, char** argv) //一个简单的示例,没有验证硬件码 if (Verification_XAuthKey_FileRead(&st_AuthLocal, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyFile, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyPass)) { + Verification_XAuthKey_KeyParse(&st_AuthLocal); Verification_XAuthKey_FileWrite(&st_AuthLocal, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyFile, st_AuthConfig.st_XVerification.st_XCDKey.tszKeyPass); XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,授权文件验证成功,总可运行次数:%s,剩余可运行次数:%lld"), st_AuthLocal.st_AuthRegInfo.tszLeftTime, st_AuthLocal.st_AuthRegInfo.nHasTime); } diff --git a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj index bdd8488b..f5d112df 100644 --- a/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj +++ b/XEngine_Source/XEngine_APPService/XEngine_AuthorizeService/XEngine_AuthorizeService.vcxproj @@ -37,39 +37,39 @@ Application true - v143 + v145 Unicode Application false - v143 + v145 true Unicode Application true - v143 + v145 MultiByte Application true - v143 + v145 MultiByte Application false - v143 + v145 true Unicode Application false - v143 + v145 true Unicode diff --git a/XEngine_Source/XEngine_DependLibrary b/XEngine_Source/XEngine_DependLibrary index 207abe8b..237be589 160000 --- a/XEngine_Source/XEngine_DependLibrary +++ b/XEngine_Source/XEngine_DependLibrary @@ -1 +1 @@ -Subproject commit 207abe8b617744e35bf1438a03536d898ddc93fd +Subproject commit 237be589ec33bba0bf3405c095db470c1d3766b3