From c67d94a1c2198f581d89b145a84affe73467375f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=A5=ED=98=84=EC=95=A0?= Date: Wed, 16 Mar 2022 23:00:06 +0900 Subject: [PATCH 1/2] feat: google calendar api --- spring/notinote/build.gradle | 8 +- .../Notice/service/GoogleCalendarService.java | 201 ++++++++++++++++++ 2 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java diff --git a/spring/notinote/build.gradle b/spring/notinote/build.gradle index 3c25ed3..c66d775 100644 --- a/spring/notinote/build.gradle +++ b/spring/notinote/build.gradle @@ -23,13 +23,19 @@ repositories { } dependencies { + // google calendar api + implementation 'com.google.api-client:google-api-client:1.33.0' + implementation 'com.google.oauth-client:google-oauth-client-jetty:1.32.1' + implementation 'com.google.apis:google-api-services-calendar:v3-rev20211026-1.32.1' + + // jwt implementation 'io.jsonwebtoken:jjwt-api:0.11.2' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'io.jsonwebtoken:jjwt-api:0.11.2' implementation 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.2' diff --git a/spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java b/spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java new file mode 100644 index 0000000..27aa3d5 --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java @@ -0,0 +1,201 @@ +package com.answer.notinote.Notice.service; + +import com.google.api.client.auth.oauth2.Credential; +import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; +import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver; +import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow; +import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.JsonFactory; +import com.google.api.client.json.gson.GsonFactory; +import com.google.api.client.util.DateTime; +import com.google.api.client.util.store.FileDataStoreFactory; +import com.google.api.services.calendar.Calendar; +import com.google.api.services.calendar.CalendarScopes; +import com.google.api.services.calendar.model.*; +import org.springframework.stereotype.Service; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.security.GeneralSecurityException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Service +public class GoogleCalendarService { + private static final String APPLICATION_NAME = "Google Calendar API Java Quickstart"; + + private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); + + private static final String TOKENS_DIRECTORY_PATH = "tokens"; + + private static final List SCOPES = Collections.singletonList(CalendarScopes.CALENDAR); + + private static final String CREDENTIALS_FILE_PATH = "/client_secret.json"; + + private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException { + // Load client secrets. + InputStream in = GoogleCalendarService.class.getResourceAsStream(CREDENTIALS_FILE_PATH); + if (in == null) { + throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH); + } + GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); + + // Build flow and trigger user authorization request. + GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( + HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) + .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH))) + .setAccessType("offline") + .build(); + LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build(); + Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); + //returns an authorized Credential object. + return credential; + } + + public void createEvent(String summary, String description, String date) throws GeneralSecurityException, IOException { + // Build a new authorized API client service. + final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); + Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)) + .setApplicationName(APPLICATION_NAME) + .build(); + + Event event = new Event() + .setSummary(summary) + .setDescription(description); + + //date Format: "2015-05-28T09:00:00-07:00" + DateTime startDateTime = new DateTime("2015-05-28T09:00:00-07:00"); + EventDateTime start = new EventDateTime() + .setDateTime(startDateTime) + .setTimeZone("Asia/Seoul"); + event.setStart(start); + + DateTime endDateTime = new DateTime("2015-05-28T17:00:00-07:00"); + EventDateTime end = new EventDateTime() + .setDateTime(endDateTime) + .setTimeZone("Asia/Seoul"); + event.setEnd(end); + + event.setColorId("11"); + + // 리마인더를 메일 or 팝업으로 보낼 수 있음 + EventReminder[] reminderOverrides = new EventReminder[] { + new EventReminder().setMethod("email").setMinutes(24 * 60), + new EventReminder().setMethod("popup").setMinutes(10), + }; + Event.Reminders reminders = new Event.Reminders() + .setUseDefault(false) + .setOverrides(Arrays.asList(reminderOverrides)); + event.setReminders(reminders); + + String calendarId = "primary"; + event = service.events().insert(calendarId, event).execute(); + System.out.printf("Event created: %s\n", event.getHtmlLink()); + } +} + +/* + * "1": { + * "background": "#ac725e", + * "foreground": "#1d1d1d" + * }, + * "2": { + * "background": "#d06b64", + * "foreground": "#1d1d1d" + * }, + * "3": { + * "background": "#f83a22", + * "foreground": "#1d1d1d" + * }, + * "4": { + * "background": "#fa573c", + * "foreground": "#1d1d1d" + * }, + * "5": { + * "background": "#ff7537", + * "foreground": "#1d1d1d" + * }, + * "6": { + * "background": "#ffad46", + * "foreground": "#1d1d1d" + * }, + * "7": { + * "background": "#42d692", + * "foreground": "#1d1d1d" + * }, + * "8": { + * "background": "#16a765", + * "foreground": "#1d1d1d" + * }, + * "9": { + * "background": "#7bd148", + * "foreground": "#1d1d1d" + * }, + * "10": { + * "background": "#b3dc6c", + * "foreground": "#1d1d1d" + * }, + * "11": { + * "background": "#fbe983", + * "foreground": "#1d1d1d" + * }, + * "12": { + * "background": "#fad165", + * "foreground": "#1d1d1d" + * }, + * "13": { + * "background": "#92e1c0", + * "foreground": "#1d1d1d" + * }, + * "14": { + * "background": "#9fe1e7", + * "foreground": "#1d1d1d" + * }, + * "15": { + * "background": "#9fc6e7", + * "foreground": "#1d1d1d" + * }, + * "16": { + * "background": "#4986e7", + * "foreground": "#1d1d1d" + * }, + * "17": { + * "background": "#9a9cff", + * "foreground": "#1d1d1d" + * }, + * "18": { + * "background": "#b99aff", + * "foreground": "#1d1d1d" + * }, + * "19": { + * "background": "#c2c2c2", + * "foreground": "#1d1d1d" + * }, + * "20": { + * "background": "#cabdbf", + * "foreground": "#1d1d1d" + * }, + * "21": { + * "background": "#cca6ac", + * "foreground": "#1d1d1d" + * }, + * "22": { + * "background": "#f691b2", + * "foreground": "#1d1d1d" + * }, + * "23": { + * "background": "#cd74e6", + * "foreground": "#1d1d1d" + * }, + * "24": { + * "background": "#a47ae2", + * "foreground": "#1d1d1d" + * } + * }, + */ + From 6db2c801d63337c1b15cc3b9e4647a95b01028d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=A5=ED=98=84=EC=95=A0?= Date: Thu, 24 Mar 2022 01:36:37 +0900 Subject: [PATCH 2/2] feat: event entity - create event entity & CRUID - add google calendar api --- .../Child/controller/ChildController.java | 2 +- .../answer/notinote/Child/domain/Child.java | 18 +- .../answer/notinote/Child/dto/ChildDto.java | 10 ++ .../Child/dto/ChildrenResponseDto.java | 19 ++ .../notinote/Child/service/ChildService.java | 18 ++ .../Event/controller/EventController.java | 45 +++++ .../answer/notinote/Event/domain/Event.java | 58 +++++++ .../domain/repository/EventRepository.java | 9 + .../notinote/Event/dto/EventRequestDto.java | 18 ++ .../notinote/Event/dto/EventResponseDto.java | 21 +++ .../notinote/Event/service/EventService.java | 35 ++++ .../service/GoogleCalendarService.java | 162 ++++-------------- .../Event/util/BooleanToYNConverter.java | 15 ++ .../answer/notinote/Exception/ErrorCode.java | 1 + .../User/controller/UserController.java | 27 ++- .../notinote/User/domain/entity/User.java | 4 + .../notinote/User/dto/UserResponseDto.java | 7 +- .../notinote/User/service/UserService.java | 27 ++- 18 files changed, 348 insertions(+), 148 deletions(-) create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildrenResponseDto.java create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/controller/EventController.java create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/domain/Event.java create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/domain/repository/EventRepository.java create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventRequestDto.java create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventResponseDto.java create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/service/EventService.java rename spring/notinote/src/main/java/com/answer/notinote/{Notice => Event}/service/GoogleCalendarService.java (62%) create mode 100644 spring/notinote/src/main/java/com/answer/notinote/Event/util/BooleanToYNConverter.java diff --git a/spring/notinote/src/main/java/com/answer/notinote/Child/controller/ChildController.java b/spring/notinote/src/main/java/com/answer/notinote/Child/controller/ChildController.java index 16aa198..232013c 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/Child/controller/ChildController.java +++ b/spring/notinote/src/main/java/com/answer/notinote/Child/controller/ChildController.java @@ -2,8 +2,8 @@ import org.springframework.stereotype.Controller; + @Controller public class ChildController { - } diff --git a/spring/notinote/src/main/java/com/answer/notinote/Child/domain/Child.java b/spring/notinote/src/main/java/com/answer/notinote/Child/domain/Child.java index dcc9af4..986d0a6 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/Child/domain/Child.java +++ b/spring/notinote/src/main/java/com/answer/notinote/Child/domain/Child.java @@ -1,6 +1,7 @@ package com.answer.notinote.Child.domain; import com.answer.notinote.Child.dto.ChildDto; +import com.answer.notinote.Event.domain.Event; import com.answer.notinote.User.domain.entity.Timestamped; import com.answer.notinote.User.domain.entity.User; import com.fasterxml.jackson.annotation.JsonIgnore; @@ -9,6 +10,8 @@ import lombok.NoArgsConstructor; import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; @Entity @Getter @@ -32,9 +35,20 @@ public class Child extends Timestamped { @Column() Long color; - public Child (User user, ChildDto requestDto) { - this.user = user; + @OneToMany(mappedBy = "child", cascade = CascadeType.ALL) + private List events = new ArrayList<>(); + + public Child (ChildDto requestDto) { this.cname = requestDto.getCname(); this.color = requestDto.getColor(); } + + public void setUser(User user) { + this.user = user; + user.setUchildren(this); + } + + public void setEvents(Event event) { + this.events.add(event); + } } diff --git a/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildDto.java b/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildDto.java index e9cfde5..af7a34f 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildDto.java +++ b/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildDto.java @@ -2,11 +2,16 @@ import com.answer.notinote.Child.domain.Child; +import com.answer.notinote.Event.domain.Event; +import com.answer.notinote.Event.dto.EventResponseDto; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.ArrayList; +import java.util.List; + @Getter @Setter @NoArgsConstructor @AllArgsConstructor @@ -14,10 +19,15 @@ public class ChildDto { Long cid; String cname; Long color; + List events = new ArrayList<>(); public ChildDto(Child child) { this.cid = child.getCid(); this.cname = child.getCname(); this.color = child.getColor(); + + for(Event event : child.getEvents()) { + if (event.isRegistered()) this.events.add(new EventResponseDto(event)); + } } } diff --git a/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildrenResponseDto.java b/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildrenResponseDto.java new file mode 100644 index 0000000..3fa9969 --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Child/dto/ChildrenResponseDto.java @@ -0,0 +1,19 @@ +package com.answer.notinote.Child.dto; + +import lombok.Getter; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +public class ChildrenResponseDto { + int event_num = 0; + List children = new ArrayList<>(); + + public void addChild(ChildDto childDto) { + children.add(childDto); + event_num += childDto.getEvents().size(); + } +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Child/service/ChildService.java b/spring/notinote/src/main/java/com/answer/notinote/Child/service/ChildService.java index cebe663..44f84b8 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/Child/service/ChildService.java +++ b/spring/notinote/src/main/java/com/answer/notinote/Child/service/ChildService.java @@ -1,7 +1,12 @@ package com.answer.notinote.Child.service; +import com.answer.notinote.Child.domain.Child; import com.answer.notinote.Child.domain.repository.ChildRepository; +import com.answer.notinote.Child.dto.ChildDto; +import com.answer.notinote.Exception.CustomException; +import com.answer.notinote.Exception.ErrorCode; +import com.answer.notinote.User.domain.entity.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -10,4 +15,17 @@ public class ChildService { private final ChildRepository childRepository; + + public Child create(ChildDto childDto, User user) { + Child child = new Child(childDto); + child.setUser(user); + + return childRepository.save(child); + } + + public Child findById(Long id) { + return childRepository.findById(id).orElseThrow( + () -> new CustomException(ErrorCode.NOT_FOUND) + ); + } } diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/controller/EventController.java b/spring/notinote/src/main/java/com/answer/notinote/Event/controller/EventController.java new file mode 100644 index 0000000..831c63f --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/controller/EventController.java @@ -0,0 +1,45 @@ +package com.answer.notinote.Event.controller; + +import com.answer.notinote.Child.domain.Child; +import com.answer.notinote.Child.service.ChildService; +import com.answer.notinote.Event.domain.Event; +import com.answer.notinote.Event.dto.EventRequestDto; +import com.answer.notinote.Event.dto.EventResponseDto; +import com.answer.notinote.Event.service.EventService; +import com.answer.notinote.Event.service.GoogleCalendarService; +import io.swagger.models.Response; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +@RestController +@RequiredArgsConstructor +public class EventController { + + private final EventService eventService; + private final ChildService childService; + private final GoogleCalendarService calendarService; + + @PostMapping("/event") + public ResponseEntity createEvent(@RequestParam(value = "id") Long id, @RequestBody EventRequestDto requestDto) { + Child child = childService.findById(id); + + Event event = eventService.create(requestDto, child); + + return ResponseEntity.ok(new EventResponseDto(event)); + } + + @PostMapping("/event/calendar") + public ResponseEntity createEventInCalendar(@RequestParam(value = "id") Long id) throws GeneralSecurityException, IOException { + Event event = eventService.findEventById(id); + calendarService.createEvent(event); + + return ResponseEntity.ok(new EventResponseDto(event)); + } +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/domain/Event.java b/spring/notinote/src/main/java/com/answer/notinote/Event/domain/Event.java new file mode 100644 index 0000000..c1e981a --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/domain/Event.java @@ -0,0 +1,58 @@ +package com.answer.notinote.Event.domain; + +import com.answer.notinote.Child.domain.Child; +import com.answer.notinote.Event.dto.EventRequestDto; +import com.answer.notinote.Event.util.BooleanToYNConverter; +import com.answer.notinote.User.domain.entity.Timestamped; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.time.LocalDate; + +@Entity +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class Event extends Timestamped { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column + private Long eid; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "cid") + private Child child; + + @Column(length = 1000) + private String content; + + @Column + private LocalDate date; + + @Convert(converter = BooleanToYNConverter.class) + @Column(length = 1) + private boolean registered; + + @Convert(converter = BooleanToYNConverter.class) + @Column(length = 1) + private boolean highlight; + + public Event(EventRequestDto eventDto) { + this.content = eventDto.getContent(); + this.date = eventDto.getDate(); + this.registered = eventDto.getRegistered(); + this.highlight = eventDto.getHighlight(); + } + + public void setChild(Child child) { + this.child = child; + child.setEvents(this); + } + + public void register() { + this.registered = true; + } +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/domain/repository/EventRepository.java b/spring/notinote/src/main/java/com/answer/notinote/Event/domain/repository/EventRepository.java new file mode 100644 index 0000000..381fc64 --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/domain/repository/EventRepository.java @@ -0,0 +1,9 @@ +package com.answer.notinote.Event.domain.repository; + +import com.answer.notinote.Event.domain.Event; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface EventRepository extends JpaRepository { +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventRequestDto.java b/spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventRequestDto.java new file mode 100644 index 0000000..43b7492 --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventRequestDto.java @@ -0,0 +1,18 @@ +package com.answer.notinote.Event.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDate; + +@Getter @Setter +@AllArgsConstructor +@NoArgsConstructor +public class EventRequestDto { + private String content; + private LocalDate date; + private Boolean highlight; + private Boolean registered; +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventResponseDto.java b/spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventResponseDto.java new file mode 100644 index 0000000..a48320e --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/dto/EventResponseDto.java @@ -0,0 +1,21 @@ +package com.answer.notinote.Event.dto; + +import com.answer.notinote.Event.domain.Event; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDate; + +@Getter +@Setter +public class EventResponseDto { + private Long eid; + private String content; + private LocalDate date; + + public EventResponseDto(Event event) { + this.eid = event.getEid(); + this.content = event.getContent(); + this.date = event.getDate(); + } +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/service/EventService.java b/spring/notinote/src/main/java/com/answer/notinote/Event/service/EventService.java new file mode 100644 index 0000000..db6020e --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/service/EventService.java @@ -0,0 +1,35 @@ +package com.answer.notinote.Event.service; + +import com.answer.notinote.Child.domain.Child; +import com.answer.notinote.Event.domain.Event; +import com.answer.notinote.Event.domain.repository.EventRepository; +import com.answer.notinote.Event.dto.EventRequestDto; +import com.answer.notinote.Exception.CustomException; +import com.answer.notinote.Exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class EventService { + + private final EventRepository eventRepository; + + public Event create(EventRequestDto eventDto, Child child) { + Event event = new Event(eventDto); + event.setChild(child); + + return eventRepository.save(event); + } + + public void registerEvent(Long id) { + Event event = findEventById(id); + event.register(); + } + + public Event findEventById(Long id) { + return eventRepository.findById(id).orElseThrow( + () -> new CustomException(ErrorCode.NOT_FOUND) + ); + } +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java b/spring/notinote/src/main/java/com/answer/notinote/Event/service/GoogleCalendarService.java similarity index 62% rename from spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java rename to spring/notinote/src/main/java/com/answer/notinote/Event/service/GoogleCalendarService.java index 27aa3d5..d7ae1af 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/Notice/service/GoogleCalendarService.java +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/service/GoogleCalendarService.java @@ -1,4 +1,4 @@ -package com.answer.notinote.Notice.service; +package com.answer.notinote.Event.service; import com.google.api.client.auth.oauth2.Credential; import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp; @@ -27,37 +27,14 @@ @Service public class GoogleCalendarService { - private static final String APPLICATION_NAME = "Google Calendar API Java Quickstart"; - - private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); + private static final String APPLICATION_NAME = "Notinote"; private static final String TOKENS_DIRECTORY_PATH = "tokens"; - - private static final List SCOPES = Collections.singletonList(CalendarScopes.CALENDAR); - private static final String CREDENTIALS_FILE_PATH = "/client_secret.json"; + private static final List SCOPES = Collections.singletonList(CalendarScopes.CALENDAR); + private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance(); - private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException { - // Load client secrets. - InputStream in = GoogleCalendarService.class.getResourceAsStream(CREDENTIALS_FILE_PATH); - if (in == null) { - throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH); - } - GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); - - // Build flow and trigger user authorization request. - GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( - HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) - .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH))) - .setAccessType("offline") - .build(); - LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build(); - Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); - //returns an authorized Credential object. - return credential; - } - - public void createEvent(String summary, String description, String date) throws GeneralSecurityException, IOException { + public void createEvent(com.answer.notinote.Event.domain.Event eventEntity) throws GeneralSecurityException, IOException { // Build a new authorized API client service. final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT)) @@ -65,23 +42,23 @@ public void createEvent(String summary, String description, String date) throws .build(); Event event = new Event() - .setSummary(summary) - .setDescription(description); + .setSummary(eventEntity.getContent()) + .setDescription(""); //date Format: "2015-05-28T09:00:00-07:00" - DateTime startDateTime = new DateTime("2015-05-28T09:00:00-07:00"); + DateTime startDateTime = new DateTime(eventEntity.getDate().toString()+"T09:00:00-07:00"); EventDateTime start = new EventDateTime() .setDateTime(startDateTime) .setTimeZone("Asia/Seoul"); event.setStart(start); - DateTime endDateTime = new DateTime("2015-05-28T17:00:00-07:00"); + DateTime endDateTime = new DateTime(eventEntity.getDate().toString()+"T17:00:00-07:00"); EventDateTime end = new EventDateTime() .setDateTime(endDateTime) .setTimeZone("Asia/Seoul"); event.setEnd(end); - event.setColorId("11"); + event.setColorId(eventEntity.getChild().getColor().toString()); // 리마인더를 메일 or 팝업으로 보낼 수 있음 EventReminder[] reminderOverrides = new EventReminder[] { @@ -97,105 +74,24 @@ public void createEvent(String summary, String description, String date) throws event = service.events().insert(calendarId, event).execute(); System.out.printf("Event created: %s\n", event.getHtmlLink()); } -} -/* - * "1": { - * "background": "#ac725e", - * "foreground": "#1d1d1d" - * }, - * "2": { - * "background": "#d06b64", - * "foreground": "#1d1d1d" - * }, - * "3": { - * "background": "#f83a22", - * "foreground": "#1d1d1d" - * }, - * "4": { - * "background": "#fa573c", - * "foreground": "#1d1d1d" - * }, - * "5": { - * "background": "#ff7537", - * "foreground": "#1d1d1d" - * }, - * "6": { - * "background": "#ffad46", - * "foreground": "#1d1d1d" - * }, - * "7": { - * "background": "#42d692", - * "foreground": "#1d1d1d" - * }, - * "8": { - * "background": "#16a765", - * "foreground": "#1d1d1d" - * }, - * "9": { - * "background": "#7bd148", - * "foreground": "#1d1d1d" - * }, - * "10": { - * "background": "#b3dc6c", - * "foreground": "#1d1d1d" - * }, - * "11": { - * "background": "#fbe983", - * "foreground": "#1d1d1d" - * }, - * "12": { - * "background": "#fad165", - * "foreground": "#1d1d1d" - * }, - * "13": { - * "background": "#92e1c0", - * "foreground": "#1d1d1d" - * }, - * "14": { - * "background": "#9fe1e7", - * "foreground": "#1d1d1d" - * }, - * "15": { - * "background": "#9fc6e7", - * "foreground": "#1d1d1d" - * }, - * "16": { - * "background": "#4986e7", - * "foreground": "#1d1d1d" - * }, - * "17": { - * "background": "#9a9cff", - * "foreground": "#1d1d1d" - * }, - * "18": { - * "background": "#b99aff", - * "foreground": "#1d1d1d" - * }, - * "19": { - * "background": "#c2c2c2", - * "foreground": "#1d1d1d" - * }, - * "20": { - * "background": "#cabdbf", - * "foreground": "#1d1d1d" - * }, - * "21": { - * "background": "#cca6ac", - * "foreground": "#1d1d1d" - * }, - * "22": { - * "background": "#f691b2", - * "foreground": "#1d1d1d" - * }, - * "23": { - * "background": "#cd74e6", - * "foreground": "#1d1d1d" - * }, - * "24": { - * "background": "#a47ae2", - * "foreground": "#1d1d1d" - * } - * }, - */ + private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT) throws IOException { + // Load client secrets. + InputStream in = GoogleCalendarService.class.getResourceAsStream(CREDENTIALS_FILE_PATH); + if (in == null) { + throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH); + } + GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in)); + // Build flow and trigger user authorization request. + GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder( + HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES) + .setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH))) + .setAccessType("offline") + .build(); + LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build(); + Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user"); + //returns an authorized Credential object. + return credential; + } +} diff --git a/spring/notinote/src/main/java/com/answer/notinote/Event/util/BooleanToYNConverter.java b/spring/notinote/src/main/java/com/answer/notinote/Event/util/BooleanToYNConverter.java new file mode 100644 index 0000000..bdf810c --- /dev/null +++ b/spring/notinote/src/main/java/com/answer/notinote/Event/util/BooleanToYNConverter.java @@ -0,0 +1,15 @@ +package com.answer.notinote.Event.util; + +import javax.persistence.AttributeConverter; + +public class BooleanToYNConverter implements AttributeConverter { + @Override + public String convertToDatabaseColumn(Boolean bool) { + return (bool != null && bool) ? "Y" : "N"; + } + + @Override + public Boolean convertToEntityAttribute(String yn) { + return "Y".equalsIgnoreCase(yn); + } +} \ No newline at end of file diff --git a/spring/notinote/src/main/java/com/answer/notinote/Exception/ErrorCode.java b/spring/notinote/src/main/java/com/answer/notinote/Exception/ErrorCode.java index c96d176..c8b28de 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/Exception/ErrorCode.java +++ b/spring/notinote/src/main/java/com/answer/notinote/Exception/ErrorCode.java @@ -12,6 +12,7 @@ public enum ErrorCode { TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, "토큰이 존재하지 않습니다."), TOKEN_INVALID(HttpStatus.BAD_REQUEST, "액세스 토큰이 만료되었습니다."), NOT_SUPPORTED_TYPE(HttpStatus.CONFLICT, "지원하지 않는 로그인 형식입니다"), + NOT_FOUND(HttpStatus.NOT_FOUND, "해당 객체가 존재하지 않습니다."), ; private final HttpStatus httpStatus; diff --git a/spring/notinote/src/main/java/com/answer/notinote/User/controller/UserController.java b/spring/notinote/src/main/java/com/answer/notinote/User/controller/UserController.java index 007dc99..e46b7c0 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/User/controller/UserController.java +++ b/spring/notinote/src/main/java/com/answer/notinote/User/controller/UserController.java @@ -25,12 +25,17 @@ public class UserController { private final JwtTokenProvider jwtTokenProvider; private final RefreshTokenRepository refreshTokenRepository; + /** + * oauth2 로그인을 진행합니다. + * @param response + * @param token + * @return + */ @GetMapping("/login/oauth2") public ResponseEntity oauthLogin(HttpServletResponse response, @RequestHeader("Authorization") String token) { User user = userService.oauthLogin(token); issueJwtToken(response, user); - return ResponseEntity.ok(new UserResponseDto(user)); } @@ -59,10 +64,16 @@ public ResponseEntity login(HttpServletResponse response, @PathVariable("id") return ResponseEntity.ok(new UserResponseDto(user)); } + /** + * 회원을 로그아웃합니다. + * @param request + * @return + */ @DeleteMapping("/logout") public ResponseEntity logout(HttpServletRequest request) { return ResponseEntity.ok(userService.logout(request)); } + /** * 회원을 탙퇴 처리 합니다. * @param id @@ -73,6 +84,20 @@ public Long delete(@RequestParam Long id) { return userService.delete(id); } + /** + * 회원의 아이들에 대한 정보를 조회합니다. + * @param request + * @return + */ + @GetMapping("/user/children") + public ResponseEntity getChildren(HttpServletRequest request) { + String token = jwtTokenProvider.resolveToken(request); + String email = jwtTokenProvider.getUserEmail(token); + User user = userService.findUserByEmail(email); + + return ResponseEntity.ok(userService.findChildrenByUserId(user.getUid())); + } + private void issueJwtToken(HttpServletResponse response, User user) { if(user.getUroleType() == RoleType.USER) { String jwtToken = jwtTokenProvider.createToken(user.getUemail()); diff --git a/spring/notinote/src/main/java/com/answer/notinote/User/domain/entity/User.java b/spring/notinote/src/main/java/com/answer/notinote/User/domain/entity/User.java index 55fee35..75e4371 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/User/domain/entity/User.java +++ b/spring/notinote/src/main/java/com/answer/notinote/User/domain/entity/User.java @@ -48,4 +48,8 @@ public User(UserRequestDto requestDto) { this.username = requestDto.getUsername(); this.uemail = requestDto.getUemail(); } + + public void setUchildren(Child child) { + this.uchildren.add(child); + } } diff --git a/spring/notinote/src/main/java/com/answer/notinote/User/dto/UserResponseDto.java b/spring/notinote/src/main/java/com/answer/notinote/User/dto/UserResponseDto.java index 2715409..86459c1 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/User/dto/UserResponseDto.java +++ b/spring/notinote/src/main/java/com/answer/notinote/User/dto/UserResponseDto.java @@ -1,7 +1,6 @@ package com.answer.notinote.User.dto; import com.answer.notinote.Auth.data.RoleType; -import com.answer.notinote.Child.domain.Child; import com.answer.notinote.Child.dto.ChildDto; import com.answer.notinote.User.domain.entity.User; import lombok.AllArgsConstructor; @@ -32,8 +31,8 @@ public UserResponseDto(User user) { this.uprofileImg = user.getUprofileImg(); this.uroleType = user.getUroleType(); - user.getUchildren().forEach( child -> - this.uchildren.add(new ChildDto(child)) - ); + if (user.getUchildren() != null) { + user.getUchildren().forEach( child -> this.uchildren.add(new ChildDto(child))); + } } } diff --git a/spring/notinote/src/main/java/com/answer/notinote/User/service/UserService.java b/spring/notinote/src/main/java/com/answer/notinote/User/service/UserService.java index 27738f7..d820529 100644 --- a/spring/notinote/src/main/java/com/answer/notinote/User/service/UserService.java +++ b/spring/notinote/src/main/java/com/answer/notinote/User/service/UserService.java @@ -1,11 +1,14 @@ package com.answer.notinote.User.service; -import com.answer.notinote.Auth.repository.RefreshTokenRepository; +import com.answer.notinote.Auth.data.ProviderType; import com.answer.notinote.Auth.service.RefreshTokenService; import com.answer.notinote.Auth.service.OAuthService; import com.answer.notinote.Auth.token.provider.JwtTokenProvider; import com.answer.notinote.Auth.userdetails.GoogleUser; import com.answer.notinote.Child.domain.Child; +import com.answer.notinote.Child.dto.ChildDto; +import com.answer.notinote.Child.dto.ChildrenResponseDto; +import com.answer.notinote.Child.service.ChildService; import com.answer.notinote.Exception.CustomException; import com.answer.notinote.Exception.ErrorCode; import com.answer.notinote.User.dto.JoinRequestDto; @@ -18,7 +21,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; import java.util.List; @Service @@ -27,6 +29,8 @@ public class UserService { private final OAuthService oAuthService; private final RefreshTokenService refreshTokenService; + private final ChildService childService; + private final UserRepository userRepository; private final JwtTokenProvider jwtTokenProvider; @@ -41,6 +45,7 @@ public User oauthLogin(String token) { .uemail(googleUser.getEmail()) .username(googleUser.getFamilyName()) .uroleType(RoleType.GUEST) + .uproviderType(ProviderType.GOOGLE) .build(); userRepository.save(user); } @@ -52,16 +57,14 @@ public User oauthLogin(String token) { public User join(JoinRequestDto requestDto) { User user = findUserById(requestDto.getUid()); - List children = new ArrayList<>(); - requestDto.getUchildren().forEach( childDto -> - children.add(new Child(user, childDto)) - ); + requestDto.getUchildren().forEach( childDto -> { + childService.create(childDto, user); + }); if (user.getUroleType() == RoleType.GUEST) { user.setUsername(requestDto.getUsername()); user.setUlanguage(requestDto.getUlanguage()); user.setUroleType(RoleType.USER); - user.setUchildren(children); user.setUprofileImg(requestDto.getUprofileImg()); userRepository.save(user); @@ -105,6 +108,16 @@ public User findUserByEmail(String email) { ); } + public ChildrenResponseDto findChildrenByUserId(Long id) { + User user = findUserById(id); + + ChildrenResponseDto response = new ChildrenResponseDto(); + for (Child child : user.getUchildren()) { + response.addChild(new ChildDto(child)); + } + return response; + } + public List findAllUsers() { return userRepository.findAll(); }