diff --git a/.gitignore b/.gitignore index cd38e2e7b..08516de94 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,6 @@ logs attachments *.patch +#properties.env +#src/main/resources/environment-vars.yaml \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..f73e74d23 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM maven:3.9.9-amazoncorretto-17 AS build +WORKDIR /app + +COPY pom.xml ./ +COPY src ./src + +RUN mvn clean package -Pprod + +FROM openjdk:17-jdk-slim +WORKDIR /app + +COPY --from=build /app/target/*.jar jira.jar +COPY /resources /app/resources + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "/app/jira.jar"] +CMD ["--spring.profiles.active=prod"] diff --git a/README.md b/README.md index 719b268f5..253e249a6 100644 --- a/README.md +++ b/README.md @@ -27,4 +27,28 @@ - https://habr.com/ru/articles/259055/ Список выполненных задач: -... \ No newline at end of file + +Task 1. Анализ структуры проекта (onboarding). + +Task 2. Удалены социальные сети: vk, yandex. + +Task 3. Чувствительная информация вынесена в отдельный проперти файл: + логин, + пароль БД, + идентификаторы для OAuth регистрации/авторизации, + настройки почты. +Основной вариант properties.env; альтернативный - environment-vars.yaml. + +Task 5. Написаны тесты для публичных методов контроллера ProfileRestController. + +Task s.n. Рефакторинг сокращения TO -> DTO в классах и методах. Лучше читается и не путается с "to". + +Task 6. Рефакторинг метода com.javarush.jira.bugtracking.attachment.FileUtil#upload, +чтобы он использовал современный подход для работы с файловой системмой. + +Task 7. Новый функционал: добавление тегов к задаче (REST API + реализация на сервисе). Также добавлены тесты. + +Task 11. Локализация на двух языках для шаблонов писем (mails) и стартовой страницы index.html. + +Task s.n. + 9-10. Dockerfile для основного сервера. Docker-compose файл для запуска контейнера сервера +вместе с БД и nginx. Организация автоматизированного развертывания бд: sql -> changelog.xml. \ No newline at end of file diff --git a/config/nginx.conf b/config/nginx.conf index 82b9e234d..4be33c9af 100644 --- a/config/nginx.conf +++ b/config/nginx.conf @@ -1,40 +1,46 @@ -# https://losst.ru/ustanovka-nginx-ubuntu-16-04 -# https://pai-bx.com/wiki/nginx/2332-useful-redirects-in-nginx/#1 -# sudo iptables -A INPUT ! -s 127.0.0.1 -p tcp -m tcp --dport 8080 -j DROP -server { - listen 80; +worker_processes 1; - # https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configuration - gzip on; - gzip_types text/css application/javascript application/json; - gzip_min_length 2048; +events { + worker_connections 1024; +} - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - root /opt/jirarush/resources; +http { + server { + listen 80; - if ($request_uri ~ ';') {return 404;} + error_log /var/log/nginx/myapp_error.log debug; # Логи ошибок для этого сервера + access_log /var/log/nginx/myapp_access.log; # Логи доступа для этого сервера - # proxy_cookie_flags ~ secure samesite=none; + # https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configuration + gzip on; + gzip_types text/css application/javascript application/json; + gzip_min_length 2048; - # static - location /static/ { - expires 30d; - access_log off; - } - location /robots.txt { - access_log off; - } + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + root /resources; - location ~ (/$|/view/|/ui/|/oauth2/) { - expires 0m; - proxy_pass http://localhost:8080; - proxy_connect_timeout 30s; - } - location ~ (/api/|/doc|/swagger-ui/|/v3/api-docs/) { - proxy_pass http://localhost:8080; - proxy_connect_timeout 150s; - } - location / { - try_files /view/404.html = 404; + if ($request_uri ~ ';') {return 404;} + + # proxy_cookie_flags ~ secure samesite=none; + # static + location /static/ { + expires 30d; + access_log off; + } + location /robots.txt { + access_log off; + } + location ~ (/$|/view/|/ui/|/oauth2/) { + expires 0m; + proxy_pass http://localhost:8080; + proxy_connect_timeout 30s; + } + location ~ (/api/|/doc|/swagger-ui/|/v3/api-docs/) { + proxy_pass http://localhost:8080; + proxy_connect_timeout 150s; + } + location / { + try_files $uri /view/404.html =404; + } + } } -} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..4ec1a349b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,62 @@ +services: + jira-app: + container_name: app + build: . + ports: + - "8080:8080" + env_file: + - properties.env + environment: + SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/jira + SPRING_DATASOURCE_USERNAME: jira + SPRING_DATASOURCE_PASSWORD: JiraRush + depends_on: + db: + condition: service_healthy + networks: + - jira-spring + volumes: + - ~/jira/logs/app:/app/logs + + db: + container_name: jira-db + image: postgres:latest + restart: always + environment: + POSTGRES_DB: jira + POSTGRES_USER: jira + POSTGRES_PASSWORD: JiraRush + ports: + - "5432:5432" + healthcheck: + test: [ "CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}" ] + interval: 5s + timeout: 3s + retries: 5 + start_period: 5s + networks: + - jira-spring + volumes: + - postgres_data:/var/lib/postgresql/data/ + - ~/jira/logs/postgres:/var/log/postgresql + + nginx: + container_name: nginx + image: nginx:latest + restart: always + volumes: + - ~/jira/logs/nginx:/var/log/nginx + - ./config/nginx.conf:/etc/nginx/nginx.conf + ports: + - "80:80" + depends_on: + - jira-app + networks: + - jira-spring + +networks: + jira-spring: + driver: bridge + +volumes: + postgres_data: diff --git a/pom.xml b/pom.xml index f6c152c68..736dccc30 100644 --- a/pom.xml +++ b/pom.xml @@ -142,6 +142,20 @@ junit-platform-launcher test + + + + org.testcontainers + postgresql + 1.20.4 + test + + + org.testcontainers + junit-jupiter + 1.20.4 + test + diff --git a/properties.env b/properties.env new file mode 100644 index 000000000..b240ee2bd --- /dev/null +++ b/properties.env @@ -0,0 +1,36 @@ +# Database env +SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/jira +SPRING_DATASOURCE_USER=jira +SPRING_DATASOURCE_PASSWORD=JiraRush + +# OAuth2 env +# GITHUB +GITHUB_CLIENT_ID=3d0d8738e65881fff266 +GITHUB_CLIENT_SECRET=0f97031ce6178b7dfb67a6af587f37e222a16120 +GITHUB_SCOPE=email + +# Google +GOOGLE_CLIENT_ID=329113642700-f8if6pu68j2repq3ef6umd5jgiliup60.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=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 +GOOGLE_SCOPE=email,profile + +# GitLab +GITLAB_CLIENT_ID=b8520a3266089063c0d8261cce36971defa513f5ffd9f9b7a3d16728fc83a494 +GITLAB_CLIENT_SECRET=e72c65320cf9d6495984a37b0f9cc03ec46be0bb6f071feaebbfe75168117004 +GITLAB_CLIENT_NAME=GitLab +GITLAB_REDIRECT_URL="{baseUrl}/login/oauth2/code/{registrationId}" +GITLAB_AUTH_GRANT_TYPE=authorization_code +GITLAB_SCOPE=read_user + +GITLAB_AUTH_URI=https://gitlab.com/oauth/authoriz +GITLAB_TOKEN_URI=https://gitlab.com/oauth/token +GITLAB_USER_INFO_URI=https://gitlab.com/api/v4/user +GITLAB_USER_NAME_ATTR=email + +# Email env +EMAIL_SMTP_AUTH=true +EMAIL_STARTTLS_ENABLE=true +EMAIL_HOST=smtp.gmail.com +EMAIL_PORT=587 +EMAIL_USERNAME=jira4jr@gmail.com +EMAIL_PASSWORD=zdfzsrqvgimldzyj diff --git a/resources/mails/email-confirmation.html b/resources/mails/email-confirmation.html index 106e6129a..d44e10cda 100644 --- a/resources/mails/email-confirmation.html +++ b/resources/mails/email-confirmation.html @@ -1,13 +1,12 @@ - - - JiraRush - подтверждение почты - - - -

-

Чтобы завершить настройку учетной записи и начать пользоваться JiraRush, подтвердите, что вы правильно указали вашу - электронную почту.

-Подтвердить почту - + + + JiraRush - confirm email + + + +

+

Before using JiraRush and complete account setup please confirm your email.

+ Confirm email + \ No newline at end of file diff --git a/resources/mails/password-reset.html b/resources/mails/password-reset.html index b37a49007..810a2fbdc 100644 --- a/resources/mails/password-reset.html +++ b/resources/mails/password-reset.html @@ -1,12 +1,12 @@ - + - JiraRush - установить новый пароль + JiraRush - setup new password -

-

-Установить пароль +

+

+Setup password \ No newline at end of file diff --git a/resources/static/css/main.css b/resources/static/css/main.css index 9aeb0c406..300338f40 100644 --- a/resources/static/css/main.css +++ b/resources/static/css/main.css @@ -72,6 +72,11 @@ } } +/*.nav-link {*/ +/* padding: 0.1rem 1rem;*/ +/* font-size: 1rem;*/ +/*}*/ + .sidebar-nav, .accordion-body, .accordion-button, .accordion-button:not(.collapsed) { background-color: var(--nav); color: darkgray; diff --git a/resources/static/fontawesome/css/all.css b/resources/static/fontawesome/css/all.css index af5980828..5652a68f6 100644 --- a/resources/static/fontawesome/css/all.css +++ b/resources/static/fontawesome/css/all.css @@ -8603,9 +8603,11 @@ readers do not read off random characters that represent icons */ content: "\f3e8"; } +/* .fa-vk:before { content: "\f189"; } +*/ .fa-untappd:before { content: "\f405"; @@ -9955,9 +9957,11 @@ readers do not read off random characters that represent icons */ content: "\f3bc"; } +/* .fa-yandex:before { content: "\f413"; } +*/ .fa-readme:before { content: "\f4d5"; @@ -10183,9 +10187,11 @@ readers do not read off random characters that represent icons */ content: "\f7c6"; } +/* .fa-yandex-international:before { content: "\f414"; } +*/ .fa-cc-amex:before { content: "\f1f3"; diff --git a/resources/view/404.html b/resources/view/404.html index 734f45370..bb37e329a 100644 --- a/resources/view/404.html +++ b/resources/view/404.html @@ -1,26 +1,23 @@ - + - Application Error + Application Error -

- -
-
-

-

404 NOT_FOUND

-

No page here

+

404 NOT_FOUND

+

No page here

-
diff --git a/resources/view/admin/users.html b/resources/view/admin/users.html index 5b772a33a..6365c8bfc 100644 --- a/resources/view/admin/users.html +++ b/resources/view/admin/users.html @@ -1,21 +1,21 @@ - +
-

Users

- +

Users

+ - - - - - - - + + + + + + + @@ -23,7 +23,6 @@

Users

First nameLast nameDisplay nameEmailRolesRegisteredActiveFirst nameLast nameDisplay nameEmailRolesRegisteredActive
-