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
19 changes: 19 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Секрети для бази даних
DB_USERNAME=your_database_user
DB_PASSWORD=your_database_password

# Секрети для пошти (наприклад, Gmail App Password)
MAIL_USERNAME=your_email@example.com
MAIL_PASSWORD=your_email_app_password

# Секрети для OAuth2 Google
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

# Секрети для OAuth2 GitHub
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret

# Секрети для OAuth2 GitLab
GITLAB_CLIENT_ID=your_gitlab_client_id
GITLAB_CLIENT_SECRET=your_gitlab_client_secret
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ target
logs
attachments
*.patch

.env
pgdata
pgdata-test

37 changes: 37 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#FROM postgres:18
#RUN apt-get update && apt-get install -y tzdata
#ENV TZ=Europe/Kyiv
## Оновлення tzdata та перевстановлення /etc/localtime
#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone


#FROM eclipse-temurin:17-jre
#
#RUN apt-get update && apt-get install -y tzdata && rm -rf /var/lib/apt/lists/*
#
#ENV TZ=Europe/Kyiv
#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
#
#WORKDIR /app
#
## Копіюємо лише правильний виконуваний jar (ігноруючи .jar.original)
##COPY target/*[!o][!r][!i][!g][!i][!n][!a][!l].jar app.jar
#COPY target/*.jar app.jar
#
#ENTRYPOINT ["java", "-jar", "app.jar"]


FROM eclipse-temurin:17-jre

RUN apt-get update && apt-get install -y tzdata && rm -rf /var/lib/apt/lists/*

ENV TZ=Europe/Kyiv
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /app

# Універсальне копіювання будь-якого головного jar-файлу
COPY target/*.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@
- https://habr.com/ru/articles/259055/

Список выполненных задач:
...

№ 6 (на 25.05.2026)
137 changes: 137 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
#version: '3.8'
#services:
# postgres_db:
# image: postgres:latest
# container_name: postgres-db-test
# environment:
# POSTGRES_USER: jira
# POSTGRES_PASSWORD: jira-test
# POSTGRES_DB: jira
# TZ: Europe/Kyiv
# PGTZ: Europe/Kyiv
## command: postgres -c timezone='Europe/Kyiv'
# ports:
# - "5433:5432"
# volumes:
# - pgdata:/var/lib/postgresql/data
# networks:
# - java_network
# restart: always
#
# app:
# build: .
# container_name: java_app
# ports:
# - "8080:8080"
# environment:
# SPRING_DATASOURCE_URL: jdbc:postgresql://postgres_db:5433/jira?serverTimezone=Europe/Kyiv
# SPRING_DATASOURCE_USERNAME: jira
# SPRING_DATASOURCE_PASSWORD: jira-test
# TZ: Europe/Kyiv
# PGTZ: Europe/Kyiv
# volumes:
# - pgdata:/var/lib/postgresql/data
# depends_on:
# - postgres_db
# networks:
# - java_network
#
#networks:
# java_network:
# driver: bridge
#
#volumes:
# pgdata:
#
#
#
##services:
## db:
## build: .
## image: postgres
## environment:
## TZ: Europe/Kyiv
## PGTZ: Europe/Kyiv
## volumes:
## - pgdata:/var/lib/postgresql/data
##volumes:
## pgdata:

# version: '3.8'
services:
# Основна база даних для розробки (Порт 5432)
postgres-db:
image: postgres:latest
container_name: postgres-db
ports:
- "5432:5432"
environment:
- POSTGRES_USER=${DB_USERNAME}
- POSTGRES_PASSWORD=${DB_PASSWORD}
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- ./pgdata:/var/lib/postgresql/data
networks:
- java_network
restart: always
# Перевірка готовності бази приймати підключення
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U jira -d jira" ]
interval: 5s
timeout: 5s
retries: 5

# Тестова база даних для Maven тестів (Порт 5433)
postgres-db-test:
image: postgres:latest
container_name: postgres-db-test
ports:
- "5433:5432"
environment:
- POSTGRES_USER=jira
- POSTGRES_PASSWORD=jira-test
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- ./pgdata-test:/var/lib/postgresql/data
# Хитрість: створюємо копію файлу зони з новою назвою перед запуском Postgres
command: >
sh -c "mkdir -p /usr/share/zoneinfo/Europe &&
cp /usr/share/zoneinfo/Europe/Kyiv /usr/share/zoneinfo/Europe/Kiev || true &&
exec docker-entrypoint.sh postgres"
app:
build: .
container_name: java_app
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres-db:5432/jira
# SPRING_DATASOURCE_USERNAME: jira
# SPRING_DATASOURCE_PASSWORD: JiraRush
SPRING_DATASOURCE_USERNAME: ${DB_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD}
# DB_HOST: postgres-db
DB_USERNAME: ${DB_USERNAME}
DB_PASSWORD: ${DB_PASSWORD}
MAIL_USERNAME: ${MAIL_USERNAME}
MAIL_PASSWORD: ${MAIL_PASSWORD}
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
GITLAB_CLIENT_ID: ${GITLAB_CLIENT_ID}
GITLAB_CLIENT_SECRET: ${GITLAB_CLIENT_SECRET}
TZ: Europe/Kyiv
# depends_on:
# - postgres_db
depends_on:
postgres-db:
condition: service_healthy # Запуск додатку ТІЛЬКИ після успішного healthcheck бази
networks:
- java_network

networks:
java_network:
driver: bridge

volumes:
pgdata:
13 changes: 9 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,11 @@
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
Expand Down Expand Up @@ -129,19 +129,24 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- <scope>test</scope>-->
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
<!-- <scope>test</scope>-->
</dependency>
<!-- https://youtrack.jetbrains.com/issue/IDEA-231927-->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.h2database</groupId>-->
<!-- <artifactId>h2</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
</dependencies>

<build>
Expand Down
16 changes: 8 additions & 8 deletions resources/view/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ <h3 class="mb-3">Sign in</h3>
type="button">
<i class="fa-brands fa-google"></i>
</a>
<a class="btn btn-primary btn-lg me-2" href="/oauth2/authorization/vk" style="padding-left: 17px; padding-right: 17px;"
type="button">
<i class="fa-brands fa-vk"></i>
</a>
<a class="btn btn-danger btn-lg me-2" href="/oauth2/authorization/yandex" style="padding-left: 21px; padding-right: 21px;"
type="button">
<i class="fa-brands fa-yandex"></i>
</a>
<!-- <a class="btn btn-primary btn-lg me-2" href="/oauth2/authorization/vk" style="padding-left: 17px; padding-right: 17px;"-->
<!-- type="button">-->
<!-- <i class="fa-brands fa-vk"></i>-->
<!-- </a>-->
<!-- <a class="btn btn-danger btn-lg me-2" href="/oauth2/authorization/yandex" style="padding-left: 21px; padding-right: 21px;"-->
<!-- type="button">-->
<!-- <i class="fa-brands fa-yandex"></i>-->
<!-- </a>-->
<a class="btn btn-dark btn-lg me-2" href="/oauth2/authorization/github" type="button">
<i class="fa-brands fa-github"></i>
</a>
Expand Down
16 changes: 8 additions & 8 deletions resources/view/unauth/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ <h3 class="mb-3">Registration</h3>
type="button">
<i class="fa-brands fa-google"></i>
</a>
<a class="btn btn-primary btn-lg me-2" href="/oauth2/authorization/vk" style="padding-left: 17px; padding-right: 17px;"
type="button">
<i class="fa-brands fa-vk"></i>
</a>
<a class="btn btn-danger btn-lg me-2" href="/oauth2/authorization/yandex" style="padding-left: 21px; padding-right: 21px;"
type="button">
<i class="fa-brands fa-yandex"></i>
</a>
<!-- <a class="btn btn-primary btn-lg me-2" href="/oauth2/authorization/vk" style="padding-left: 17px; padding-right: 17px;"-->
<!-- type="button">-->
<!-- <i class="fa-brands fa-vk"></i>-->
<!-- </a>-->
<!-- <a class="btn btn-danger btn-lg me-2" href="/oauth2/authorization/yandex" style="padding-left: 21px; padding-right: 21px;"-->
<!-- type="button">-->
<!-- <i class="fa-brands fa-yandex"></i>-->
<!-- </a>-->
<a class="btn btn-dark btn-lg me-2" href="/oauth2/authorization/github" type="button">
<i class="fa-brands fa-github"></i>
</a>
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/com/javarush/jira/JiraRushApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;

import java.util.TimeZone;

@SpringBootApplication
@EnableConfigurationProperties(AppProperties.class)
@EnableCaching
public class JiraRushApplication {

public static void main(String[] args) {
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Kyiv"));
SpringApplication.run(JiraRushApplication.class, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,22 @@ public static void upload(MultipartFile multipartFile, String directoryPath, Str
throw new IllegalRequestDataException("Select a file to upload.");
}

File dir = new File(directoryPath);
if (dir.exists() || dir.mkdirs()) {
File file = new File(directoryPath + fileName);
try (OutputStream outStream = new FileOutputStream(file)) {
outStream.write(multipartFile.getBytes());
} catch (IOException ex) {
throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename());
}
// File dir = new File(directoryPath);
// if (dir.exists() || dir.mkdirs()) {
// File file = new File(directoryPath + fileName);
// try (OutputStream outStream = new FileOutputStream(file)) {
// outStream.write(multipartFile.getBytes());
// } catch (IOException ex) {
// throw new IllegalRequestDataException("Failed to upload file" + multipartFile.getOriginalFilename());
// }
// }
try {
Path dirPath = Path.of(directoryPath);
Files.createDirectories(dirPath);
Path filePath = dirPath.resolve(fileName);
multipartFile.transferTo(filePath);
} catch (IOException ex) {
throw new IllegalRequestDataException("Failed to upload file " + multipartFile.getOriginalFilename());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,24 @@

import java.util.List;

import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.repository.query.Param;

@Transactional(readOnly = true)
public interface ActivityRepository extends BaseRepository<Activity> {
@Query("SELECT a FROM Activity a JOIN FETCH a.author WHERE a.taskId =:taskId ORDER BY a.updated DESC")
List<Activity> findAllByTaskIdOrderByUpdatedDesc(long taskId);

@Query("SELECT a FROM Activity a JOIN FETCH a.author WHERE a.taskId =:taskId AND a.comment IS NOT NULL ORDER BY a.updated DESC")
List<Activity> findAllComments(long taskId);

@Modifying
@Query(value = "INSERT INTO activity (author_id, task_id, updated, comment, status_code, priority_code, type_code, title, description, estimate) " +
"VALUES (:authorId, :taskId, CURRENT_TIMESTAMP, :comment, :statusCode, :priorityCode, :typeCode, :title, :description, :estimate)",
nativeQuery = true)
void saveActivityDirectly(@Param("authorId") long authorId, @Param("taskId") long taskId,
@Param("comment") String comment, @Param("statusCode") String statusCode,
@Param("priorityCode") String priorityCode, @Param("typeCode") String typeCode,
@Param("title") String title, @Param("description") String description,
@Param("estimate") Integer estimate);
}
Loading