Skip to content
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

#119 Native Sublinks API #359

Open
wants to merge 131 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
139ae2a
#119 Created base controllers for native API
jgrim Dec 22, 2023
8115338
Merge branch 'main' into issue/119-native-api
jgrim Apr 23, 2024
9388d2a
Minor fix addition
Pdzly Apr 24, 2024
d340421
Added Personmapper
Pdzly Apr 24, 2024
c29a96b
Remove unnecessary blank line in PersonMapper
Pdzly Apr 25, 2024
e922f0e
Merge branch 'refs/heads/feature/353-swap-to-postgres' into issue/119…
Pdzly Apr 26, 2024
523d863
Refactor PersonService, implement JWT auth and person registration
Pdzly Apr 29, 2024
adab151
Refactor codebase to switch primitive boolean to Boolean and expand A…
Pdzly May 2, 2024
6384aba
Fixed a bug
Pdzly May 2, 2024
93f62f0
Fixed a bug
Pdzly May 2, 2024
6034093
Add find methods in repositories and enhance community service
Pdzly May 2, 2024
364454a
Implement comment service logic and enhance authorization
Pdzly May 4, 2024
7945a0a
Refactor to use Optional in CommunityRepository methods
Pdzly May 4, 2024
842ce8d
Refactor authentication and add language support to comments
Pdzly May 5, 2024
a21b35b
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly May 5, 2024
ce6b513
Refactor code for readability and consistency
Pdzly May 5, 2024
123a928
.
Pdzly May 6, 2024
0b8f6e2
Refactor authentication and update APIs
Pdzly May 6, 2024
e2523b1
Refactor controller classes and improve security
Pdzly May 7, 2024
ac83973
Renamed Enum 'ListingType' to 'SublinksListingType' and updated refer…
Pdzly May 7, 2024
505d895
Made the community controller work
Pdzly May 7, 2024
9b91168
Merge branch 'main' into issue/119-native-api
Pdzly May 8, 2024
2566d31
Fixed some more
Pdzly May 8, 2024
0d47e47
Add CommunityView and CommunityAggregates models
Pdzly May 8, 2024
05a030b
Fixed a hickup
Pdzly May 8, 2024
a76268e
Renamed some attributes
Pdzly May 8, 2024
171f0b7
Renamed some attributes
Pdzly May 8, 2024
95a7861
Revert "Renamed some attributes"
Pdzly May 10, 2024
94d7372
Revert "Fixed a hickup"
Pdzly May 10, 2024
a15c903
Revert "Add CommunityView and CommunityAggregates models"
Pdzly May 10, 2024
fb87d98
Merge remote-tracking branch 'origin/issue/119-native-api' into issue…
Pdzly May 10, 2024
9a5e686
Revert "Renamed some attributes"
Pdzly May 11, 2024
bddbff7
Revert "Renamed some attributes"
Pdzly May 11, 2024
904475b
Revert "Fixed a hickup"
Pdzly May 11, 2024
ae145c4
Revert "Add CommunityView and CommunityAggregates models"
Pdzly May 11, 2024
19a10ec
Renamed some attributes
Pdzly May 11, 2024
92b6f1c
Add community moderation features
Pdzly May 11, 2024
9288a10
Merge branch 'main' into issue/119-native-api
jgrim May 12, 2024
bc0c69f
Implement user ban and unban functionality
Pdzly May 13, 2024
99d0a69
Add CRUD features for communities and initial post functionality
Pdzly May 17, 2024
4b873d1
Refactor UserController to improve person update logic
Pdzly May 19, 2024
800de62
Update comment controller to return a list of responses
Pdzly May 19, 2024
f467971
Enhance comment and community features
Pdzly May 19, 2024
24b5209
Enhance ban logic and add community remove feature
Pdzly May 21, 2024
9e01c0b
Enhance ban logic and add community remove feature
Pdzly May 21, 2024
e3d7037
Merge remote-tracking branch 'origin/issue/119-native-api' into issue…
Pdzly May 21, 2024
f894d1f
Merge branch 'main' into issue/119-native-api
Pdzly May 22, 2024
5bbf85a
Add community and comment moderation features
Pdzly May 18, 2024
dd612d5
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly May 25, 2024
430baa2
Add comment pinning feature and refactor HTTP methods
Pdzly May 25, 2024
815c3f0
Add comment pinning functionality and refactor HTTP methods
Pdzly May 26, 2024
290cb35
Refactor application and extend functionality
Pdzly May 28, 2024
4a5a936
Merge branch 'main' into issue/119-native-api
Pdzly May 28, 2024
529971e
Refactor PersonAggregationController and add Auth checks
Pdzly May 28, 2024
c6f3615
Enhanced authorization checks and response models
Pdzly May 28, 2024
b4fe7c4
Add search functionality for instances and enhance APIs
Pdzly May 30, 2024
6fdc7b3
LINT
Pdzly May 30, 2024
1885ed3
Extend Search API to support communities, posts, and comments
Pdzly May 31, 2024
b67c2d8
Refactor code structure and add search functionality
Pdzly Jun 1, 2024
cf8726a
Optimize search functionality and improve code structure
Pdzly Jun 2, 2024
ac6a1dd
Refactor PostReport and PostLike repositories
Pdzly Jun 3, 2024
1ee4353
Add show and create methods to SublinksPostService
Pdzly Jun 3, 2024
74f00e8
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly Jun 3, 2024
3ddde7b
Enhance Post functionalities with language support and slur filter
Pdzly Jun 3, 2024
58b825a
Implement comment aggregate API and extend post functionalities
Pdzly Jun 6, 2024
f37650b
Implement comment aggregate API and extend post functionalities
Pdzly Jun 7, 2024
c450e00
Merge branch 'main' into issue/119-native-api
Pdzly Jun 7, 2024
dbf7b5d
Remove unnecessary comment from SQL migration script
Pdzly Jun 9, 2024
5a5ec06
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly Jun 10, 2024
dec9b68
Add announcement functionality to Sublinks API
Pdzly Jun 16, 2024
6977dff
Add CRUD operations and models for announcements
Pdzly Jun 17, 2024
9f157db
Add 'active' status and 'creator' field to announcements
Pdzly Jun 24, 2024
626ca5d
Refactor permissions checks in various services
Pdzly Jun 25, 2024
46def33
Add functionality for handling user metadata
Pdzly Jun 29, 2024
47c53fa
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly Jun 29, 2024
9a0a7eb
Refactor security configuration in SecurityConfig.java
Pdzly Jun 29, 2024
bd0ebc1
Rearrange JWT filter addition in SecurityConfig
Pdzly Jun 29, 2024
e99b145
Refactor SublinksPersonMetaDataMapper class
Pdzly Jun 30, 2024
d550b84
Refactor code and enhance User Data Management capabilities
Pdzly Jun 30, 2024
2ae010c
Refactor UserDataService to simplify metadata updates
Pdzly Jun 30, 2024
67b75a7
Reorder import statements in UserDataService
Pdzly Jul 2, 2024
abd18c6
Add authorization to instance config actions
Pdzly Jul 5, 2024
3769ed4
Refactor moderation models and update relevant methods
Pdzly Jul 6, 2024
b3be4a2
Add post aggregate functionality
Pdzly Jul 6, 2024
68da5cb
Update moderation actions from "remove" to "pin"
Pdzly Jul 7, 2024
4cf90cb
Add purge community operation and update delete action summary
Pdzly Jul 7, 2024
9afff74
Add post pinning, community pinning, and post purging methods
Pdzly Jul 9, 2024
015d23e
Update permissions and search functionalities in API
Pdzly Jul 15, 2024
230837a
Remove "purge" functionality and cleanup controllers
Pdzly Jul 15, 2024
0559f32
Change request mapping in SublinksPostAggregateController
Pdzly Jul 16, 2024
7c55988
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly Jul 29, 2024
c4e12ed
Enhance role management and authorization handling.
Pdzly Aug 2, 2024
3a74604
Update role management and ACL services for role expiration
Pdzly Aug 4, 2024
07c22d8
Refactor RequestResponse imports and enhance RolesController
Pdzly Aug 4, 2024
b1fe484
Merge branch 'refs/heads/main' into issue/119-native-api
Pdzly Aug 4, 2024
341daf8
Add inheritance support to roles and enhance role mapping.
Pdzly Aug 6, 2024
efb22c1
Enable Hikari pool suspension and update transactional annotations
Pdzly Aug 6, 2024
ba4f7d0
Refactor role saving to use saveAndFlush
Pdzly Aug 6, 2024
89e2b8d
Refactor role and permissions mapping for improved handling
Pdzly Aug 7, 2024
c058838
Enhance mapper configurations and simplify role permission logic
Pdzly Aug 8, 2024
d3be423
Refactor role service pagination and formatting of controller methods
Pdzly Aug 8, 2024
f364f08
Add missing newline for better readability
Pdzly Aug 8, 2024
9510654
Add purge post functionality to moderation
Pdzly Aug 9, 2024
eecb193
Implement purge post placeholder in SublinksPostService
Pdzly Aug 9, 2024
2625aae
Refactor method parameter name in purge method
Pdzly Aug 9, 2024
4172499
Add @NonNull annotations and comprehensive JavaDocs
Pdzly Aug 9, 2024
528cc2f
Adjust pagination to start from the first page.
Pdzly Aug 9, 2024
42662ce
Add SublinksCommentSortTypeMapper and refactor sort type logic
Pdzly Aug 9, 2024
a0c129d
Refactor comment entities and service methods
Pdzly Aug 11, 2024
700476e
Remove replies field from CommentResponse model
Pdzly Aug 11, 2024
15a53ea
Remove @Builder annotation from CommentResponse
Pdzly Aug 11, 2024
ebb7e41
Add instance data to PersonResponse and improve search handling
Pdzly Aug 11, 2024
eaad440
Refactor comment handling and clean up unused dependencies
Pdzly Aug 12, 2024
b79b558
Clarify comment handling in buildHierarchy method
Pdzly Aug 12, 2024
c4007d1
Fix incomplete comment in SublinksCommentService.java
Pdzly Aug 12, 2024
96cff2e
Fix typos in comment structuring logic documentation.
Pdzly Aug 12, 2024
fa2fed4
Refactor pagination logic and improve SQL query
Pdzly Aug 12, 2024
81bc5d8
Standardize API tags and refactor unauthorized exception
Pdzly Aug 12, 2024
53dd65a
Add Swagger annotations to community models
Pdzly Aug 13, 2024
66d4ee9
Add Swagger annotations to CommentResponse and UpdateComment
Pdzly Aug 14, 2024
cfa198a
Add Swagger annotations and rename model class
Pdzly Aug 14, 2024
04a03be
Fix indentation in SublinksCommentAggregateController
Pdzly Aug 19, 2024
6e4f6ef
Merge branch 'main' into issue/119-native-api
Pdzly Aug 19, 2024
9e0f129
Remove RolePermissionService from SublinksCommentModerationController
Pdzly Aug 26, 2024
2dbeae8
Add token handling to session management
Pdzly Sep 5, 2024
f0d250f
Format code for consistency in SublinksAnnouncementService
Pdzly Sep 19, 2024
1c0587a
Add JWT token to SublinksJwtPerson object
Pdzly Oct 12, 2024
caba87b
LINT
Pdzly Oct 18, 2024
b855280
Change submodule URL for 'docker' repository
Pdzly Oct 18, 2024
8de8fcd
Change submodule URL for 'docker' repository
Pdzly Oct 18, 2024
1da86ae
Add password encryption in SublinksPersonService
Pdzly Oct 18, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.sublinks.sublinksapi.api.sublinks.v1.authentication;

import com.sublinks.sublinksapi.person.entities.Person;
import com.sublinks.sublinksapi.person.repositories.PersonRepository;
import com.sublinks.sublinksapi.person.services.UserDataService;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.security.SignatureException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.core.annotation.Order;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
@RequiredArgsConstructor
@Order(1)
public class JwtFilter extends OncePerRequestFilter {

private final JwtUtil jwtUtil;
private final PersonRepository personRepository;
private final UserDataService userDataService;

@Override
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response, final FilterChain filterChain)
throws ServletException, IOException {

String authorizingToken = request.getHeader("Authorization");

if (authorizingToken == null && request.getCookies() != null) {
for (Cookie cookie : request.getCookies()) {
if (cookie.getName().equals("jwt")) {
authorizingToken = cookie.getValue();
break;
}
}

}

String token = null;
String userName = null;

try {
if (authorizingToken != null) {
if (authorizingToken.startsWith("Bearer ")) {
token = authorizingToken.substring(7);
} else {
token = authorizingToken;
}
userName = jwtUtil.extractUsername(token);
}
} catch (ExpiredJwtException | SignatureException ex) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "invalid_token");
}

if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null) {
final Optional<Person> person = personRepository.findOneByName(userName);
if (person.isEmpty()) {
throw new UsernameNotFoundException("Invalid name");
}

if (jwtUtil.validateToken(token, person.get())) {

// Add a check if token and ip was changed? To give like a "warning" to the user that he has a new ip logged into his account
userDataService.checkAndAddIpRelation(person.get(), request.getRemoteAddr(), token,
request.getHeader("User-Agent"));
final JwtPerson authenticationToken = new JwtPerson(person.get(),
person.get().getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
filterChain.doFilter(request, response);
}

@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {

return !request.getServletPath().startsWith("/api/v3");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.sublinks.sublinksapi.api.sublinks.v1.authentication;

import com.sublinks.sublinksapi.person.entities.Person;
import java.util.Collection;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

public class JwtPerson extends AbstractAuthenticationToken {

private final Person person;

public JwtPerson(final Person person, final Collection<? extends GrantedAuthority> authorities) {

super(authorities);
this.person = person;
setAuthenticated(true);
}

@Override
public Object getCredentials() {

return null;
}

@Override
public Object getPrincipal() {

return this.person;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.sublinks.sublinksapi.api.sublinks.v1.authentication;

import com.sublinks.sublinksapi.person.entities.Person;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import java.io.Serial;
import java.io.Serializable;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import javax.crypto.SecretKey;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class JwtUtil implements Serializable {

public static final long JWT_TOKEN_VALIDITY = 24 * 60 * 60;
@Serial
private static final long serialVersionUID = -2550185165626007488L;
private final String secret;

public JwtUtil(@Value("${jwt.secret}") final String secret) {

this.secret = secret;
}

public String generateToken(final Person person) {

final Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, person.getUsername());
}

public Boolean validateToken(final String token, final Person person) {

final String tokenUsername = extractUsername(token);
return (tokenUsername.equals(person.getUsername()) && !isTokenExpired(token));
}

public String extractUsername(final String token) {

return extractClaim(token, Claims::getSubject);
}

public Date extractExpiration(final String token) {

return extractClaim(token, Claims::getExpiration);
}

public <T> T extractClaim(final String token, final Function<Claims, T> claimsResolver) {

final Claims claims = extractAllClaims(token);
return claimsResolver.apply(claims);
}

private Claims extractAllClaims(final String token) {

final SecretKey key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret));
return Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload();
}

private Boolean isTokenExpired(final String token) {

return extractExpiration(token).before(new Date());
}

private String doGenerateToken(final Map<String, Object> claims, final String subject) {

final byte[] keyBytes = Decoders.BASE64.decode(secret);
final Key key = Keys.hmacShaKeyFor(keyBytes);
return Jwts.builder()
.claims(claims)
.subject(subject)
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
.signWith(key)
.compact();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.sublinks.sublinksapi.api.sublinks.v1.authentication.config;

import com.sublinks.sublinksapi.api.sublinks.v1.authentication.JwtFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

private final JwtFilter jwtFilter;

@Bean
public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception {

http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests((requests) -> requests
.anyRequest().permitAll()
)
.sessionManagement(
(sessionManagement) -> sessionManagement.sessionCreationPolicy(
SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,62 @@
package com.sublinks.sublinksapi.api.sublinks.v1.common.controllers;

import com.sublinks.sublinksapi.api.sublinks.v1.authentication.JwtPerson;
import com.sublinks.sublinksapi.person.entities.Person;
import java.util.Optional;
import java.util.function.Supplier;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ResponseStatusException;

public abstract class AbstractSublinksApiController {

/**
* Get the person object or throw a 400 Bad Request exception.
*
* @param principal JwtPerson object that contains the person as it's principal
* @return Person
* @throws ResponseStatusException Exception thrown when Person not present
*/
public Person getPersonOrThrowBadRequest(JwtPerson principal) throws ResponseStatusException {

return Optional.ofNullable(principal).map(p -> (Person) p.getPrincipal()).orElseThrow(
() -> new ResponseStatusException(HttpStatus.BAD_REQUEST));
}

/**
* Get the person object or throw a 400 Bad Request exception.
*
* @param principal JwtPerson object that contains the person as it's principal
* @return Person
* @throws ResponseStatusException Exception thrown when Person not present
*/
public <X extends Throwable> Person getPersonOrThrow(JwtPerson principal,
Supplier<? extends X> exceptionSupplier) throws X {

return Optional.ofNullable(principal).map(p -> (Person) p.getPrincipal()).orElseThrow(
exceptionSupplier);
}


/**
* Get the person object or throw a 401 Unauthorized exception.
*
* @param principal JwtPerson object that contains the person as it's principal
* @return Person
* @throws ResponseStatusException Exception thrown when Person not present
*/
public Person getPersonOrThrowUnauthorized(JwtPerson principal) throws ResponseStatusException {

return Optional.ofNullable(principal).map(p -> (Person) p.getPrincipal()).orElseThrow(
() -> new ResponseStatusException(HttpStatus.UNAUTHORIZED));
}

public Person getPerson(JwtPerson principal) {

return getOptionalPerson(principal).orElse(null);
}

public Optional<Person> getOptionalPerson(JwtPerson principal) {

return Optional.ofNullable(principal).map(p -> (Person) p.getPrincipal());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.sublinks.sublinksapi.api.sublinks.v1.common.enums;

public enum DateSort {
public enum SortOrder {
ASC,
DESC
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.sublinks.sublinksapi.api.sublinks.v1.languages.controllers;

import com.sublinks.sublinksapi.api.sublinks.v1.common.controllers.AbstractSublinksApiController;
import com.sublinks.sublinksapi.api.sublinks.v1.languages.models.LanguageResponse;
import com.sublinks.sublinksapi.instance.models.LocalInstanceContext;
import com.sublinks.sublinksapi.language.entities.Language;
import com.sublinks.sublinksapi.language.services.LanguageService;
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.tags.Tag;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.core.convert.ConversionService;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.ResponseStatusException;

@RequestMapping("api/v1/languages")
@Tag(name = "Languages", description = "Languages API")
@AllArgsConstructor
public class LanguageController extends AbstractSublinksApiController {

private final LanguageService languageService;
private final LocalInstanceContext localInstanceContext;
private final ConversionService conversionService;

@Operation(summary = "Get a list of languagesKeys")
@GetMapping
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "List of languagesKeys", useReturnTypeSchema = true)})
public List<LanguageResponse> index() {

List<Language> languages = languageService.instanceLanguages(localInstanceContext.instance());

return languages.stream().map(
language -> conversionService.convert(language, LanguageResponse.class)).toList();

}

@Operation(summary = "Get a specific language")
@GetMapping("/{id}")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Language", useReturnTypeSchema = true),
@ApiResponse(responseCode = "404", description = "Language not found")})
public LanguageResponse show(@PathVariable String id) {

List<Language> languages = languageService.instanceLanguages(localInstanceContext.instance());

Language foundLanguage = languages.stream().filter(
language -> language.getId().equals(Long.valueOf(id))).findFirst().orElseThrow(
() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "language_not_found"));

return conversionService.convert(foundLanguage, LanguageResponse.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.sublinks.sublinksapi.api.sublinks.v1.languages.mappers;

import com.sublinks.sublinksapi.api.sublinks.v1.languages.models.LangaugeResponse;
import com.sublinks.sublinksapi.authorization.services.RoleAuthorizingService;
import com.sublinks.sublinksapi.language.entities.Language;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingConstants;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, uses = {
RoleAuthorizingService.class})
public abstract class LanguageMapper implements Converter<Language, LangaugeResponse> {

@Override
@Mapping(target = "key", source = "language.name")
@Mapping(target = "name", source = "language.name")
@Mapping(target = "code", source = "language.code")
public abstract LangaugeResponse convert(@Nullable Language language);

}
Loading
Loading