Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f18c0d1
refactor: moved FacilityDTOs to new package
Kattsyn May 11, 2025
5fe34fb
refactor: moved imageDTOs to new package
Kattsyn May 11, 2025
032c1e1
refactor: move propertyDTOs to new package
Kattsyn May 11, 2025
15b1847
refactor: move reservationDTOs to new package
Kattsyn May 11, 2025
7e021cc
refactor: move categoryDTOs to new package
Kattsyn May 11, 2025
8d6b025
refactor: move requestDTOs to new package
Kattsyn May 11, 2025
54eaa22
refactor: move propertyDTOs to new package
Kattsyn May 11, 2025
7a8cfa5
refactor: move userDTOs to new package
Kattsyn May 11, 2025
f293e18
refactor: move responseDTOs to new package
Kattsyn May 11, 2025
2ecbe21
refactor: move responseDTOs to new package
Kattsyn May 11, 2025
f49a232
refactor: move requestDTOs to new package
Kattsyn May 11, 2025
3476b5b
refactor: move responseDTOs to new package
Kattsyn May 11, 2025
8b308cb
refactor: move propertyDTOs to new package
Kattsyn May 11, 2025
24a7478
refactor: move requestDTOs to new package
Kattsyn May 11, 2025
1258a46
(TP-105) chore: add web dependencies
Kattsyn May 11, 2025
ed9f066
(TP-105) feat: add openrouter vars
Kattsyn May 11, 2025
40ec2ef
(TP-105) feat: add GenerateDescriptionRequest
Kattsyn May 11, 2025
25fd590
(TP-105) feat: add GenerateDescriptionResponse
Kattsyn May 11, 2025
4cb0216
(TP-105) feat: add TooManyRequestsException
Kattsyn May 11, 2025
c9c1243
(TP-105) feat: add and impl SecurityService
Kattsyn May 11, 2025
c27abea
(TP-105) feat: add and impl AiService
Kattsyn May 11, 2025
eca7c7f
(TP-105) feat: OperRouterProperties
Kattsyn May 11, 2025
ed38654
(TP-105) feat: OpenRouterConfig
Kattsyn May 11, 2025
a8c2a93
(TP-105) feat: add and impl AiController
Kattsyn May 11, 2025
6f409b1
(TP-105) refactor: change env vars names
Kattsyn May 11, 2025
0632425
feat: add .env file creation and filling
Kattsyn May 11, 2025
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
32 changes: 32 additions & 0 deletions .github/workflows/backend-ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,38 @@ jobs:
runs-on: ubuntu-latest
needs: build-and-push-docker-image
steps:
- name: Set up SSH key
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
eval $(ssh-agent -s)
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
- name: List files
run: ls -la

- name: Create app.env file
run: |
echo "DB_NAME=${{ secrets.DB_NAME }}" >> .env
echo "DB_USER=${{ secrets.DB_USER }}" >> .env
echo "DB_PASSWORD=${{ secrets.DB_PASSWORD }}" >> .env
echo "JWT_SECRET_ACCESS=${{ secrets.JWT_SECRET_ACCESS }}" >> .env
echo "JWT_SECRET_REFRESH=${{ secrets.JWT_SECRET_REFRESH }}" >> .env
echo "JWT_EXPIRATION_TIME_IN_DAYS_REFRESH=${{ secrets.JWT_EXPIRATION_TIME_IN_DAYS_REFRESH }}" >> .env
echo "JWT_EXPIRATION_TIME_IN-MINUTES_ACCESS=${{ secrets.JWT_EXPIRATION_TIME_IN_MINUTES_ACCESS }}" >> .env
echo "MAIL_USERNAME=${{ secrets.MAIL_USERNAME }}" >> .env
echo "MAIL_PASSWORD =${{ secrets.MAIL_PASSWORD }}" >> .env
echo "COMMISSION_FOR_RENTER_IN_PERCENT=${{ secrets.COMMISSION_FOR_RENTER_IN_PERCENT }}" >> .env
echo "COMMISSION_FOR_OWNER_IN_PERCENT=${{ secrets.COMMISSION_FOR_OWNER_IN_PERCENT }}" >> .env
echo "OPENROUTER_API_URL=${{ secrets.OPENROUTER_API_URL }}" >> .env
echo "OPENROUTER_API_KEY=${{ secrets.OPENROUTER_API_KEY }}" >> .env
echo "OPENROUTER_API_MODEL=${{ secrets.OPENROUTER_API_MODEL }}" >> .env
echo "OPENROUTER_API_DEFAULT_SYSTEM_PROMPT=${{ secrets.OPENROUTER_API_DEFAULT_SYSTEM_PROMPT }}" >> .env

- name: Copy files to the server
run: |
eval $(ssh-agent -s)
scp ./.env ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:${{ secrets.APP_PATH }}/
- name: SSH Execute Commands
uses: appleboy/ssh-action@v1
with:
Expand Down
3 changes: 3 additions & 0 deletions rentplace/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
runtimeOnly 'org.flywaydb:flyway-database-postgresql:11.2.0'
implementation 'org.flywaydb:flyway-core:11.2.0'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mapstruct:mapstruct:1.5.5.Final'
implementation 'org.flywaydb:flyway-core'
implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:8.0.1'

implementation("org.springframework.boot:spring-boot-starter-mail:3.4.3")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public class JwtProvider {
public JwtProvider(
@Value("${jwt.secret.access}") String jwtAccessSecret,
@Value("${jwt.secret.refresh}") String jwtRefreshSecret,
@Value("${jwt.expiration_time_in_minutes.access}") int accessTokenExpTimeInMinutes,
@Value("${jwt.expiration_time_in_days.refresh}") int refreshTokenExpTimeInDays
@Value("${jwt.expiration-time-in-minutes.access}") int accessTokenExpTimeInMinutes,
@Value("${jwt.expiration-time-in-days.refresh}") int refreshTokenExpTimeInDays
) {
this.jwtAccessSecret = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtAccessSecret));
this.jwtRefreshSecret = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtRefreshSecret));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package kattsyn.dev.rentplace.configs;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
@EnableConfigurationProperties(OpenRouterProperties.class)
public class OpenRouterConfig {

@Bean
public WebClient webClient(OpenRouterProperties props) {
return WebClient.builder()
.baseUrl(props.url())
.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + props.key())
.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package kattsyn.dev.rentplace.configs;

import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "openrouter.api")
public record OpenRouterProperties(
@NotBlank String url,
@NotBlank String key,
@NotBlank String defaultSystemPrompt,
@NotBlank String model) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package kattsyn.dev.rentplace.controllers;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.security.auth.message.AuthException;
import jakarta.validation.Valid;
import kattsyn.dev.rentplace.dtos.ai.GenerateDescriptionRequest;
import kattsyn.dev.rentplace.dtos.ai.GenerateDescriptionResponse;
import kattsyn.dev.rentplace.services.AiService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("${api.path}/ai")
@RequiredArgsConstructor
@Tag(name = "AI Controller", description = "Интеграция с OpenRouter для работы с LLM моделями")
public class AiController {

private final AiService aiService;

@Operation(
summary = "Сгенерировать описание проекта",
description = "Принимает системный и пользовательский промпты, отсылает их в Open Router AI и возвращает сгенерированный текст."
)
@ApiResponses({
@ApiResponse(responseCode = "200", description = "Сгенерированное описание получено"),
@ApiResponse(responseCode = "400", description = "Неверные данные запроса"),
@ApiResponse(responseCode = "401", description = "Неавторизованный доступ"),
@ApiResponse(responseCode = "403", description = "Доступ запрещён"),
@ApiResponse(responseCode = "404", description = "Пользователь не найден"),
@ApiResponse(responseCode = "429", description = "Превышен лимит AI-запросов (10 в час)"),
@ApiResponse(responseCode = "500", description = "Внутренняя ошибка сервера")
})
@PostMapping(path = "/description", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@SecurityRequirement(name = "JWT")
public ResponseEntity<GenerateDescriptionResponse> generateDescription(
@Valid @ModelAttribute GenerateDescriptionRequest request
) throws AuthException {
GenerateDescriptionResponse response = new GenerateDescriptionResponse(aiService.generateDescription(request));
return ResponseEntity.ok(response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.security.auth.message.AuthException;
import kattsyn.dev.rentplace.dtos.*;
import kattsyn.dev.rentplace.dtos.requests.CodeRequest;
import kattsyn.dev.rentplace.dtos.requests.JwtRequest;
import kattsyn.dev.rentplace.dtos.requests.RefreshJwtRequest;
import kattsyn.dev.rentplace.dtos.requests.RegisterRequest;
import kattsyn.dev.rentplace.dtos.responses.CodeResponse;
import kattsyn.dev.rentplace.dtos.responses.JwtResponse;
import kattsyn.dev.rentplace.dtos.users.UserDTO;
import kattsyn.dev.rentplace.services.AuthService;
import kattsyn.dev.rentplace.services.VerificationCodeService;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import kattsyn.dev.rentplace.dtos.CategoryCreateEditDTO;
import kattsyn.dev.rentplace.dtos.CategoryDTO;
import kattsyn.dev.rentplace.dtos.ImageDTO;
import kattsyn.dev.rentplace.dtos.categories.CategoryCreateEditDTO;
import kattsyn.dev.rentplace.dtos.categories.CategoryDTO;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import kattsyn.dev.rentplace.entities.Image;
import kattsyn.dev.rentplace.services.CategoryService;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import kattsyn.dev.rentplace.dtos.FacilityCreateEditDTO;
import kattsyn.dev.rentplace.dtos.FacilityDTO;
import kattsyn.dev.rentplace.dtos.ImageDTO;
import kattsyn.dev.rentplace.dtos.facilities.FacilityCreateEditDTO;
import kattsyn.dev.rentplace.dtos.facilities.FacilityDTO;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import kattsyn.dev.rentplace.services.FacilityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import kattsyn.dev.rentplace.dtos.PropertyDTO;
import kattsyn.dev.rentplace.dtos.properties.PropertyDTO;
import kattsyn.dev.rentplace.services.FavouritesService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import kattsyn.dev.rentplace.dtos.ImageDTO;
import kattsyn.dev.rentplace.dtos.PropertyCreateEditDTO;
import kattsyn.dev.rentplace.dtos.PropertyDTO;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import kattsyn.dev.rentplace.dtos.properties.PropertyCreateEditDTO;
import kattsyn.dev.rentplace.dtos.properties.PropertyDTO;
import kattsyn.dev.rentplace.dtos.filters.PropertyFilterDTO;
import kattsyn.dev.rentplace.services.PropertyService;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import kattsyn.dev.rentplace.dtos.*;
import kattsyn.dev.rentplace.dtos.reservations.ReservationCreateEditDTO;
import kattsyn.dev.rentplace.dtos.reservations.ReservationDTO;
import kattsyn.dev.rentplace.services.ReservationService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import kattsyn.dev.rentplace.dtos.ImageDTO;
import kattsyn.dev.rentplace.dtos.UserCreateEditDTO;
import kattsyn.dev.rentplace.dtos.UserDTO;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import kattsyn.dev.rentplace.dtos.users.UserCreateEditDTO;
import kattsyn.dev.rentplace.dtos.users.UserDTO;
import kattsyn.dev.rentplace.entities.Image;
import kattsyn.dev.rentplace.services.UserService;
import lombok.RequiredArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kattsyn.dev.rentplace.dtos.ai;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class GenerateDescriptionRequest {
private String systemPrompt;

private String userPrompt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kattsyn.dev.rentplace.dtos.ai;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class GenerateDescriptionResponse {

private String generatedDescription;

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.categories;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.categories;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.facilities;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.facilities;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.images;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.properties;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.properties;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import kattsyn.dev.rentplace.dtos.users.UserDTO;
import kattsyn.dev.rentplace.dtos.categories.CategoryDTO;
import kattsyn.dev.rentplace.dtos.facilities.FacilityDTO;
import kattsyn.dev.rentplace.dtos.images.ImageDTO;
import kattsyn.dev.rentplace.enums.PropertyStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.requests;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.requests;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.requests;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.requests;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.reservations;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.reservations;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import kattsyn.dev.rentplace.dtos.users.UserDTO;
import kattsyn.dev.rentplace.dtos.properties.PropertyDTO;
import kattsyn.dev.rentplace.enums.PaymentStatus;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.responses;

import io.swagger.v3.oas.annotations.media.Schema;
import kattsyn.dev.rentplace.enums.AuthType;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.responses;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.responses;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package kattsyn.dev.rentplace.dtos;
package kattsyn.dev.rentplace.dtos.users;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
Expand Down
Loading
Loading