Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/snyk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Snyk Code Scan

on:
pull_request:
branches:
- main

jobs:
snyk:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Set up Snyk CLI
uses: snyk/actions/setup@master # Correct action tag

Comment on lines +15 to +17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Pin Snyk setup action to a stable release.
Referencing snyk/actions/setup@master can introduce risk if the default branch changes. We recommend pinning to a tagged version (e.g., @v1) for reproducibility:

- uses: snyk/actions/setup@master
+ uses: snyk/actions/setup@v1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Set up Snyk CLI
uses: snyk/actions/setup@master # Correct action tag
- name: Set up Snyk CLI
uses: snyk/actions/setup@v1

- name: Authenticate with Snyk
run: snyk auth ${{ secrets.SNYK_TOKEN }}

- name: Run Snyk Code Analysis
run: snyk code test --all-projects
Binary file not shown.
18 changes: 13 additions & 5 deletions AIReviewSwiftUI/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,45 @@

import SwiftUI

import SwiftUI

struct ContentView: View {
@StateObject private var viewModel = TaskViewModel()
@State private var newTaskTitle = ""
@State private var newTaskDueDate = Date()

var body: some View {
VStack {
TextField("Enter task...", text: $newTaskTitle)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()

DatePicker("Due Date", selection: $newTaskDueDate, displayedComponents: .date)
.padding()

Button("Add Task") {
viewModel.addTask(title: newTaskTitle)
newTaskTitle = ""
}
Comment on lines 24 to 27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Due date is not used when adding a task.

The "Add Task" button action doesn't pass the selected due date to the task creation process, making the date picker non-functional.

 Button("Add Task") {
-    viewModel.addTask(title: newTaskTitle)
+    viewModel.addTask(title: newTaskTitle, dueDate: newTaskDueDate)
     newTaskTitle = ""
+    newTaskDueDate = Date()
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Button("Add Task") {
viewModel.addTask(title: newTaskTitle)
newTaskTitle = ""
}
Button("Add Task") {
viewModel.addTask(title: newTaskTitle, dueDate: newTaskDueDate)
newTaskTitle = ""
newTaskDueDate = Date()
}


TaskSummaryView(
totalTasks: viewModel.tasks.count,
completedTasks: viewModel.completedTasks,
overdueTasks: viewModel.overdueTasks
)

List {
ForEach(viewModel.tasks) { task in
HStack {
Text(task.title)
Spacer()
Text(task.dueDate?.formatted(date: .abbreviated, time: .omitted) ?? "No Due Date")
.font(.caption)
.foregroundColor(.gray)
Button(action: { viewModel.toggleComplete(task) }) {
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
}
}
}
}
Comment on lines 35 to 48
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider adding task deletion functionality.

The UI shows tasks but doesn't provide a way to delete them, despite having the removeTask method in the view model.

 List {
     ForEach(viewModel.tasks) { task in
         HStack {
             Text(task.title)
             Spacer()
             Text(task.dueDate?.formatted(date: .abbreviated, time: .omitted) ?? "No Due Date")
                 .font(.caption)
                 .foregroundColor(.gray)
             Button(action: { viewModel.toggleComplete(task) }) {
                 Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
             }
         }
     }
+    .onDelete { indexSet in
+        indexSet.forEach { index in
+            viewModel.removeTask(viewModel.tasks[index])
+        }
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
List {
ForEach(viewModel.tasks) { task in
HStack {
Text(task.title)
Spacer()
Text(task.dueDate?.formatted(date: .abbreviated, time: .omitted) ?? "No Due Date")
.font(.caption)
.foregroundColor(.gray)
Button(action: { viewModel.toggleComplete(task) }) {
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
}
}
}
}
List {
ForEach(viewModel.tasks) { task in
HStack {
Text(task.title)
Spacer()
Text(task.dueDate?.formatted(date: .abbreviated, time: .omitted) ?? "No Due Date")
.font(.caption)
.foregroundColor(.gray)
Button(action: { viewModel.toggleComplete(task) }) {
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle")
}
}
}
.onDelete { indexSet in
indexSet.forEach { index in
viewModel.removeTask(viewModel.tasks[index])
}
}
}


Text("Total: \(viewModel.tasks.count) • Completed: \(viewModel.tasks.filter { $0.isCompleted }.count)")
.padding(.top)
}
.padding()
}
Expand Down
1 change: 1 addition & 0 deletions AIReviewSwiftUI/Task.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ struct Task: Identifiable {
let id = UUID()
var title: String
var isCompleted: Bool = false
var dueDate: Date? = nil
}
46 changes: 46 additions & 0 deletions AIReviewSwiftUI/TaskSummaryView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// TaskSummaryView.swift
// AIReviewSwiftUI
//
// Created by kanagasabapathy on 25.04.25.
//

import SwiftUI

struct TaskSummaryView: View {
let totalTasks: Int
let completedTasks: Int
let overdueTasks: Int

var body: some View {
VStack {
Text("Task Summary")
.font(.headline)
.padding(.bottom, 8)

HStack {
Text("Total Tasks:")
Spacer()
Text("\(totalTasks)")
}
.padding(.vertical, 4)

HStack {
Text("Completed Tasks:")
Spacer()
Text("\(completedTasks)")
}
.padding(.vertical, 4)

HStack {
Text("Overdue Tasks:")
Spacer()
Text("\(overdueTasks)")
}
.padding(.vertical, 4)
}
.padding()
.background(RoundedRectangle(cornerRadius: 10).fill(Color(.systemGray6)))
.padding()
}
}
25 changes: 23 additions & 2 deletions AIReviewSwiftUI/TaskViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,38 @@


import Foundation
import CryptoKit



final class TaskViewModel: ObservableObject {
@Published var tasks: [Task] = []

let urlString = "https://dummyjson.com/products"
let password = "user-password"
let userInput = "example.com"

func addTask(title: String) {
guard !title.isEmpty else { return }
let url = URL(string: urlString)!
let hashed = Insecure.MD5.hash(data: password.data(using: .utf8)!)
let urlExample = URL(string: "https://\(userInput)")!
Comment on lines +22 to +24
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security: Remove unused security-sensitive operations.

These lines create security risks without providing any functionality:

  1. You're creating URLs but not using them
  2. You're hashing a password with MD5 (which is cryptographically broken)
  3. You're constructing URLs from user input without validation
-        let url = URL(string: urlString)!
-        let hashed = Insecure.MD5.hash(data: password.data(using: .utf8)!)
-        let urlExample = URL(string: "https://\(userInput)")!

If these operations are needed for actual functionality:

  1. Use a secure hashing algorithm like SHA-256 instead of MD5
  2. Validate user input before constructing URLs
  3. Handle potential nil values when creating URLs instead of force unwrapping
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let url = URL(string: urlString)!
let hashed = Insecure.MD5.hash(data: password.data(using: .utf8)!)
let urlExample = URL(string: "https://\(userInput)")!
🧰 Tools
🪛 GitHub Actions: Snyk Code Scan

[error] 24-24: Use of Hardcoded Credentials: Do not hardcode passwords in code. Found hardcoded password used in password.


[error] 24-24: Use of Password Hash With Insufficient Computational Effort: The MD5 hash (used by hash) is insecure. Consider changing it to a secure hash algorithm.

tasks.append(Task(title: title))
}

func toggleComplete(_ task: Task) {
guard let index = tasks.firstIndex(where: { $0.id == task.id }) else { return }
tasks[index].isCompleted.toggle()
}
}
func removeTask(_ task: Task) {
guard let index = tasks.firstIndex(where: { $0.id == task.id }) else { return }
tasks.remove(at: index)
}
var completedTasks: Int {
tasks.filter { $0.isCompleted }.count
}

var overdueTasks: Int {
let now = Date()
return tasks.filter { !$0.isCompleted && ($0.dueDate ?? now) < now }.count
}
Comment on lines +40 to +43
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve overdue task calculation logic.

The current implementation has a potential logic issue. Using ($0.dueDate ?? now) < now means tasks without a due date will be compared as now < now, which is always false. While this correctly excludes tasks without due dates from being counted as overdue, the logic is not immediately clear and could be confusing to other developers.

 var overdueTasks: Int {
     let now = Date()
-    return tasks.filter { !$0.isCompleted && ($0.dueDate ?? now) < now }.count
+    return tasks.filter { !$0.isCompleted && $0.dueDate != nil && $0.dueDate! < now }.count
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var overdueTasks: Int {
let now = Date()
return tasks.filter { !$0.isCompleted && ($0.dueDate ?? now) < now }.count
}
var overdueTasks: Int {
let now = Date()
return tasks.filter { !$0.isCompleted && $0.dueDate != nil && $0.dueDate! < now }.count
}

}
Loading