Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…-server into feature/37-kan-93-token
  • Loading branch information
sseoU committed Oct 30, 2024
2 parents b13ba1c + 7e8cad6 commit 4f84b71
Show file tree
Hide file tree
Showing 36 changed files with 627 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import jakarta.validation.Valid;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.LoginResponse;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.RefreshResponse;
import org.ioteatime.meonghanyangserver.auth.dto.request.EmailRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.LoginRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.SendEmailRequest;
import org.ioteatime.meonghanyangserver.common.api.Api;
import org.ioteatime.meonghanyangserver.user.dto.UserDto;
import org.ioteatime.meonghanyangserver.user.dto.response.UserSimpleResponse;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;

Expand All @@ -18,11 +19,14 @@ public interface AuthApi {
Api<Object> registerUser(@Valid @RequestBody UserDto userDto);

@Operation(summary = "인증 메일 전송")
Api<?> verifyEmail(@Valid @RequestBody SendEmailRequest email);
Api<?> verifyEmail(@Valid @RequestBody EmailRequest email);

@Operation(summary = "로그인을 합니다.")
Api<LoginResponse> login(@RequestBody @Valid LoginRequest loginRequest);

@Operation(summary = "이메일 중복을 확인 합니다.")
Api<UserSimpleResponse> duplicateEmail(@Valid @RequestBody EmailRequest email);

@Operation(summary = "토큰을 다시 생성합니다.")
Api<RefreshResponse> refreshToken(@RequestHeader("Authorization") String authorizationHeader);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.LoginResponse;
import org.ioteatime.meonghanyangserver.auth.dto.reponse.RefreshResponse;
import org.ioteatime.meonghanyangserver.auth.dto.request.EmailRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.LoginRequest;
import org.ioteatime.meonghanyangserver.auth.dto.request.SendEmailRequest;
import org.ioteatime.meonghanyangserver.auth.service.AuthService;
import org.ioteatime.meonghanyangserver.common.api.Api;
import org.ioteatime.meonghanyangserver.user.dto.UserDto;
import org.ioteatime.meonghanyangserver.user.dto.response.UserSimpleResponse;
import org.springframework.web.bind.annotation.*;

@RestController
Expand All @@ -24,11 +25,18 @@ public Api<Object> registerUser(@Valid @RequestBody UserDto userDto) {
}

@PostMapping("/email-verification")
public Api<?> verifyEmail(@Valid @RequestBody SendEmailRequest sendEmailReq) {
authService.send(sendEmailReq.email());
public Api<?> verifyEmail(@Valid @RequestBody EmailRequest emailReq) {
authService.send(emailReq.email());
return Api.OK();
}

// Email 중복 확인
@PostMapping("/check-email")
public Api<UserSimpleResponse> duplicateEmail(@Valid @RequestBody EmailRequest emailReq) {
UserSimpleResponse response = authService.verifyEmail(emailReq.email());
return Api.OK(response);
}

@Override
@PostMapping("/sign-in")
public Api<LoginResponse> login(LoginRequest loginRequest) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotNull;

public record SendEmailRequest(
public record EmailRequest(
@Valid @Email @NotNull @Schema(description = "이메일", example = "[email protected]")
String email) {}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ public void send(String email) {
googleMailClient.sendMail(email, "hello", "world");
}

public UserSimpleResponse verifyEmail(String email) {
UserEntity userEntity =
userRepository
.findByEmail(email)
.orElseThrow(() -> new ApiException(ErrorTypeCode.NULL_POINT));
return UserSimpleResponse.from(userEntity);
}

public RefreshResponse reissueAccessToken(String authorizationHeader) {
String refreshToken = jwtUtils.extractTokenFromHeader(authorizationHeader);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.ioteatime.meonghanyangserver.cctv.domain;

import jakarta.persistence.*;
import lombok.Data;
import org.ioteatime.meonghanyangserver.group.domain.GroupEntity;

@Data
@Entity
@Table(name = "cctv")
public class CctvEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JoinColumn(name = "group_id", nullable = false)
private GroupEntity group;

@Column(nullable = false, length = 20)
private String cctvNickname;

@Column(nullable = false, length = 100)
private String kvsChannelName;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.ioteatime.meonghanyangserver.common.utils;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.security.core.annotation.AuthenticationPrincipal;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "id == null ? 0L : id")
public @interface LoginMember {}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@OpenAPIDefinition(
Expand All @@ -13,4 +20,48 @@
version = "v1",
contact = @Contact(name = "서유진", email = "[email protected]")))
@Configuration
public class OpenApiConfig {}
public class OpenApiConfig {
@Bean
public OpenAPI openAPI() {
SecurityScheme apiKey =
new SecurityScheme()
.type(SecurityScheme.Type.APIKEY)
.in(SecurityScheme.In.HEADER)
.name("Authorization");

SecurityRequirement securityRequirement = new SecurityRequirement().addList("Bearer Token");

Server productionServer = new Server();
productionServer.setDescription("Production Server");
productionServer.setUrl("https://my-server-name.com");

Server localServer = new Server();
localServer.setDescription("Local Server");
localServer.setUrl("http://localhost:8080");

return new OpenAPI()
.addSecurityItem(getSecurityRequirement())
.components(getAuthComponent())
.servers(List.of(productionServer, localServer))
.components(new Components().addSecuritySchemes("Bearer Token", apiKey))
.addSecurityItem(securityRequirement);
}

private SecurityRequirement getSecurityRequirement() {
String jwt = "JWT";
return new SecurityRequirement().addList(jwt);
}

private Components getAuthComponent() {
return new Components()
.addSecuritySchemes(
"JWT",
new SecurityScheme()
.name("JWT")
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.in(SecurityScheme.In.HEADER)
.name("Authorization"));
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package org.ioteatime.meonghanyangserver.config;

import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.filter.JwtRequestFilter;
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.CsrfConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final JwtRequestFilter jwtRequestFilter;

@Bean
BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
Expand All @@ -19,14 +25,18 @@ BCryptPasswordEncoder bCryptPasswordEncoder() {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(CsrfConfigurer::disable);

http.authorizeHttpRequests(
(auth) ->
auth.requestMatchers("/open-api/**", "/swagger-ui/**", "/v3/**", "/error")
auth.requestMatchers(
"/open-api/**",
"/swagger-ui/**",
"/v3/**",
"/error",
"/api/**")
.permitAll()
.anyRequest()
.authenticated());

http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.ioteatime.meonghanyangserver.group.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.ioteatime.meonghanyangserver.common.api.Api;
import org.ioteatime.meonghanyangserver.group.dto.response.CreateGroupResponse;
import org.springframework.security.core.Authentication;

@Tag(name = "Group Api", description = "Group 관련 API 목록입니다.")
public interface GroupApi {
@Operation(summary = "그룹을 생성합니다.")
Api<CreateGroupResponse> createGroup(Authentication authentication);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.ioteatime.meonghanyangserver.group.controller;

import lombok.RequiredArgsConstructor;
import org.ioteatime.meonghanyangserver.common.api.Api;
import org.ioteatime.meonghanyangserver.group.dto.response.CreateGroupResponse;
import org.ioteatime.meonghanyangserver.group.service.GroupService;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/group")
public class GroupController implements GroupApi {
private final GroupService groupService;

@Override
@PostMapping
public Api<CreateGroupResponse> createGroup(Authentication authentication) {
CreateGroupResponse createGroupResponse = groupService.createGroup(authentication);
return Api.OK(createGroupResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.ioteatime.meonghanyangserver.group.domain;

import jakarta.persistence.*;
import java.time.LocalDateTime;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.ioteatime.meonghanyangserver.cctv.domain.CctvEntity;
import org.ioteatime.meonghanyangserver.video.entity.VideoEntity;

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Table(name = "`group`")
public class GroupEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false, length = 100)
private String groupName;

@Column(nullable = false)
private LocalDateTime createdAt;

@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private List<CctvEntity> cctvs;

@OneToMany(mappedBy = "group", cascade = CascadeType.ALL)
private List<VideoEntity> videos;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.ioteatime.meonghanyangserver.group.domain;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.ioteatime.meonghanyangserver.group.domain.enums.GroupUserRole;
import org.ioteatime.meonghanyangserver.user.domain.UserEntity;

@Data
@Entity
@Table(name = "group_user")
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class GroupUserEntity {
@EmbeddedId private GroupUserId id;

@Column(nullable = false, length = 10)
@Enumerated(value = EnumType.STRING)
private GroupUserRole role;

@ManyToOne
@MapsId("groupId")
@JoinColumn(name = "group_id")
private GroupEntity group;

@ManyToOne
@MapsId("userId")
@JoinColumn(name = "user_id", unique = true)
private UserEntity user;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.ioteatime.meonghanyangserver.group.domain;

import jakarta.persistence.Embeddable;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Embeddable
@AllArgsConstructor
@NoArgsConstructor
public class GroupUserId implements Serializable {
private Long groupId;
private Long userId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.ioteatime.meonghanyangserver.group.domain.enums;

import lombok.AllArgsConstructor;

@AllArgsConstructor
public enum GroupUserRole {
ROLE_USER("USER"),
ROLE_MASTER("MASTER");

private final String description;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.ioteatime.meonghanyangserver.group.dto.response;

import java.time.LocalDateTime;

public record CreateGroupResponse(Long groupId, String groupName, LocalDateTime createdAt) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.ioteatime.meonghanyangserver.group.mapper.group;

import java.time.LocalDateTime;
import org.ioteatime.meonghanyangserver.group.domain.GroupEntity;

public class GroupEntityMapper {
public static GroupEntity toEntity(String groupName) {
return GroupEntity.builder().groupName(groupName).createdAt(LocalDateTime.now()).build();
}
}
Loading

0 comments on commit 4f84b71

Please sign in to comment.