Skip to content

Commit

Permalink
Dockerized the api
Browse files Browse the repository at this point in the history
  • Loading branch information
wissemgrari committed Apr 19, 2024
1 parent a1da697 commit 1e01cda
Show file tree
Hide file tree
Showing 20 changed files with 185 additions and 170 deletions.
79 changes: 0 additions & 79 deletions .github/workflows/azure-webapps-java-jar.yml

This file was deleted.

5 changes: 5 additions & 0 deletions .idea/codeStyles/codeStyleConfig.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions api/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target/
*.log
3 changes: 2 additions & 1 deletion api/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ build/
### VS Code ###
.vscode/

.env
application-dev.yml
application-prod.yml
30 changes: 30 additions & 0 deletions api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Use Maven image for the build stage
FROM maven:3.8.1-openjdk-17-slim as build

# Set the current working directory inside the image
WORKDIR /api

# Copy pom.xml file to the /api directory
COPY pom.xml .

# Download all required dependencies into one layer
RUN mvn -B dependency:resolve dependency:resolve-plugins

# Copy source code to the /api directory
COPY src ./src

# package the application
RUN mvn package -DskipTests

# Start a new stage for running the application
# Starting a new stage for running the application is a part of the multi-stage build process in Docker. The main advantage of this approach is that it allows you to separate the build stage and the run stage, which can significantly reduce the size of the final Docker image. In the build stage, you typically install all the necessary build tools and dependencies, and compile your application. This stage often results in a large Docker image because of all the build tools and dependencies. In the run stage, you start from a new, often smaller base image, and copy only the compiled application (and any runtime dependencies) from the build stage. This results in a smaller final Docker image because it doesn't include the build tools and dependencies that are not needed to run the application.
FROM openjdk:17-slim

# Set the current working directory inside the image
WORKDIR /app

# Copy the jar file from the build stage
COPY --from=build /api/target/*.jar app.jar

# Run the application
CMD ["java", "-jar", "app.jar"]
104 changes: 48 additions & 56 deletions api/pom.xml
Original file line number Diff line number Diff line change
@@ -1,59 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>wissem</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>wissem</name>
<description>spotify profile api</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>me.paulschwarz</groupId>
<artifactId>spring-dotenv</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>wissem</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>wissem</name>
<description>spotify profile api</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
40 changes: 25 additions & 15 deletions api/src/main/java/com/wissem/Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,30 @@
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.view.RedirectView;
import org.springframework.web.util.UriComponentsBuilder;

import java.security.NoSuchAlgorithmException;
import java.util.Map;

@RestController
@CrossOrigin(origins = "http://localhost:4200")
public class Controller {

@Value("${spotify.client_id}") String CLIENT_ID;
@Value("${spotify.client_secret}") String CLIENT_SECRET;
@Value("${spotify.code_verifier}") String CODE_VERIFIER;

String redirectUri = "http://localhost:4200/login";
String scope = "user-read-private user-read-email user-read-recently-played user-top-read user-follow-read user-follow-modify playlist-read-private playlist-read-collaborative playlist-modify-public";
@Value("${spotify.redirect_uri}") String redirectUri;
String scope =
"user-read-private user-read-email user-read-recently-played user-top-read " +
"user-follow-read user-follow-modify playlist-read-private " +
"playlist-read-collaborative playlist-modify-public";
String authUrl = "https://accounts.spotify.com/authorize";
String uri = "https://accounts.spotify.com/api/token";


@GetMapping("/")
public RedirectView index() {
return new RedirectView("index.html");
}

@GetMapping("/api/v1/auth-url")
public ResponseEntity<Map<String, String>> buildAuthUrl()
Expand All @@ -38,8 +44,7 @@ public ResponseEntity<Map<String, String>> buildAuthUrl()
.queryParam("code_challenge", codeChallenge)
.queryParam("redirect_uri", redirectUri)
.toUriString();
return new ResponseEntity<>(
Map.of("url", authUrlWithParams), HttpStatus.OK);
return new ResponseEntity<>(Map.of("url", authUrlWithParams), HttpStatus.OK);
}

@GetMapping("/api/v1/token")
Expand All @@ -49,7 +54,7 @@ public ResponseEntity<TokenResponse> getToken(@RequestParam String code) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// setting the body
MultiValueMap<String, String> body= new LinkedMultiValueMap<String, String>();
MultiValueMap<String, String> body = new LinkedMultiValueMap<String, String>();
body.add("client_id", CLIENT_ID);
body.add("grant_type", "authorization_code");
body.add("code", code);
Expand All @@ -59,7 +64,8 @@ public ResponseEntity<TokenResponse> getToken(@RequestParam String code) {
}

@PostMapping("/api/v1/refresh/token")
public ResponseEntity<TokenResponse> getRefreshToken(@RequestBody RefreshTokenBody request) {
public ResponseEntity<TokenResponse> getRefreshToken(
@RequestBody RefreshTokenBody request) {
RestTemplate restTemplate = new RestTemplate();
// setting the headers
HttpHeaders headers = new HttpHeaders();
Expand All @@ -72,17 +78,21 @@ public ResponseEntity<TokenResponse> getRefreshToken(@RequestBody RefreshTokenBo
return getTokenResponseResponseEntity(restTemplate, headers, body);
}

private ResponseEntity<TokenResponse> getTokenResponseResponseEntity(RestTemplate restTemplate, HttpHeaders headers, MultiValueMap<String, String> body) {
HttpEntity<MultiValueMap<String, String>>
entity =new HttpEntity<MultiValueMap<String, String>>(body, headers);
ResponseEntity<TokenResponse> response = restTemplate.postForEntity(uri, entity , TokenResponse.class);
return new ResponseEntity<TokenResponse>(response.getBody(), response.getStatusCode());
private ResponseEntity<TokenResponse> getTokenResponseResponseEntity(
RestTemplate restTemplate, HttpHeaders headers, MultiValueMap<String, String> body) {
HttpEntity<MultiValueMap<String, String>> entity =
new HttpEntity<MultiValueMap<String, String>>(body, headers);
ResponseEntity<TokenResponse> response =
restTemplate.postForEntity(uri, entity, TokenResponse.class);
return new ResponseEntity<TokenResponse>(response.getBody(),
response.getStatusCode());
}


}

record TokenResponse(String access_token, String token_type, int expires_in, String refresh_token, String scope) {
record TokenResponse(String access_token, String token_type, int expires_in,
String refresh_token, String scope) {
}

record RefreshTokenBody(String refreshToken) {
Expand Down
23 changes: 23 additions & 0 deletions api/src/main/java/com/wissem/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.wissem;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

@Value("${cors.allowed-origins}") private String allowedOrigins;

@Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins(allowedOrigins)
.allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true);
}

}
3 changes: 0 additions & 3 deletions api/src/main/resources/.env.example

This file was deleted.

7 changes: 3 additions & 4 deletions api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
server:
port: 5000

spotify:
client_id: ${CLIENT_ID}
client_secret: ${CLIENT_SECRET}
code_verifier: ${CODE_VERIFIER}
spring:
profiles:
active: dev
10 changes: 10 additions & 0 deletions api/src/main/resources/static/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Spotify Profile API</title>
</head>
<body>
<h1>Welcome to Spotify Profile API</h1>
</body>
</html>
1 change: 1 addition & 0 deletions client/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
10 changes: 10 additions & 0 deletions client/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM node:20-alpine as build

WORKDIR /client

COPY package.json ./

COPY yarn.lock ./

RUN yarn install

Loading

0 comments on commit 1e01cda

Please sign in to comment.