diff --git a/README.md b/README.md index ce13fabf..f368c28d 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,38 @@ # 프로젝트에 대한 간단한 설명 ## 📌Project Overview -- HaRu는 소규모 팀을 위한 All-In-One 운영 관리 플랫폼입니다., -- 보다 효율적인 팀 운영을 위한 고민에서 시작된 HaRu는, 각자의 자리에서 치열하게 움직이는 소규모 팀들의 하루를 돕고자 합니다., -- 회의 진행 보조, SNS 이벤트 진행 관리, 팀 분위기 체크까지.HaRu는 모든 팀이 더 가치 있는 순간에 집중할 수 있도록 돕습니다., +- HaRu는 소규모 팀을 위한 All-In-One 운영 관리 플랫폼입니다. +- 보다 효율적인 팀 운영을 위한 고민에서 시작된 HaRu는, 각자의 자리에서 치열하게 움직이는 소규모 팀들의 하루를 돕고자 합니다. +- 회의 진행 보조, SNS 이벤트 진행 관리, 팀 분위기 체크까지.HaRu는 모든 팀이 더 가치 있는 순간에 집중할 수 있도록 돕습니다. ## 🚀HaRu Key Features, -- **AI 회의 진행 매니저**, - - 실시간 STT 변환, - - HaRu AI 회의 진행 질문 추천, - - 회의록 자동 생성, -- **SNS 이벤트 어시스턴트**, - - Instagram 계정 연동, - - 이벤트 URL 등록, - - 이벤트 참여자 및 당첨자 리스트 추출, -- **팀 분위기 트래커**, - - 설문지 작성 및 배포, - - 팀 분위기 리포트 자동 생성, - - 운영자 맞춤 HaRu 인사이트 제공, - +- **AI 회의 진행 매니저** + - 실시간 STT + - HaRu AI 회의 진행 질문 추천 + - 회의록 자동 생성 +- **SNS 이벤트 어시스턴트** + - Instagram 계정 연동 + - 이벤트 URL 등록 + - 이벤트 참여자 및 당첨자 리스트 추출 및 pdf, word 다운로드 +- **팀 분위기 트래커** + - 설문지 작성 및 배포 + - 팀 분위기 리포트 자동 생성 + - 운영자 맞춤 HaRu 인사이트 제공 +--- ## ⚒️Technical Overview, - **FrontEnd**: Next.js · React · TypeScript · Tailwind CSS · Storybook · Vercel, - **BackEnd**: Spring · FastAPI · Docker · MySQL · AWS(EC2, S3, RDS) · Redis --- ---- - ---- - # 사용한 브랜치 전략 및 기술 스택, 프로젝트 구조 등 ## 브랜치 전략 -Untitled - -- 위 git flow를 따름 -- release브랜치는 제외 -- dev 브랜치 왼편에 feature브랜치말고 refactor, fix브랜치도 존재 - Untitled (1) +github flow +- 위 github flow를 따름 - 브랜치 - `main` - 배포용 브랜치 @@ -77,7 +69,7 @@ | Version Control | Git | | Cloud Services | AWS Route53 / EC2 / RDS(MySQL) / S3 / Docker | | Database & Caches | MySQL / Redis | -| Deployment Tools | Nginx (프록시 서버) | +| Deployment Tools | Nginx (프록시 서버) / Github Actions | | Extra Library | Swagger / WebSockets / elevenlabs | --- diff --git a/src/main/java/com/haru/api/domain/user/controller/UserController.java b/src/main/java/com/haru/api/domain/user/controller/UserController.java index 6c9564c9..d634388a 100644 --- a/src/main/java/com/haru/api/domain/user/controller/UserController.java +++ b/src/main/java/com/haru/api/domain/user/controller/UserController.java @@ -87,7 +87,7 @@ public ApiResponse logout( @Operation(summary = "회원 정보 조회", description = "# 회원 정보 조회 API 입니다. \n" + - "현재는 jwt token을 구현하지 않아 pathvariable로 userId를 넣어주세요.추후 jwt token이 구현되면 수정하겠습니다." + "access token을 header에 입력해주세요." ) @GetMapping("/info") public ApiResponse getUserInfo( @@ -100,7 +100,7 @@ public ApiResponse getUserInfo( @Operation(summary = "회원 정보 수정", description = "# 회원 정보 수정 API 입니다. \n" + - "현재는 jwt token을 구현하지 않아 pathvariable로 userId를 넣어주세요.추후 jwt token이 구현되면 수정하겠습니다." + "access token을 header에 입력해주세요." ) @PatchMapping("/info") public ApiResponse updateUserInfo( @@ -114,8 +114,7 @@ public ApiResponse updateUserInfo( @Operation(summary = "이메일로 회원 리스트 조회", description = "# 유사한 이메일을 가진 회원을 최대 4명까지 조회하는 API 입니다. \n" + - "workspace에서 회원을 초대할 때 사용할 기능입니다. \n" + - "현재는 jwt token을 구현하지 않아 pathvariable로 userId를 넣어주세요.추후 jwt token이 구현되면 수정하겠습니다." + "workspace에서 회원을 초대할 때 사용할 기능입니다. \n" ) @GetMapping("/search") public ApiResponse> searchUsers( @@ -153,4 +152,17 @@ public ApiResponse checkOriginalP ) { return ApiResponse.onSuccess(userCommandService.checkOriginalPassword(request, user)); } + + @Operation(summary = "회원가입 후 로그인", description = + "# [v1.0 (2025-08-15)](https://www.notion.so/2505da7802c5808583b9d0b08087b8e5)" + + " 회원가입 후 로그인까지 진행하는 API입니다." + ) + @PostMapping("/signup-and-login") + public ApiResponse signUpAndLogin( + @RequestBody @Valid UserRequestDTO.SignUpRequest request + ) { + UserResponseDTO.LoginResponse response = userCommandService.signupAndLogin(request); + + return ApiResponse.onSuccess(response); + } } diff --git a/src/main/java/com/haru/api/domain/user/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/haru/api/domain/user/security/jwt/JwtAuthenticationFilter.java index 97533f27..b214cb73 100644 --- a/src/main/java/com/haru/api/domain/user/security/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/haru/api/domain/user/security/jwt/JwtAuthenticationFilter.java @@ -32,6 +32,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private static final String[] whitelist = { "/api/v1/users/signup", "/api/v1/users/login", + "/api/v1/users/signup-and-login", "/swagger-ui/**", "/v3/**", "/users/admin/**", @@ -41,6 +42,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { "/api/v1/sns/oauth/callback", "/api/v1/users/signup/same", "/favicon.ico" + }; private final JwtUtils jwtUtils; private final RedisTemplate redisTemplate; diff --git a/src/main/java/com/haru/api/domain/user/service/UserCommandService.java b/src/main/java/com/haru/api/domain/user/service/UserCommandService.java index 79a34945..30c6d905 100644 --- a/src/main/java/com/haru/api/domain/user/service/UserCommandService.java +++ b/src/main/java/com/haru/api/domain/user/service/UserCommandService.java @@ -21,4 +21,6 @@ public interface UserCommandService { UserResponseDTO.CheckEmailDuplicationResponse checkEmailDuplication(UserRequestDTO.CheckEmailDuplicationRequest request); UserResponseDTO.CheckOriginalPasswordResponse checkOriginalPassword(UserRequestDTO.CheckOriginalPasswordRequest request, User user); + + UserResponseDTO.LoginResponse signupAndLogin(UserRequestDTO.SignUpRequest request); } diff --git a/src/main/java/com/haru/api/domain/user/service/UserCommandServiceImpl.java b/src/main/java/com/haru/api/domain/user/service/UserCommandServiceImpl.java index a4c75981..c3dd87e1 100644 --- a/src/main/java/com/haru/api/domain/user/service/UserCommandServiceImpl.java +++ b/src/main/java/com/haru/api/domain/user/service/UserCommandServiceImpl.java @@ -161,4 +161,24 @@ public UserResponseDTO.CheckEmailDuplicationResponse checkEmailDuplication(UserR public UserResponseDTO.CheckOriginalPasswordResponse checkOriginalPassword(UserRequestDTO.CheckOriginalPasswordRequest request, User user) { return UserConverter.toCheckOriginalPassword(passwordEncoder.matches(request.getRequestPassword(), user.getPassword())); } + + @Override + public UserResponseDTO.LoginResponse signupAndLogin(UserRequestDTO.SignUpRequest request) { + + String password = passwordEncoder.encode(request.getPassword()); + + User foundUser = userRepository.findByEmail(request.getEmail()).orElse(null); + + if (foundUser != null) { + throw new MemberHandler(ErrorStatus.MEMBER_ALREADY_EXISTS); + } else { + User user = UserConverter.toUsers(request, password); + userRepository.save(user); + + return login(UserRequestDTO.LoginRequest.builder() + .email(request.getEmail()) + .password(request.getPassword()) + .build()); + } + } }