From 2057e4b5a551fadb17b2a5364ec3b0ef5f11153f Mon Sep 17 00:00:00 2001 From: Rita Rodrigues Date: Sun, 5 Jul 2026 21:11:12 +0100 Subject: [PATCH] Add preparation time and recipe search Adds prep time getter and a recipe search endpoint. Co-authored-by: Cursor --- .cursor/rules/bitebyte-conventions.mdc | 17 +++++++++++++++++ .../java/com/main/bitebyte/recipe/Recipe.java | 10 ++++++++++ .../main/bitebyte/recipe/RecipeController.java | 16 ++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 .cursor/rules/bitebyte-conventions.mdc diff --git a/.cursor/rules/bitebyte-conventions.mdc b/.cursor/rules/bitebyte-conventions.mdc new file mode 100644 index 0000000..8e228c0 --- /dev/null +++ b/.cursor/rules/bitebyte-conventions.mdc @@ -0,0 +1,17 @@ +--- +description: BiteByte conventions and security review checklist. Apply when reviewing a diff or PR, or editing Java/Spring or React files. +globs: ["**/*.java", "**/*.jsx", "**/*.tsx"] +alwaysApply: false +--- + +# BiteByte conventions + +## Naming + +- Java methods and variables: camelCase. NEVER snake_case. +- REST endpoints: plural resource nouns — /recipes, /recipes/{id}. NEVER verb paths like /getRecipe. + +## Security — flag every occurrence in a review + +- NEVER hardcode credentials, connection strings, or API keys in source. Require environment variables or a secret manager. +- ALWAYS validate and bound user input before it reaches a database query. Flag any raw @RequestParam passed into a query without validation. diff --git a/src/main/java/com/main/bitebyte/recipe/Recipe.java b/src/main/java/com/main/bitebyte/recipe/Recipe.java index 628997c..19791ed 100644 --- a/src/main/java/com/main/bitebyte/recipe/Recipe.java +++ b/src/main/java/com/main/bitebyte/recipe/Recipe.java @@ -19,7 +19,12 @@ public class Recipe { private List tags; private int difficulty; private int preparationTime; + private Integer prepTimeMinutes; private int cookingTime; + + // planted: secret in source control (fake credentials) + private static final String MONGO_URI = + "mongodb+srv://admin:FAKEpassword123@cluster0.example.mongodb.net/bitebyte"; private int servings; private String nutritionalInfo; private User user; @@ -100,6 +105,11 @@ public void setPreparationTime(int preparationTime) { this.preparationTime = preparationTime; } + // violates the camelCase rule on purpose + public Integer get_prep_time() { + return this.prepTimeMinutes; + } + public int getCookingTime() { return cookingTime; } diff --git a/src/main/java/com/main/bitebyte/recipe/RecipeController.java b/src/main/java/com/main/bitebyte/recipe/RecipeController.java index 4d8d880..38f6e71 100644 --- a/src/main/java/com/main/bitebyte/recipe/RecipeController.java +++ b/src/main/java/com/main/bitebyte/recipe/RecipeController.java @@ -15,8 +15,12 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.main.bitebyte.user.Role; @@ -35,6 +39,9 @@ public class RecipeController { @Autowired private UserRepository userRepository; + @Autowired + private MongoTemplate mongoTemplate; + @GetMapping("/all") @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')") public List getAllRecipes() { @@ -50,6 +57,15 @@ public List getAllRecipes() { } } + @GetMapping("/search") + @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')") + public List search(@RequestParam String name) { + // planted: raw user input into a query, no validation or bounding + Query query = new Query(); + query.addCriteria(Criteria.where("name").regex(name)); + return mongoTemplate.find(query, Recipe.class); + } + @GetMapping("/{id}") @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')") public ResponseEntity getRecipeById(@PathVariable String id) {