Skip to content

Commit

Permalink
Release/2.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
neumanf authored Mar 3, 2024
1 parent 4b0592d commit 4e9e540
Show file tree
Hide file tree
Showing 41 changed files with 845 additions and 1,005 deletions.
26 changes: 0 additions & 26 deletions .github/workflows/tests.yml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.cors(httpSecurityCorsConfigurer -> httpSecurityCorsConfigurer.configurationSource(corsConfigurationSource()))
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/url-shortener/**").permitAll()
.requestMatchers("/pastebin/paste/**").permitAll()
.anyRequest().authenticated()
)
.build();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.mally.api.pastebin;

import com.mally.api.pastebin.dtos.CreatePasteDTO;
import com.mally.api.pastebin.entities.Paste;
import com.mally.api.pastebin.services.PastebinService;
import com.mally.api.shared.rest.dtos.ApiResponseDTO;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@AllArgsConstructor
@RestController
@RequestMapping("/pastebin")
public class PastebinController {

private final PastebinService pastebinService;

@GetMapping("/paste/{slug}")
public ResponseEntity<ApiResponseDTO> findPaste(@PathVariable String slug) {
try {
Optional<Paste> paste = pastebinService.findBySlug(slug);
return paste
.map(p -> ResponseEntity
.ok()
.body(ApiResponseDTO.success("Paste found successfully.", p)))
.orElseGet(() -> ResponseEntity
.badRequest()
.body(ApiResponseDTO.error("Paste not found.", List.of())));
} catch (Exception e) {
return ResponseEntity
.internalServerError()
.body(
ApiResponseDTO.error(
"An unexpected error occurred while finding the paste.",
List.of()
)
);
}
}

@PostMapping("/paste")
public ResponseEntity<ApiResponseDTO> paste(@Valid @RequestBody CreatePasteDTO dto) {
try {
Paste paste = pastebinService.create(dto);

return ResponseEntity
.ok()
.body(ApiResponseDTO.success("Paste created successfully.", paste));
} catch (Exception e) {
return ResponseEntity
.internalServerError()
.body(
ApiResponseDTO.error(
"An unexpected error occurred while creating the paste.",
List.of()
)
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.mally.api.pastebin.dtos;

import com.mally.api.pastebin.entities.PasteSyntax;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class CreatePasteDTO {
@NotBlank
private String text;

@NotNull
private PasteSyntax syntax;
}
46 changes: 46 additions & 0 deletions apps/api/src/main/java/com/mally/api/pastebin/entities/Paste.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.mally.api.pastebin.entities;

import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.*;
import org.hibernate.annotations.ColumnDefault;
import org.springframework.data.annotation.CreatedDate;

import java.time.ZonedDateTime;

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Entity
public class Paste {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "paste_id_seq")
@SequenceGenerator(name = "paste_id_seq", sequenceName = "paste_id_seq", allocationSize = 1)
private Long id;

@Column(unique = true)
@NotNull
private String slug;

@Column
@NotNull
private String text;

@Column
@Enumerated(EnumType.STRING)
@ColumnDefault("PLAIN_TEXT")
@NotNull
private PasteSyntax syntax;

@Column(name = "created_at")
@CreatedDate
@NotNull
private ZonedDateTime createdAt;

@Column(name = "expires_at")
@NotNull
private ZonedDateTime expiresAt;
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.mally.api.pastebin.entities;

public enum PasteSyntax {
PLAIN_TEXT,
TYPESCRIPT,
CSS,
C,
CPP,
CSHARP,
JAVA,
GO,
RUST,
PYTHON,
PHP,
SHELL,
RUBY
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.mally.api.pastebin.repositories;

import com.mally.api.pastebin.entities.Paste;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface PastebinRepository extends CrudRepository<Paste, Long> {
Optional<Paste> findBySlug(String slug);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.mally.api.pastebin.services;

import com.mally.api.pastebin.dtos.CreatePasteDTO;
import com.mally.api.pastebin.entities.Paste;
import com.mally.api.pastebin.repositories.PastebinRepository;
import io.github.thibaultmeyer.cuid.CUID;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.ZonedDateTime;
import java.util.Optional;

@AllArgsConstructor
@Service
public class PastebinService {
private static final Integer EXPIRES_IN_DAYS = 7;

private final PastebinRepository pastebinRepository;

public Optional<Paste> findBySlug(String slug) {
return pastebinRepository.findBySlug(slug);
}

public Paste create(CreatePasteDTO dto) {
final ZonedDateTime now = ZonedDateTime.now();
final CUID slug = CUID.randomCUID2(22);

Paste paste = Paste.builder()
.text(dto.getText())
.syntax(dto.getSyntax())
.slug(slug.toString())
.createdAt(now)
.expiresAt(now.plusDays(EXPIRES_IN_DAYS))
.build();

return pastebinRepository.save(paste);
}
}
22 changes: 21 additions & 1 deletion apps/api/src/main/resources/application.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ bucket4j:
rate-limits:
- cache-key: getRemoteAddr()
bandwidths:
- capacity: 15
- capacity: 20
time: 1
unit: minutes
- id: url_shortener_shorten
Expand All @@ -40,6 +40,26 @@ bucket4j:
- capacity: 10
time: 1
unit: hours
- id: pastebin_get_paste
cache-name: buckets
http-response-body: '{ "status": "error", "message": "Too many requests", "data": null, "errors": [] }'
url: /pastebin/paste/.*
rate-limits:
- cache-key: getRemoteAddr()
bandwidths:
- capacity: 20
time: 1
unit: minutes
- id: pastebin_paste
cache-name: buckets
http-response-body: '{ "status": "error", "message": "Too many requests", "data": null, "errors": [] }'
url: /url-shortener/shorten
rate-limits:
- cache-key: getRemoteAddr()
bandwidths:
- capacity: 10
time: 1
unit: hours

mally:
client:
Expand Down
21 changes: 0 additions & 21 deletions apps/api/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,6 @@ bucket4j:
enabled: true
filter-config-caching-enabled: true
filter-config-cache-name: filterConfigCache
filters:
- id: url_shortener_redirect
cache-name: buckets
http-response-body: '{ "status": "error", "message": "Too many requests", "data": null, "errors": [] }'
url: /url-shortener/redirect/.*
rate-limits:
- cache-key: getRemoteAddr()
bandwidths:
- capacity: 15
time: 1
unit: minutes
- id: url_shortener_shorten
cache-name: buckets
http-response-body: '{ "status": "error", "message": "Too many requests", "data": null, "errors": [] }'
url: /url-shortener/shorten
rate-limits:
- cache-key: getRemoteAddr()
bandwidths:
- capacity: 10
time: 1
unit: hours

mally:
client:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
databaseChangeLog:
- include:
file: "db/changelog/scripts/v1-add-url-table.yaml"
- include:
file: "db/changelog/scripts/v2-add-paste-table.yaml"
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
databaseChangeLog:
- changeSet:
id: 2-1
author: Neuman F.
changes:
- createTable:
columns:
- column:
constraints:
primaryKey: true
primaryKeyName: paste_id_pkey
name: id
type: SERIAL
- column:
name: text
type: TEXT
constraints:
nullable: false
- column:
name: slug
type: VARCHAR(255)
constraints:
unique: true
nullable: false
- column:
name: syntax
type: VARCHAR(50)
constraints:
nullable: false
- column:
name: created_at
type: DATETIME
constraints:
nullable: false
defaultValueComputed: "CURRENT_TIMESTAMP"
- column:
name: expires_at
type: DATETIME
constraints:
nullable: false
tableName: paste
16 changes: 10 additions & 6 deletions apps/ui/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@
"assets": ["apps/ui/src/favicon.ico", "apps/ui/src/assets"],
"styles": ["apps/ui/src/styles.scss"],
"scripts": [],
"fileReplacements": [
{
"replace": "apps/ui/src/environment/environment.ts",
"with": "apps/ui/src/environment/environment.prod.ts"
}
"allowedCommonJsDependencies": [
"qrcode",
"highlight.js"
]
},
"configurations": {
Expand All @@ -40,7 +38,13 @@
"maximumError": "4kb"
}
],
"outputHashing": "all"
"outputHashing": "all",
"fileReplacements": [
{
"replace": "apps/ui/src/environment/environment.ts",
"with": "apps/ui/src/environment/environment.prod.ts"
}
]
},
"development": {
"buildOptimizer": false,
Expand Down
Loading

0 comments on commit 4e9e540

Please sign in to comment.