diff --git a/.github/workflows/jennyexample.yaml b/.github/workflows/jennyexample.yaml new file mode 100644 index 0000000000..ae34222c97 --- /dev/null +++ b/.github/workflows/jennyexample.yaml @@ -0,0 +1,247 @@ +name: Snyk Security Scan for NX Monorepo + +on: + pull_request: + branches: [ main, master, develop ] + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + security-events: write + checks: write + +jobs: + snyk-scan: + runs-on: ubuntu-latest + name: Snyk Security Scan + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install NX CLI + run: npm install -g @nrwl/cli + + - name: Setup Snyk CLI + uses: snyk/actions/setup@master + + - name: Authenticate Snyk + run: snyk auth ${{ secrets.SNYK_TOKEN }} + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + + - name: Run Snyk Open Source Scan + id: snyk-open-source + run: | + echo "## 🔍 Snyk Open Source Vulnerability Scan Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Create output file for open source scan + OPEN_SOURCE_OUTPUT=$(mktemp) + + # Run Snyk test for all projects in the monorepo + if snyk test --all-projects --detection-depth=6 --json > "$OPEN_SOURCE_OUTPUT" 2>&1; then + echo "✅ No open source vulnerabilities found" >> $GITHUB_STEP_SUMMARY + echo "open_source_status=success" >> $GITHUB_OUTPUT + else + echo "❌ Open source vulnerabilities detected" >> $GITHUB_STEP_SUMMARY + echo "open_source_status=failure" >> $GITHUB_OUTPUT + + # Parse and format the JSON output for better readability + if command -v jq &> /dev/null; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Vulnerability Summary:" >> $GITHUB_STEP_SUMMARY + jq -r '.vulnerabilities[] | "- **\(.title)** (Severity: \(.severity | ascii_upcase)) in \(.packageName)@\(.version)"' "$OPEN_SOURCE_OUTPUT" | head -20 >> $GITHUB_STEP_SUMMARY || true + + # Add remediation advice + echo "" >> $GITHUB_STEP_SUMMARY + echo "### 💡 Remediation Advice:" >> $GITHUB_STEP_SUMMARY + jq -r '.vulnerabilities[] | select(.upgradePath != null and .upgradePath != []) | "- Upgrade \(.packageName) to version \(.upgradePath[-1])"' "$OPEN_SOURCE_OUTPUT" | sort -u | head -10 >> $GITHUB_STEP_SUMMARY || true + else + cat "$OPEN_SOURCE_OUTPUT" >> $GITHUB_STEP_SUMMARY + fi + fi + + # Save output for PR comment + cp "$OPEN_SOURCE_OUTPUT" open_source_results.json + continue-on-error: true + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + + - name: Run Snyk Code Scan + id: snyk-code + run: | + echo "" >> $GITHUB_STEP_SUMMARY + echo "## 🔍 Snyk Code Security Scan Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Create output file for code scan + CODE_OUTPUT=$(mktemp) + + # Run Snyk code test for the entire repository + if snyk code test --json > "$CODE_OUTPUT" 2>&1; then + echo "✅ No code security issues found" >> $GITHUB_STEP_SUMMARY + echo "code_status=success" >> $GITHUB_OUTPUT + else + echo "❌ Code security issues detected" >> $GITHUB_STEP_SUMMARY + echo "code_status=failure" >> $GITHUB_OUTPUT + + # Parse and format the JSON output for better readability + if command -v jq &> /dev/null; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Security Issues Summary:" >> $GITHUB_STEP_SUMMARY + jq -r '.runs[0].results[]? | "- **\(.ruleId)** (Severity: \(.level | ascii_upcase)) in \(.locations[0].physicalLocation.artifactLocation.uri):\(.locations[0].physicalLocation.region.startLine)"' "$CODE_OUTPUT" | head -20 >> $GITHUB_STEP_SUMMARY || true + + # Add remediation advice for code issues + echo "" >> $GITHUB_STEP_SUMMARY + echo "### 💡 Code Security Recommendations:" >> $GITHUB_STEP_SUMMARY + jq -r '.runs[0].results[]? | "- \(.message.text) (File: \(.locations[0].physicalLocation.artifactLocation.uri))"' "$CODE_OUTPUT" | head -10 >> $GITHUB_STEP_SUMMARY || true + else + cat "$CODE_OUTPUT" >> $GITHUB_STEP_SUMMARY + fi + fi + + # Save output for PR comment + cp "$CODE_OUTPUT" code_results.json + continue-on-error: true + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + + - name: Install jq for JSON parsing + if: steps.snyk-open-source.outputs.open_source_status == 'failure' || steps.snyk-code.outputs.code_status == 'failure' + run: sudo apt-get update && sudo apt-get install -y jq + + - name: Create PR Comment with Results + if: always() + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + let comment = '## 🛡️ Snyk Security Scan Results\n\n'; + + // Read open source results + let openSourceStatus = '${{ steps.snyk-open-source.outputs.open_source_status }}'; + let codeStatus = '${{ steps.snyk-code.outputs.code_status }}'; + + // Open Source Results + comment += '### 📦 Open Source Dependencies\n'; + if (openSourceStatus === 'success') { + comment += '✅ No vulnerabilities found in open source dependencies\n\n'; + } else { + comment += '❌ Vulnerabilities found in open source dependencies\n\n'; + + try { + const openSourceData = fs.readFileSync('open_source_results.json', 'utf8'); + const openSourceJson = JSON.parse(openSourceData); + + if (openSourceJson.vulnerabilities && openSourceJson.vulnerabilities.length > 0) { + comment += '#### Top Vulnerabilities:\n'; + openSourceJson.vulnerabilities.slice(0, 5).forEach(vuln => { + comment += `- **${vuln.title}** (${vuln.severity.toUpperCase()}) in ${vuln.packageName}@${vuln.version}\n`; + }); + comment += '\n'; + + // Add upgrade recommendations + const upgrades = openSourceJson.vulnerabilities + .filter(v => v.upgradePath && v.upgradePath.length > 0) + .slice(0, 3); + + if (upgrades.length > 0) { + comment += '#### 💡 Recommended Upgrades:\n'; + upgrades.forEach(vuln => { + comment += `- Upgrade ${vuln.packageName} to ${vuln.upgradePath[vuln.upgradePath.length - 1]}\n`; + }); + comment += '\n'; + } + } + } catch (e) { + comment += 'Error parsing open source scan results\n\n'; + } + } + + // Code Security Results + comment += '### 🔒 Code Security\n'; + if (codeStatus === 'success') { + comment += '✅ No code security issues found\n\n'; + } else { + comment += '❌ Code security issues found\n\n'; + + try { + const codeData = fs.readFileSync('code_results.json', 'utf8'); + const codeJson = JSON.parse(codeData); + + if (codeJson.runs && codeJson.runs[0] && codeJson.runs[0].results) { + comment += '#### Top Security Issues:\n'; + codeJson.runs[0].results.slice(0, 5).forEach(result => { + const location = result.locations[0].physicalLocation; + comment += `- **${result.ruleId}** (${result.level.toUpperCase()}) in ${location.artifactLocation.uri}:${location.region.startLine}\n`; + comment += ` ${result.message.text}\n`; + }); + comment += '\n'; + } + } catch (e) { + comment += 'Error parsing code scan results\n\n'; + } + } + + // Overall status + const overallStatus = (openSourceStatus === 'success' && codeStatus === 'success') ? 'success' : 'failure'; + + if (overallStatus === 'success') { + comment += '### ✅ Overall Status: PASSED\nNo security vulnerabilities detected in this PR.\n'; + } else { + comment += '### ❌ Overall Status: FAILED\nSecurity vulnerabilities detected. Please review and address the issues above.\n'; + } + + comment += '\n---\n*Powered by [Snyk](https://snyk.io) 🐍*'; + + // Post comment + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + + - name: Set Check Status + if: always() + uses: actions/github-script@v7 + with: + script: | + const openSourceStatus = '${{ steps.snyk-open-source.outputs.open_source_status }}'; + const codeStatus = '${{ steps.snyk-code.outputs.code_status }}'; + const overallStatus = (openSourceStatus === 'success' && codeStatus === 'success') ? 'success' : 'failure'; + + await github.rest.checks.create({ + owner: context.repo.owner, + repo: context.repo.repo, + name: 'Snyk Security Scan', + head_sha: context.payload.pull_request.head.sha, + status: 'completed', + conclusion: overallStatus, + output: { + title: overallStatus === 'success' ? 'Security scan passed' : 'Security vulnerabilities found', + summary: overallStatus === 'success' + ? 'No security vulnerabilities detected in open source dependencies or code.' + : 'Security vulnerabilities detected. Check the PR comment for details.' + } + }); + + - name: Fail if vulnerabilities found + if: steps.snyk-open-source.outputs.open_source_status == 'failure' || steps.snyk-code.outputs.code_status == 'failure' + run: | + echo "Security vulnerabilities detected. Please review the scan results." + exit 1 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..19345782c4 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,104 @@ +name: Snyk Security Scan with Summary + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + snyk_scan: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + # 1. Setup Java for the Maven project (Required to resolve inter-module dependencies) + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: 'maven' + + # 1.1 Add Maven Install Step (Crucial fix for your initial dependency errors) + - name: Maven Build and Install + run: mvn -B install -DskipTests + + # 2. Install Snyk CLI on the runner + - name: Install Snyk CLI + uses: snyk/actions/setup@master + + # 3. Run Snyk Test (Open Source, Code, & Container) and save JSON + # We pipe the JSON output to a file. + - name: Run Snyk Test and save JSON + id: snyk_test + # Set continue-on-error: true here to ensure the summary step runs even if issues are found + continue-on-error: true + run: snyk test --all-projects --json > snyk-results.json + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + + # 4. Process Snyk JSON and create Job Summary Table + - name: Generate Security Summary Table + run: | + # Install jq for JSON processing + if ! command -v jq &> /dev/null; then + sudo apt-get update && sudo apt-get install jq -y + fi + + # Check if the Snyk output file exists and has content (handles empty runs) + SNYK_FILE="snyk-results.json" + if [ ! -s "$SNYK_FILE" ]; then + echo "## ⚠️ Snyk Test Summary: No results file found or was empty." >> $GITHUB_STEP_SUMMARY + echo "Skipping summary generation." >> $GITHUB_STEP_SUMMARY + exit 0 + fi + + # Count vulnerabilities by severity across ALL projects in the JSON array + HIGH_COUNT=$(jq -r ' + [ + .[] | .vulnerabilities[] | select(.severity == "critical" or .severity == "high") + ] | length' "$SNYK_FILE") + + MEDIUM_COUNT=$(jq -r ' + [ + .[] | .vulnerabilities[] | select(.severity == "medium") + ] | length' "$SNYK_FILE") + + LOW_COUNT=$(jq -r ' + [ + .[] | .vulnerabilities[] | select(.severity == "low") + ] | length' "$SNYK_FILE") + + TOTAL_ISSUES=$((HIGH_COUNT + MEDIUM_COUNT + LOW_COUNT)) + + # Determine the overall status emoji + STATUS_EMOJI="✅" + if [ "$HIGH_COUNT" -gt 0 ] || [ "$MEDIUM_COUNT" -gt 0 ]; then + STATUS_EMOJI="❌" + elif [ "$TOTAL_ISSUES" -gt 0 ]; then + STATUS_EMOJI="⚠️" # Yellow for only low-severity + fi + + # Construct the Markdown table and write to the job summary + SUMMARY_MARKDOWN=$(cat <<-EOF + + ### Snyk Security Scan Summary ${STATUS_EMOJI} + + | Metric | Status | Count | + | :--- | :---: | :---: | + | **Total Vulnerabilities** | ${STATUS_EMOJI} | **${TOTAL_ISSUES}** | + | Critical/High Severity | ❌ | ${HIGH_COUNT} | + | Medium Severity | ⚠️ | ${MEDIUM_COUNT} | + | Low Severity | ⚪ | ${LOW_COUNT} | + +
+ + > For full vulnerability details by project, please check the logs of the \`Run Snyk Test and save JSON\` step. + + EOF + ) + + # Append the generated summary to the $GITHUB_STEP_SUMMARY file + echo "$SUMMARY_MARKDOWN" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/snyk-security.yml b/.github/workflows/snyk-security.yml new file mode 100644 index 0000000000..983d816c0b --- /dev/null +++ b/.github/workflows/snyk-security.yml @@ -0,0 +1,104 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# A sample workflow which sets up Snyk to analyze the full Snyk platform (Snyk Open Source, Snyk Code, +# Snyk Container and Snyk Infrastructure as Code) +# The setup installs the Snyk CLI - for more details on the possible commands +# check https://docs.snyk.io/snyk-cli/cli-reference +# The results of Snyk Code are then uploaded to GitHub Security Code Scanning +# +# In order to use the Snyk Action you will need to have a Snyk API token. +# More details in https://github.com/snyk/actions#getting-your-snyk-token +# or you can signup for free at https://snyk.io/login +# +# For more examples, including how to limit scans to only high-severity issues +# and fail PR checks, see https://github.com/snyk/actions/ + + +name: Snyk Security + +on: + push: + branches: ["main" ] + pull_request: + branches: ["main"] + +permissions: + contents: read + packages: write + +jobs: + snyk: + env: + # This is where you will need to introduce the Snyk API token created with your Snyk account + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + permissions: + contents: write # for actions/checkout to fetch code and write bumped version back + packages: write + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + runs-on: ubuntu-latest + steps: + - name: checkout code + uses: actions/checkout@v4 + + - name: setup jdk 8 + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 8 + server-id: github # Value of the distributionManagement/repository/id field of the pom.xml + settings-path: ${{ github.workspace }} # location for the settings.xml file + + - name: unit tests + run: mvn -B test --file pom.xml + + - name: build the app + run: | + mvn clean + mvn -B install --file pom.xml + + - name: Set up Snyk CLI to check for security issues + # Snyk can be used to break the build when it detects security issues. + # In this case we want to upload the SAST issues to GitHub Code Scanning + uses: snyk/actions/setup@806182742461562b67788a64410098c9d9b96adb + + # For Snyk Open Source you must first set up the development environment for your application's dependencies + # For example for Node + #- uses: actions/setup-node@v4 + # with: + # node-version: 20 + + # Runs Snyk Code (SAST) analysis and uploads result into GitHub. + # Use || true to not fail the pipeline + + - name: Snyk Code test + run: snyk code test --debug --org=${{ env.SNYK_ORG_ID }} --sarif > snyk-code.sarif || true + + # Runs Snyk Open Source (SCA) analysis and uploads result to Snyk. + - name: Snyk Open Source monitor + run: snyk monitor --all-projects --target-reference=cicd || true + + # Runs Snyk Infrastructure as Code (IaC) analysis and uploads result to Snyk. + # Use || true to not fail the pipeline. + - name: Snyk IaC test and report + run: snyk iac test --report --target-reference=cicd || true + + # Push the Snyk Code results into GitHub Code Scanning tab + - name: Upload result to GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: snyk-code.sarif + + # - name: Automated Github Action Maven Version Bump + # uses: mickem/gh-action-bump-maven-version@v1.0.0 + + # # Publish the built artifact to the github maven repo + # - name: Publish to GitHub Packages Apache Maven + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # if: steps.bump.outputs.bumped == false + # run: | + # mvn deploy -s $GITHUB_WORKSPACE/settings.xml diff --git a/.github/workflows/summary table.yml b/.github/workflows/summary table.yml new file mode 100644 index 0000000000..2ddfe8eb1c --- /dev/null +++ b/.github/workflows/summary table.yml @@ -0,0 +1,62 @@ +name: Snyk Security Scan + +on: + push: + branches: + - main + - master + pull_request: + # Scan on pull requests to get results before merge + types: [opened, synchronize, reopened] + branches: + - main + - master + +jobs: + snyk: + runs-on: ubuntu-latest + + # Use environment variables for easier management + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up JDK 17 (or your required version) + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: 'maven' + + # ➡️ FIX FOR MAVEN DEPENDENCY RESOLUTION ERROR ⬅️ + # Builds all modules and installs artifacts to the local Maven repository + # (e.g., todolist-core and todolist-web-common) so subsequent modules can find them. + - name: Maven Build and Install + run: mvn -B install -DskipTests + # If your build requires specific settings.xml, ensure it's configured here. + + # ➡️ FIX FOR SNYK & JQ SUMMARY ERROR ⬅️ + # Uses the official Snyk action to scan, generate SARIF, and create a Job Summary. + - name: Snyk Security Test + uses: snyk/actions/maven@master + id: snyk + with: + args: --all-projects --sarif-file-output=snyk-results.sarif --severity-threshold=low + # The Snyk action automatically uses the SNYK_TOKEN environment variable. + + # Uploads the SARIF file to GitHub Code Scanning for a rich summary and alerts. + - name: Upload SARIF file for GitHub Code Scanning + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: snyk-results.sarif + + # Add a step to fail the build if vulnerabilities are found, + # only if the previous Snyk step did not already fail. + - name: Fail if Snyk found critical vulnerabilities (Optional) + if: steps.snyk.outputs.vulnerabilities > 0 + run: | + echo "Snyk found ${{ steps.snyk.outputs.vulnerabilities }} vulnerabilities. See the detailed summary and Code Scanning tab for details." + exit 1 diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 0000000000..e45af55a1f --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,42 @@ +# Node.js +# Build a general Node.js project with npm. +# Add steps that analyze code, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript + +trigger: +- main + +pool: + vmImage: ubuntu-latest + +steps: +- task: NodeTool@0 + inputs: + versionSpec: '20.x' + displayName: 'Install Node.js' + +- script: | + npm install + npm run build + displayName: 'npm install and build' + + # snyk code + - script: snyk code test --sarif-file-output=CodeAnalysisLogs/snyk-code.sarif + continueOnError: true + displayName: 'snyk code' + + # snyk open source + - script: snyk test --all-projects --sarif-file-output=CodeAnalysisLogs/snyk-open-source.sarif + continueOnError: true + displayName: 'snyk open source' + + # snyk container + # NOTE: Change this to your container name + - script: snyk container test sebsnyk/juice-shop --file=Dockerfile --sarif-file-output=CodeAnalysisLogs/snyk-container.sarif + continueOnError: true + displayName: 'snyk container' + + # snyk iac + - script: snyk iac test --sarif-file-output=CodeAnalysisLogs/snyk-iac.sarif + continueOnError: true + displayName: 'snyk iac' diff --git a/log4shell-goof/log4shell-server/k8s/imagebuild.sh b/log4shell-goof/log4shell-server/k8s/imagebuild.sh index 5fe689d04d..3c3500da54 100755 --- a/log4shell-goof/log4shell-server/k8s/imagebuild.sh +++ b/log4shell-goof/log4shell-server/k8s/imagebuild.sh @@ -8,7 +8,7 @@ else fi echo "📦 Building image ${DOCKER_ACCOUNT}/log4shell-server:latest ..." -docker build -t ${DOCKER_ACCOUNT}/log4shell-server:latest $MYDIR/.. +docker build --platform linux/arm64 -t ${DOCKER_ACCOUNT}/log4shell-server:latest $MYDIR/.. echo echo "🚚 Pushing image to DockerHub..." -docker push ${DOCKER_ACCOUNT}/log4shell-server:latest +docker push --platform linux/arm64 ${DOCKER_ACCOUNT}/log4shell-server:latest diff --git a/pom.xml b/pom.xml index 7a67b8cd71..01ea8cbb84 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ io.github.snyk java-goof - 0.0.1-SNAPSHOT + 0.0.2 Java Goof A collection of vulnerable Java apps https://github.com/snyk-labs/java-goof diff --git a/todolist-goof/k8s/imagebuild.sh b/todolist-goof/k8s/imagebuild.sh index f5086c5acc..b25389e0cd 100755 --- a/todolist-goof/k8s/imagebuild.sh +++ b/todolist-goof/k8s/imagebuild.sh @@ -8,7 +8,7 @@ else fi echo "📦 Building image ${DOCKER_ACCOUNT}/java-goof:latest ..." -docker build -t ${DOCKER_ACCOUNT}/java-goof:latest $MYDIR/.. +docker build --platform linux/arm64 -t ${DOCKER_ACCOUNT}/java-goof:latest $MYDIR/.. echo echo "🚚 Pushing image to DockerHub..." -docker push ${DOCKER_ACCOUNT}/java-goof:latest +docker push --platform linux/arm64 ${DOCKER_ACCOUNT}/java-goof:latest diff --git a/todolist-goof/pom.xml b/todolist-goof/pom.xml index 4df79d1b1b..e399d18452 100644 --- a/todolist-goof/pom.xml +++ b/todolist-goof/pom.xml @@ -58,8 +58,8 @@ 3.2 true - 1.7 - 1.7 + 1.8 + 1.8 true diff --git a/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/api/TodoRepository.java b/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/api/TodoRepository.java index a258167cf2..dcf8980240 100644 --- a/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/api/TodoRepository.java +++ b/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/api/TodoRepository.java @@ -83,4 +83,11 @@ public interface TodoRepository { */ void remove(final Todo todo); + /** + * Wibble a todo. + * + * @param todo the todo to wibble + */ + void wibble(final Todo todo); + } diff --git a/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/impl/TodoRepositoryImpl.java b/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/impl/TodoRepositoryImpl.java index 02621ccd9f..3a91f04576 100644 --- a/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/impl/TodoRepositoryImpl.java +++ b/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/repository/impl/TodoRepositoryImpl.java @@ -94,4 +94,12 @@ public void remove(final Todo todo) { entityManager.remove(t); } + /** + * {@inheritDoc} + */ + public void wibble(final Todo todo) { + Todo t = entityManager.find(Todo.class, todo.getId()); + entityManager.remove(t); + } + } diff --git a/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/service/impl/TodoServiceImpl.java b/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/service/impl/TodoServiceImpl.java index 382665cac1..f9bbca69aa 100644 --- a/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/service/impl/TodoServiceImpl.java +++ b/todolist-goof/todolist-core/src/main/java/io/github/todolist/core/service/impl/TodoServiceImpl.java @@ -89,4 +89,5 @@ public Todo create(final Todo todo) { public void remove(final Todo todo) { todoRepository.remove(todo); } + }