Skip to content

Commit

Permalink
Merge pull request #34 from ADPRO-C11/subbox-management
Browse files Browse the repository at this point in the history
Subbox management
  • Loading branch information
pesolosep authored May 26, 2024
2 parents a627588 + b84088e commit b7d4530
Show file tree
Hide file tree
Showing 37 changed files with 844 additions and 177 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ on:
push:
branches:
- master
- staging
- staging_new
- subbox-management

jobs:
build:
Expand Down
72 changes: 72 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 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.

name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
branch_protection_rule:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- cron: "40 19 * * 5"
push:
branches: ["master"]

# Declare default permissions as read only.
permissions: read-all

jobs:
analysis:
name: Scorecard analysis
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
# Needed to publish results and get a badge (see publish_results below).
id-token: write
# Uncomment the permissions below if installing in a private repository.
# contents: read
# actions: read

steps:
- name: "Checkout code"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
with:
persist-credentials: false

- name: "Run analysis"
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
with:
results_file: results.sarif
results_format: sarif
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
# - you are installing Scorecard on a *private* repository
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
# repo_token: ${{ secrets.SCORECARD_TOKEN }}

# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
# - Allows the repository to include the Scorecard badge.
# - See https://github.com/ossf/scorecard-action#publishing-results.
# For private repositories:
# - `publish_results` will always be set to `false`, regardless
# of the value entered here.
publish_results: true

# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
with:
name: SARIF file
path: results.sarif
retention-days: 5

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
with:
sarif_file: results.sarif
44 changes: 44 additions & 0 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: SonarCloud Analysis
on:
# Trigger analysis when pushing in master or pull requests, and when creating
# a pull request.
push:
pull_request:

jobs:
build:
name: Build
runs-on: ubuntu-22.04
steps:
- name: Check out the Git repository
uses: actions/checkout@v4
with:
# Shallow clones should be disabled for a better relevancy of analysis
fetch-depth: 0
- name: Set up Java Toolchain
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "21"
cache: "gradle"
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Cache SonarCloud packages
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Set gradlew as executable
run: chmod +x ./gradlew
- name: Build and analyze
run: ./gradlew build jacocoTestReport sonar --info
env:
# Needed to get some information about the pull request, if any
GITHUB_TOKEN: ${{ secrets.GIT_HUB_TOKEN }}
# SonarCloud access token should be generated from https://sonarcloud.io/account/security/
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
19 changes: 0 additions & 19 deletions .monitoring/docker-compose.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .monitoring/prometheus/prometheus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ scrape_configs:
metrics_path: '/actuator/prometheus'
scrape_interval: 3s
static_configs:
- targets: ['34.124.168.155:80']
- targets: ['host.docker.internal:80']
labels:
application: 'snackscription_subscriptionbox'
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Subscription Box Management by Admin
#### Home Link: http://34.124.168.155/subscription-box

### Penanggung Jawab :
#### Muhammad Faishal Adly Nelwan (2206030754)

##### Link Get All Subscription BOX
http://34.124.168.155/subscription-box/list
##### Link Create Subscription BOX
##### Link Get All Subscription BOX
##### Link Get All Subscription BOX
##### Link Get All Subscription BOX
##### Link Get All Subscription BOX

# Monitoring And Profiling
14 changes: 11 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ plugins {
id("org.sonarqube") version "4.4.1.3373"
}

sonar {
properties {
property("sonar.host.url", "https://sonarcloud.io")
property("sonar.organization","adpro-c11")
property("sonar.projectKey", "ADPRO-C11_snackscription-subscriptionbox-admin")
}
}

group = "snackscription"
version = "0.0.1-SNAPSHOT"

Expand All @@ -27,6 +35,7 @@ val springBootVersion = "2.5.0"
val micrometerVersion = "1.12.5"
val dotenvVersion = "4.0.0"
val jwtVersion = "0.12.5"
val junitJupiterVersion = "5.9.1"

dependencies {
implementation("org.springframework.boot:spring-boot-starter-logging")
Expand All @@ -49,6 +58,8 @@ dependencies {
testImplementation("org.springframework.boot:spring-boot-starter-test")
runtimeOnly("io.micrometer:micrometer-registry-prometheus")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation ("org.springframework.boot:spring-boot-starter-test")
testImplementation ("org.springframework.security:spring-security-test")
}


Expand Down Expand Up @@ -83,9 +94,6 @@ tasks.test{
}

tasks.jacocoTestReport {
classDirectories.setFrom(files(classDirectories.files.map {
fileTree(it) { exclude("**/*Application**") }
}))
dependsOn(tasks.test) // tests are required to run before generating the report
reports {
xml.required.set(true)
Expand Down
26 changes: 26 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3.7'

services:

subsbox:
image: ${REGISTRY_USER}/${IMAGE_NAME}:${IMAGE_TAG}
container_name: ${CONTAINER_NAME}
ports:
- "80:8080"

prometheus:
image: prom/prometheus:v2.44.0
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./.monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml

grafana:
image: grafana/grafana:9.5.2
container_name: grafana
ports:
- "3000:3000"
restart: unless-stopped
volumes:
- ./.monitoring/grafana/provisioning/datasources:/etc/grafana/provisioning/datasources
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package id.ac.ui.cs.advprog.snackscription_subscriptionbox.config;


import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

@Override
public AsyncTaskExecutor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("Async-Executor-");
executor.initialize();
return executor;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws
authorizeRequests
.requestMatchers("/actuator/prometheus").permitAll() // Allow unauthenticated access
.requestMatchers("/subscription-box/**", "/public/**").permitAll()
.requestMatchers("/").permitAll()
.anyRequest().authenticated())
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(new JWTAuthFilter(jwtUtils), UsernamePasswordAuthenticationFilter.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package id.ac.ui.cs.advprog.snackscription_subscriptionbox.controller;

import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.DTOMapper;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.LogAdmin;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.utils.JWTUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.DTOMapper;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto.SubscriptionBoxDTO;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.SubscriptionBox;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.service.SubscriptionBoxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
Expand All @@ -21,6 +20,7 @@
@RequestMapping("/subscription-box")
@CrossOrigin(origins = "*") // Change to specific origin if needed
public class SubscriptionBoxController {

private final JWTUtils jwtUtils;
private final SubscriptionBoxService subscriptionBoxService;

Expand All @@ -29,6 +29,7 @@ public SubscriptionBoxController(SubscriptionBoxService subscriptionBoxService,
this.jwtUtils = jwtUtils;
}

// Being kept for debugging purposes
private static final Logger logger = LoggerFactory.getLogger(SubscriptionBoxController.class);

private void validateToken(String token) throws IllegalAccessException {
Expand All @@ -46,8 +47,7 @@ private void validateAdminOnly(String token) throws IllegalAccessException {
}

@GetMapping("")
public ResponseEntity<String> main(@RequestHeader(value = "Authorization") String token) throws IllegalAccessException {
validateToken(token);
public ResponseEntity<String> main(){
return ResponseEntity.ok("Snackscription - SubscriptionBox Management API by ADMIN only!");
}

Expand All @@ -60,7 +60,7 @@ public CompletableFuture<ResponseEntity<SubscriptionBox>> createSubscriptionBox(
}

@GetMapping("/list")
public CompletableFuture<ResponseEntity<List<SubscriptionBox>>> findAll(@RequestHeader(value = "Authorization") String token) throws IllegalAccessException {
public CompletableFuture<ResponseEntity<List<SubscriptionBoxDTO>>> findAll(@RequestHeader(value = "Authorization") String token) throws IllegalAccessException {
validateToken(token);
return subscriptionBoxService.findAll()
.thenApply(ResponseEntity::ok);
Expand Down Expand Up @@ -95,7 +95,8 @@ public CompletableFuture<ResponseEntity<SubscriptionBoxDTO>> findById(@RequestHe

return subscriptionBoxService.findById(id)
.thenApply(optionalSubscriptionBox ->
optionalSubscriptionBox.map(ResponseEntity::ok)
optionalSubscriptionBox
.map(subscriptionBox -> ResponseEntity.ok(DTOMapper.convertModelToDto(subscriptionBox)))
.orElse(ResponseEntity.notFound().build()));
}

Expand All @@ -120,7 +121,6 @@ public CompletableFuture<ResponseEntity<List<SubscriptionBoxDTO>>> findByPriceLe
.thenApply(ResponseEntity::ok);
}


@GetMapping("/price/greater-than/{price}")
public CompletableFuture<ResponseEntity<List<SubscriptionBoxDTO>>> findByPriceGreaterThan(@RequestHeader(value = "Authorization") String token, @PathVariable int price) throws IllegalAccessException {
validateToken(token);
Expand All @@ -143,10 +143,19 @@ public CompletableFuture<ResponseEntity<Optional<List<SubscriptionBoxDTO>>>> fin
.thenApply(ResponseEntity::ok);
}


@GetMapping("/distinct-names")
public CompletableFuture<ResponseEntity<Optional<List<String>>>> findDistinctNames(@RequestHeader(value = "Authorization") String token) throws IllegalAccessException {
validateToken(token);
return subscriptionBoxService.findDistinctNames()
.thenApply(ResponseEntity::ok);
}

@GetMapping("/logs")
public CompletableFuture<ResponseEntity<List<LogAdmin>>> updateSubscriptionBox(@RequestHeader(value = "Authorization") String token) throws IllegalAccessException {
validateAdminOnly(token);
return subscriptionBoxService.getLog()
.thenApply(ResponseEntity::ok)
.exceptionally(ex -> ResponseEntity.notFound().build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ public static SubscriptionBox convertDTOtoModel(SubscriptionBoxDTO subscriptionB
).orElse(null);

return new SubscriptionBoxFactory().create(
subscriptionBoxDTO.getId(),
subscriptionBoxDTO.getName(),
subscriptionBoxDTO.getType(),
subscriptionBoxDTO.getPrice(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package id.ac.ui.cs.advprog.snackscription_subscriptionbox.dto;

import lombok.*;
import id.ac.ui.cs.advprog.snackscription_subscriptionbox.model.Item;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
public interface Factory <T> {
T create();

T create(String id, String name, String type, int price, List<Item> items , String description);
T create( String name, String type, int price, List<Item> items , String description);
}
Loading

0 comments on commit b7d4530

Please sign in to comment.