Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
java-version: '23'
distribution: 'temurin'

- name: Up docker compose
run: docker compose up -d

- name: Grant execute permission for gradlew
run: chmod +x gradlew

Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ build/
.classpath
.factorypath
.project
.settings
.authSettings
.springBeans
.sts4-cache
bin/
Expand Down
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'software.amazon.awssdk:s3:2.20.0'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
40 changes: 39 additions & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
postgres:
container_name: codzilla_postgres
container_name: codzilla-postgres
image: postgres:15
ports:
- "5433:5432"
Expand All @@ -16,5 +16,43 @@ services:
timeout: 5s
retries: 5

redis:
image: redis:7.2-alpine
container_name: codzilla-redis
restart: always
ports:
- "6379:6379"
command: >
redis-server
--requirepass redis-password
--maxmemory 512mb
--maxmemory-policy allkeys-lru
--appendonly yes
volumes:
- redis_data:/data

redis-insight:
image: redis/redisinsight:latest
container_name: codzilla-redis-insight
restart: always
environment:
- RDI_PORT=5540
ports:
- "8001:5540"
depends_on:
- redis

minio:
image: minio/minio
container_name: codzilla-minio
ports:
- "9000:9000"
- "9001:9001"
environment:
MINIO_ROOT_USER: minio-user
MINIO_ROOT_PASSWORD: minio-password
command: server /data --console-address ":9001"

volumes:
redis_data:
postgres_data:
40 changes: 40 additions & 0 deletions src/main/java/com/codzilla/backend/S3/S3Configuration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.codzilla.backend.S3;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

import java.net.URI;


@Slf4j
@Configuration
@EnableConfigurationProperties(S3Settings.class)
public class S3Configuration {

@Autowired
S3Settings settings;

@Bean
public S3Client s3Client() {
log.info(settings.toString());
return S3Client.builder()
.endpointOverride(URI.create(settings.endpoint()))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(
settings.accessKey(),
settings.secretKey())))
.region(Region.of(settings.region()))
.forcePathStyle(true)
.build();
}


}
34 changes: 34 additions & 0 deletions src/main/java/com/codzilla/backend/S3/S3Initialization.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.codzilla.backend.S3;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;


@Slf4j
@Component
public class S3Initialization {

@Autowired
S3Settings settings;

@Autowired
S3Client s3Client;

@EventListener(ApplicationReadyEvent.class)
public void initBucket() {
try {
s3Client.headBucket(HeadBucketRequest.builder().bucket(settings.bucketName()).build());
log.info("Already have bucket: " + settings.bucketName());
} catch (NoSuchBucketException e) {
s3Client.createBucket(CreateBucketRequest.builder().bucket(settings.bucketName()).build());
log.info("Create bucket: " + settings.bucketName());
}
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/codzilla/backend/S3/S3Settings.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.codzilla.backend.S3;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "app.s3")
public record S3Settings(
String endpoint,
String accessKey,
String secretKey,
String region,
String bucketName

) {
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.codzilla.backend.Submissions;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;
import tools.jackson.databind.ObjectMapper;

import java.util.Optional;
import java.util.UUID;

@Repository
public class RedisSubmissionRepository implements SubmissionRepository {

@Autowired
protected ObjectMapper objectMapper;

@Autowired
RedisTemplate<String, Object> redisTemplate;

@Override
public void save(Submission submission) {
redisTemplate.opsForValue().set("submission:" + submission.id(), submission);
}

@Override
public Optional<Submission> get(UUID id) {
Object value = redisTemplate.opsForValue().get("submission:"+id);
if (value == null) return Optional.empty();
return Optional.of(objectMapper.convertValue(value, Submission.class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.codzilla.backend.Submissions;

import com.codzilla.backend.S3.S3Settings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.core.sync.ResponseTransformer;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;

import java.util.Optional;
import java.util.UUID;


@Repository
public class S3SubmissionRepository implements SubmissionRepository {
@Autowired
S3Client s3Client;

@Autowired
S3Settings settings;

@Override
public void save(Submission submission) {
s3Client.putObject(
PutObjectRequest.builder()
.contentType("text/plain")
.bucket(settings.bucketName())
.key("submissions/" + submission.id() + ".cpp")
.build(),
RequestBody.fromBytes(submission.content())
);
}

@Override
public Optional<Submission> get(UUID id) {
try {
String code = s3Client.getObject(
GetObjectRequest.builder()
.bucket(settings.bucketName())
.key("submissions/" + id + ".cpp") // todo: cpp?
.build(),
ResponseTransformer.toBytes()

).asUtf8String();
Submission result = new Submission(id, UUID.fromString(""), "".getBytes(), Language.CPP);
return Optional.of(result);
} catch (NoSuchKeyException ex) {
return Optional.empty();
}

}
}
13 changes: 13 additions & 0 deletions src/main/java/com/codzilla/backend/Submissions/Submission.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.codzilla.backend.Submissions;

import java.util.UUID;

public record Submission(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

лучше сделать

public record Submission(
  UUID id,
  UUID userId,
  byte[] content,
  Language language
) {
}

public enum Language { CPP }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а для юзеров сделать id uuid primary key и потом повесить индекс на поле email

UUID id,
UUID userId,
byte[] content,
Language language
) {
}

enum Language { CPP, PY, JAVA }
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.codzilla.backend.Submissions;


import com.codzilla.backend.S3.S3Settings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JacksonJsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;


@Slf4j
@Configuration
public class SubmissionConfiguration {

@Bean
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
var redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(redisConnectionFactory);

redisTemplate.setKeySerializer(new StringRedisSerializer());

JacksonJsonRedisSerializer<Object> serializer = new JacksonJsonRedisSerializer<>(Object.class);

redisTemplate.setValueSerializer(serializer);
return redisTemplate;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.codzilla.backend.Submissions;

import java.util.Optional;
import java.util.UUID;

public interface SubmissionRepository {


void save(Submission submission);
Optional<Submission> get(UUID id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.codzilla.backend.Submissions;

public class SubmissionService {
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.codzilla.backend.auth.JWTUtils.JWTUtils;
import com.codzilla.backend.auth.User;
import com.codzilla.backend.auth.UserService;
import com.codzilla.backend.auth.config.Settings;
import com.codzilla.backend.auth.config.AuthSettings;
import com.codzilla.backend.auth.dto.LoginRequestDTO;
import com.codzilla.backend.auth.dto.LoginResponseDTO;
import com.codzilla.backend.auth.dto.RegisterRequestDTO;
Expand All @@ -26,16 +26,16 @@
public class AuthController {
private final AuthenticationManager authManager;
private final JWTUtils jwtUtils;
private final Settings settings;
private final AuthSettings authSettings;
private final UserService userService;

@Autowired
public AuthController(AuthenticationManager authManager,
JWTUtils jwtUtils, Settings settings, UserService userService) {
JWTUtils jwtUtils, AuthSettings authSettings, UserService userService) {
this.userService = userService;
this.authManager = authManager;
this.jwtUtils = jwtUtils;
this.settings = settings;
this.authSettings = authSettings;
}

@PostMapping("/login")
Expand All @@ -51,14 +51,14 @@ public ResponseEntity<?> login(@RequestBody LoginRequestDTO request, HttpServlet
jwtCookie.setHttpOnly(true);
jwtCookie.setSecure(false);
jwtCookie.setPath("/");
jwtCookie.setMaxAge((int) settings.getRefreshTokenTtl().toSeconds());
jwtCookie.setMaxAge((int) authSettings.getRefreshTokenTtl().toSeconds());
response.addCookie(jwtCookie);

var refreshToken = jwtUtils.generateRefreshToken(auth);
Cookie refreshCookie = new Cookie("refresh_jwt", refreshToken);
refreshCookie.setPath("/");
refreshCookie.setHttpOnly(true);
refreshCookie.setMaxAge((int) settings.getRefreshTokenTtl().toSeconds());
refreshCookie.setMaxAge((int) authSettings.getRefreshTokenTtl().toSeconds());
refreshCookie.setSecure(false);
response.addCookie(refreshCookie);

Expand Down Expand Up @@ -115,7 +115,7 @@ public ResponseEntity<?> refreshToken(HttpServletRequest request, HttpServletRes
cookie.setHttpOnly(true);
cookie.setSecure(false);
cookie.setPath("/");
cookie.setMaxAge((int) settings.getRefreshTokenTtl().toSeconds());
cookie.setMaxAge((int) authSettings.getRefreshTokenTtl().toSeconds());
response.addCookie(cookie);
return ResponseEntity.ok("Jwt access was updated.");

Expand Down
Loading
Loading