-
Notifications
You must be signed in to change notification settings - Fork 6
Yana P. #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Yana P. #3
Changes from all commits
c47a1d4
2a01b7f
c016fb5
fedbbae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package net.hackyourfuture.hyfshop.product; | ||
|
|
||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| @Configuration | ||
| public class AppConfig { | ||
|
|
||
| @Bean | ||
| public ObjectMapper objectMapper(){ | ||
| return new ObjectMapper(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| package net.hackyourfuture.hyfshop.product; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| 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 software.amazon.awssdk.services.s3.presigner.S3Presigner; | ||
|
|
||
| import java.net.URI; | ||
|
|
||
| @Configuration | ||
| public class B2Config { | ||
|
|
||
| @Value("${b2.endpoint}") private String endpoint; | ||
| @Value("${b2.region}") private String region; | ||
| @Value("${b2.access-key}") private String accessKey; | ||
| @Value("${b2.secret-key}") private String secretKey; | ||
|
|
||
| @Bean | ||
| public S3Client s3Client() { | ||
| return S3Client.builder() | ||
| .credentialsProvider(StaticCredentialsProvider.create( | ||
| AwsBasicCredentials.create(accessKey, secretKey))) | ||
| .endpointOverride(URI.create(endpoint)) | ||
| .region(Region.of(region)) | ||
| .build(); | ||
| } | ||
|
|
||
| @Bean | ||
| public S3Presigner s3Presigner() { | ||
| return S3Presigner.builder() | ||
| .credentialsProvider(StaticCredentialsProvider.create( | ||
| AwsBasicCredentials.create(accessKey, secretKey))) | ||
| .endpointOverride(URI.create(endpoint)) | ||
| .region(Region.of(region)) | ||
| .build(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| package net.hackyourfuture.hyfshop.product; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.web.multipart.MultipartFile; | ||
| import software.amazon.awssdk.core.sync.RequestBody; | ||
| import software.amazon.awssdk.services.s3.S3Client; | ||
| import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; | ||
| import software.amazon.awssdk.services.s3.model.PutObjectRequest; | ||
| import software.amazon.awssdk.services.s3.presigner.S3Presigner; | ||
|
|
||
| import java.util.UUID; | ||
|
|
||
| @Service | ||
|
|
||
| public class FileService { | ||
|
|
||
| private final S3Client s3Client; | ||
| private final S3Presigner s3Presigner; | ||
|
|
||
| @Value("${b2.bucket}") | ||
| private String bucket; | ||
|
|
||
| @Value("${b2.endpoint}") | ||
| private String endpoint; | ||
|
|
||
| public FileService(S3Client s3Client, S3Presigner s3Presigner) { | ||
| this.s3Client = s3Client; | ||
| this.s3Presigner = s3Presigner; | ||
| } | ||
|
|
||
| public String upload(MultipartFile file) throws Exception { | ||
| String key = "uploads/" + UUID.randomUUID() + "-" + file.getOriginalFilename(); | ||
| s3Client.putObject( | ||
| PutObjectRequest.builder() | ||
| .bucket(bucket).key(key) | ||
| .contentType(file.getContentType()).build(), | ||
| RequestBody.fromInputStream(file.getInputStream(), file.getSize()) | ||
| ); | ||
| return endpoint + "/" + bucket + "/" + key; | ||
| } | ||
|
|
||
| public void delete(String imageUrl) { | ||
| String key = imageUrl.replace(endpoint + "/" + bucket + "/", ""); | ||
| s3Client.deleteObject( | ||
| DeleteObjectRequest.builder() | ||
| .bucket(bucket).key(key).build() | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,60 +1,95 @@ | ||
| package net.hackyourfuture.hyfshop.product; | ||
|
|
||
| import com.fasterxml.jackson.core.type.TypeReference; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import lombok.AllArgsConstructor; | ||
| import net.hackyourfuture.hyfshop.product.dto.ProductResponse; | ||
| import org.springframework.jdbc.core.RowMapper; | ||
| import org.springframework.jdbc.core.simple.JdbcClient; | ||
| import org.springframework.stereotype.Repository; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| @Repository | ||
| @AllArgsConstructor | ||
| public class ProductRepository { | ||
| private final JdbcClient jdbcClient; | ||
| private final ObjectMapper objectMapper = new ObjectMapper(); | ||
|
|
||
| public static final RowMapper<Product> PRODUCT_ROW_MAPPER = (rs, _) -> { | ||
| public final RowMapper<Product> PRODUCT_ROW_MAPPER = (rs, _) -> { | ||
| var product = new Product(); | ||
| product.setId(rs.getInt("id")); | ||
| product.setTitle(rs.getString("title")); | ||
| product.setPrice(rs.getBigDecimal("price")); | ||
| product.setCategory(rs.getString("category")); | ||
| product.setImageUrl(rs.getString("image_url")); | ||
|
|
||
| try{ | ||
| String json = rs.getString("details"); | ||
| if(json != null){ | ||
| product.setDetails(objectMapper.readValue(json, | ||
| new TypeReference<Map<String, Object>>() { | ||
| })); | ||
| } | ||
| }catch(Exception e){ | ||
| throw new RuntimeException(e); | ||
| } | ||
|
|
||
| return product; | ||
| }; | ||
|
|
||
| public List<Product> getAllProducts() { | ||
| return jdbcClient | ||
| .sql("SELECT id, title, price, category, image_url FROM products") | ||
| .sql("SELECT * FROM products ORDER BY id") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its not a best practice to use * in select query even though im movement all colums getting fetched |
||
| .query(PRODUCT_ROW_MAPPER) | ||
| .list(); | ||
|
|
||
| } | ||
|
|
||
| public Product findById(int id) { | ||
| return jdbcClient | ||
| .sql("SELECT id, title, price, category, image_url FROM products WHERE id = :id") | ||
| .sql("SELECT * FROM products WHERE id = :id") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Its not a best practice to use * in select query even though im movement all colums getting fetched |
||
| .param("id", id) | ||
| .query(PRODUCT_ROW_MAPPER) | ||
| .single(); | ||
| } | ||
|
|
||
| public void setImageUrl(int id, String imageUrl) { | ||
| jdbcClient.sql(""" | ||
| public Product setImageUrl(int id, String imageUrl) { | ||
| return jdbcClient.sql(""" | ||
| UPDATE products | ||
| SET image_url = :imageUrl | ||
| WHERE id = :id | ||
| RETURNING * | ||
| """) | ||
| .param("id", id) | ||
| .param("imageUrl", imageUrl) | ||
| .update(); | ||
| .param("id", id) | ||
| .query(PRODUCT_ROW_MAPPER) | ||
| .single(); | ||
| } | ||
|
|
||
| public List<Product> findByColor(String color) { | ||
| // TODO: Implement | ||
| throw new UnsupportedOperationException("Not implemented yet"); | ||
| return jdbcClient.sql(""" | ||
| SELECT * FROM products | ||
| WHERE details->>'color' = :color | ||
| OR details ->'colors' @> :colorJson::jsonb | ||
| ORDER BY id | ||
| """) | ||
| .param("color", color) | ||
| .param("colorJson", "\"" + color + "\"") | ||
| .query(PRODUCT_ROW_MAPPER) | ||
| .list(); | ||
| } | ||
|
|
||
| public Product setSize(int id, String size) { | ||
| // TODO: Implement | ||
| throw new UnsupportedOperationException("Not implemented yet"); | ||
| return jdbcClient.sql(""" | ||
| UPDATE products | ||
| SET details = jsonb_set(details, '{size}', :size::jsonb) | ||
| WHERE id = :id | ||
| RETURNING * | ||
| """) | ||
| .param("size", "\"" + size + "\"") | ||
| .param("id", id) | ||
| .query(PRODUCT_ROW_MAPPER) | ||
| .single(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@YanaP1312 , @GetMapping ("/search") got replaced by @GetMapping (params = "color").
Why does endpoint got changed here ? Does exisiting searchProducts API working ? If there is frontend intergation then it will broke it.