diff options
author | Orangerot <purple@orangerot.dev> | 2024-05-24 17:42:08 +0200 |
---|---|---|
committer | Orangerot <purple@orangerot.dev> | 2024-05-24 17:47:22 +0200 |
commit | 7fcdc1c788725f866de71fc9dfd8c4d1cb132b57 (patch) | |
tree | 89931c85ae3f149884ba02c69862558e93f01531 /20-implementierungsheft/assets/diagrams/class_after.puml |
Diffstat (limited to '20-implementierungsheft/assets/diagrams/class_after.puml')
-rw-r--r-- | 20-implementierungsheft/assets/diagrams/class_after.puml | 574 |
1 files changed, 574 insertions, 0 deletions
diff --git a/20-implementierungsheft/assets/diagrams/class_after.puml b/20-implementierungsheft/assets/diagrams/class_after.puml new file mode 100644 index 0000000..0a8f475 --- /dev/null +++ b/20-implementierungsheft/assets/diagrams/class_after.puml @@ -0,0 +1,574 @@ +@startuml +' skinparam linetype ortho +' skinparam groupInheritance 2 +allowmixing + +package authentication_api <<Frame>> { + + package controller as auth.controller <<Frame>> { + + class AuthenticationController <<@RestController>> { + + <<create>> AuthenticationController(AuthenticationService, EMailConfigProperties): + + logout(String, HttpServletResponse): HttpStatus + + registerUser(UserInfoRequest): HttpStatus + + forgotPassword(String): HttpStatus + + getDeviceList(String, HttpServletResponse): ResponseEntity<List<DeviceWrapper>> + + login(String, HttpServletResponse): HttpStatus + + deleteUser(String, PasswordRequest): HttpStatus + + changePassword(String, ChangePasswordRequest): HttpStatus + + verifyRegistration(String, String, HttpServletResponse): HttpStatus + + resetPassword(String, String, PasswordRequest): HttpStatus + } + + entity AuthenticationResponse << record >> { + + <<create>> AuthenticationResponse(String): + + token(): String + } + + entity ChangePasswordRequest << record >> { + + <<create>> ChangePasswordRequest(String, String): + + oldPassword(): String + + newPassword(): String + } + + entity DeviceWrapper << record >> { + + <<create>> DeviceWrapper(): + + <<create>> DeviceWrapper(String, String, String, int): + + id(): String + + caption(): String + + type(): String + + subscriptions(): int + } + + entity ForgotPasswordRequest << record >> { + + <<create>> ForgotPasswordRequest(String): + + email(): String + } + + entity PasswordRequest << record >> { + + <<create>> PasswordRequest(String): + + password(): String + } + + entity UserInfoRequest << record >> { + + <<create>> UserInfoRequest(String, String, String): + + password(): String + + email(): String + + username(): String + } + } + + package data_access as auth.dao <<Frame>> { + + interface AuthenticationDao <<@Repository>> { + + findByEmail(String): Optional<User> + + deleteAllByEnabledFalseAndCreatedAtLessThan(long): void + + existsByUsername(String): boolean + + findByUsername(String): Optional<User> + } + } + + package service as auth.service <<Frame>> { + + class AuthenticationService <<@Service>> { + + <<create>> AuthenticationService(AuthenticationDao, PasswordEncoder, JwtService, EMailServiceImpl, EncryptionService, InputCheckService): + + verifyRegistration(String, String): HttpStatus + + logout(String, HttpServletResponse): HttpStatus + + changePassword(String, ChangePasswordRequest): HttpStatus + + registerUser(UserInfoRequest): HttpStatus + + deleteUser(String, PasswordRequest): HttpStatus + + forgotPassword(String): HttpStatus + + resetPassword(String, String, PasswordRequest): HttpStatus + + deleteInvalidUsersOlderThan(long): void + + login(String, HttpServletResponse): HttpStatus + } + + class EMailServiceImpl <<@Service>> { + + <<create>> EMailServiceImpl(JavaMailSender, EMailConfigProperties, JwtService): + - substitutePlaceholders(String, UserDetails, String): String + + sendVerification(String, UserDetails): void + + sendPasswordReset(String, UserDetails): void + - generatePasswordResetURLString(UserDetails): String + - sendMail(String, String, String): void + - generateVerificationURLString(UserDetails): String + } + + class EncryptionService <<@Service>> { + + <<create>> EncryptionService(SecurityConfigProperties): + + saltAndHashEmail(String): String + - getSalt(): byte[] + } + + class InputCheckService <<@Service>> { + + <<create>> InputCheckService(): + + validateEmail(String): boolean + + validateUsername(String): boolean + + validatePassword(String): boolean + } + + class ResourceReader { + + <<create>> ResourceReader(): + + readFileToString(String): String + } + } +} + +package config <<Frame>> { + + class ApplicationConfig <<@Configuration>> { + + <<create>> ApplicationConfig(AuthenticationDao): + + userDetailsService(): UserDetailsService + + addInterceptors(InterceptorRegistry): void + + authenticationManager(AuthenticationConfiguration): AuthenticationManager + + passwordEncoder(): PasswordEncoder + + corsConfigurer(): WebMvcConfigurer + + authenticationProvider(): AuthenticationProvider + } + + class AuthenticationValidatorInterceptor { + + <<create>> AuthenticationValidatorInterceptor(): + - extractUsernamePathVariable(HttpServletRequest): String? + + preHandle(HttpServletRequest, HttpServletResponse, Object): boolean + } + + entity EMailConfigProperties << record >> { + + <<create>> EMailConfigProperties(String, String, String): + + resetUrlPath(): String + + verificationUrl(): String + + dashboardBaseUrl(): String + } + + class JwtAuthenticationFilter <<@Component>> { + + <<create>> JwtAuthenticationFilter(JwtService, UserDetailsService): + # doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain): void + - authenticateIfValid(Cookie, HttpServletRequest): void + } + + class JwtService <<@Service>> { + + <<create>> JwtService(SecurityConfigProperties): + + generateUrlTokenString(UserDetails): String + + isTokenValid(String, UserDetails): boolean + + generateAccessTokenString(UserDetails): String + + extractUsername(String): String + + extractClaim(String, Function<Claims, T>): T + - isTokenExpired(String): boolean + + generateTokenString(Map<String, Object>, UserDetails, long): String + - extractExpiration(String): Date + - extractAllClaims(String): Claims + - getSigningKey(): Key + } + + class SecurityConfig <<@Configuration>> { + + <<create>> SecurityConfig(JwtAuthenticationFilter, AuthenticationProvider): + ~ corsConfigurationSource(): CorsConfigurationSource + + securityFilterChain(HttpSecurity): SecurityFilterChain + } + + entity SecurityConfigProperties << record >> { + + <<create>> SecurityConfigProperties(String, String): + + jwtSigningKey(): String + + emailSigningKey(): String + } +} + +package episode_actions_api <<Frame>> { + + package controller as episode.controller <<Frame>> { + + class EpisodeActionController <<@RestController>> { + + <<create>> EpisodeActionController(EpisodeActionService): + + addEpisodeActions(String, List<EpisodeActionPost>): ResponseEntity<UpdateURLsWrapper> + + getEpisodeActionsOfPodcast(String, String): ResponseEntity<EpisodeActionGetResponse> + + getEpisodeActions(String): ResponseEntity<EpisodeActionGetResponse> + + getEpisodeActionsSince(String, long): ResponseEntity<EpisodeActionGetResponse> + + getEpisodeActionsOfPodcastSince(String, String, long): ResponseEntity<EpisodeActionGetResponse> + } + + class EpisodeActionGetResponse { + + <<create>> EpisodeActionGetResponse(List<EpisodeActionPost>): + + getTimestamp(): long + + getActions(): List<EpisodeActionPost> + } + + class EpisodeActionPost { + + <<create>> EpisodeActionPost(): + + <<create>> EpisodeActionPost(String, String, String, String, int, EpisodeAction): + + equals(Object): boolean + + hashCode(): int + + builder(): EpisodeActionPostBuilder + + getPodcastURL(): String + + getEpisodeURL(): String + + getTitle(): String + + getGuid(): String + + setGuid(String): void + + setEpisodeAction(EpisodeAction): void + + setTotal(int): void + + getTotal(): int + + setTitle(String): void + # canEqual(Object): boolean + + getEpisodeAction(): EpisodeAction + + toString(): String + + setPodcastURL(String): void + + setEpisodeURL(String): void + } + } + + package data_access as episode.dao <<Frame>> { + + interface EpisodeActionDao <<@Repository>> { + + findByUserUsernameAndEpisodeSubscriptionUrl(String, String): List<EpisodeAction> + + delete(EpisodeAction): void + + findByUserUsernameAndTimestampGreaterThanEqual(String, LocalDateTime): List<EpisodeAction> + + findByUserUsername(String): List<EpisodeAction> + + findByUserAndEpisodeUrlAndAction(User, String, Action): Optional<EpisodeAction> + + findByUserUsernameAndTimestampGreaterThanEqualAndEpisodeSubscriptionUrl(String, LocalDateTime, String): List<EpisodeAction> + + deleteByUserUsernameAndEpisodeSubscriptionUrl(String, String): void + + existsByUserAndEpisodeUrlAndAction(User, String, Action): boolean + } + + interface EpisodeDao <<@Repository>> { + + existsByGuid(String): boolean + + findByUrl(String): Optional<Episode> + + existsByUrl(String): boolean + + findByGuid(String): Optional<Episode> + } + } + + package service as episode.service <<Frame>> { + + class EpisodeActionService <<@Service>> { + + <<create>> EpisodeActionService(EpisodeActionDao, EpisodeDao, AuthenticationDao, SubscriptionDao, SubscriptionActionDao, RSSParser): + - episodeActionPostsToEpisodeActions(User, List<EpisodeActionPost>): List<EpisodeAction> + - createEpisode(EpisodeActionPost): Episode + + getEpisodeActionsOfPodcastSince(String, String, long): List<EpisodeActionPost> + - getEpisodeFromDatabase(EpisodeActionPost): Episode + - addEpisodeActionsToDatabase(User, List<EpisodeAction>): void + - addNewestEpisodeActionToDatabase(User, EpisodeAction): void + - episodeActionsToEpisodeActionPosts(List<EpisodeAction>): List<EpisodeActionPost> + - addEpisodeActionToDatabase(User, EpisodeAction): void + + getEpisodeActionsSince(String, long): List<EpisodeActionPost> + - episodeActionPostToEpisodeAction(User, EpisodeActionPost): EpisodeAction + + getEpisodeActions(String): List<EpisodeActionPost> + + getEpisodeActionsOfPodcast(String, String): List<EpisodeActionPost> + + addEpisodeActions(String, List<EpisodeActionPost>): void + } + } +} + +package model <<Frame>> { + + enum Action << enumeration >> { + + <<create>> Action(): + + valueOf(String): Action + + getJsonProperty(): String + + values(): Action[] + } + + class Episode <<@Entity>> { + + <<create>> Episode(): + + <<create>> Episode(Long, String, String, String, int, Subscription, List<EpisodeAction>): + + getId(): Long + # canEqual(Object): boolean + + getGuid(): String + + setTitle(String): void + + builder(): EpisodeBuilder + + setTotal(int): void + + setGuid(String): void + + equals(Object): boolean + + setSubscription(Subscription): void + + getUrl(): String + + getTitle(): String + + toString(): String + + getTotal(): int + + setUrl(String): void + + setEpisodeActions(List<EpisodeAction>): void + + getSubscription(): Subscription + + getEpisodeActions(): List<EpisodeAction> + + setId(Long): void + + hashCode(): int + } + + class EpisodeAction <<@Entity>> { + + <<create>> EpisodeAction(Long, User, Episode, LocalDateTime, Action, int, int): + + <<create>> EpisodeAction(): + + getEpisode(): Episode + + setEpisode(Episode): void + + setPosition(int): void + # canEqual(Object): boolean + + setUser(User): void + + setStarted(int): void + + getId(): Long + + getUser(): User + + getTimestamp(): LocalDateTime + + getAction(): Action + + getStarted(): int + + hashCode(): int + + setTimestamp(LocalDateTime): void + + equals(Object): boolean + + getPosition(): int + + builder(): EpisodeActionBuilder + + setId(Long): void + + setAction(Action): void + + toString(): String + + toEpisodeActionPost(): EpisodeActionPost + } + + enum Role << enumeration >> { + + <<create>> Role(): + + valueOf(String): Role + + toString(): String + + values(): Role[] + } + + class Subscription <<@Entity>> { + + <<create>> Subscription(): + + <<create>> Subscription(Long, String, String, long, List<SubscriptionAction>, List<Episode>): + + setId(Long): void + + getId(): Long + + equals(Object): boolean + + getUrl(): String + + hashCode(): int + + builder(): SubscriptionBuilder + # canEqual(Object): boolean + + toString(): String + + getTitle(): String + + getTimestamp(): long + + setEpisodes(List<Episode>): void + + getSubscriptionActions(): List<SubscriptionAction> + + getEpisodes(): List<Episode> + + setSubscriptionActions(List<SubscriptionAction>): void + + setUrl(String): void + + setTitle(String): void + + setTimestamp(long): void + + addEpisode(Episode): void + } + + class SubscriptionAction <<@Entity>> { + + <<create>> SubscriptionAction(): + + <<create>> SubscriptionAction(int, User, long, Subscription, boolean): + + equals(Object): boolean + + getId(): int + + getUser(): User + + getTimestamp(): long + + getSubscription(): Subscription + + isAdded(): boolean + # canEqual(Object): boolean + + setId(int): void + + hashCode(): int + + setUser(User): void + + toString(): String + + builder(): SubscriptionActionBuilder + + setTimestamp(long): void + + setSubscription(Subscription): void + + setAdded(boolean): void + } + + class User <<@Entity>> { + + <<create>> User(Long, String, String, String, boolean, long, Role, List<SubscriptionAction>, List<EpisodeAction>): + + <<create>> User(): + + getId(): Long + + setCreatedAt(long): void + + getUsername(): String + + builder(): UserBuilder + + toString(): String + + getEmail(): String + + setPassword(String): void + + setSubscriptionActions(List<SubscriptionAction>): void + + equals(Object): boolean + + getPassword(): String + + setEmail(String): void + + setRole(Role): void + + isEnabled(): boolean + + setUsername(String): void + + getCreatedAt(): long + + getRole(): Role + + getSubscriptionActions(): List<SubscriptionAction> + # canEqual(Object): boolean + + hashCode(): int + + setEnabled(boolean): void + + setEpisodeActions(List<EpisodeAction>): void + + getEpisodeActions(): List<EpisodeAction> + + setId(Long): void + + getAuthorities(): Collection<GrantedAuthority> + + isCredentialsNonExpired(): boolean + + isAccountNonLocked(): boolean + + isAccountNonExpired(): boolean + } +} + +package subscriptions_api <<Frame>> { + + package controller as subscription.controller <<Frame>> { + + class SubscriptionController <<@RestController>> { + + <<create>> SubscriptionController(SubscriptionService): + + applySubscriptionDelta(String, String, SubscriptionDelta): ResponseEntity<UpdateURLsWrapper> + + getSubscriptions(String, String, String): ResponseEntity<List<String>> + + getSubscriptionDelta(String, String, long): ResponseEntity<SubscriptionDelta> + + getTitles(String): ResponseEntity<List<SubscriptionTitles>> + + uploadSubscriptions(String, String, List<String>): ResponseEntity<String> + } + + class SubscriptionDelta { + + <<create>> SubscriptionDelta(List<String>, List<String>): + + getTimestamp(): long + + getRemove(): List<String> + + getAdd(): List<String> + } + + entity SubscriptionTitles << record >> { + + <<create>> SubscriptionTitles(Subscription, List<EpisodeActionPost>): + + episodes(): List<EpisodeActionPost> + + subscription(): Subscription + } + } + + package data_access as subscription.dao <<Frame>> { + + interface SubscriptionActionDao <<@Repository>> { + + findByUserUsernameAndAddedTrue(String): List<SubscriptionAction> + + existsByUserAndSubscription(User, Subscription): boolean + + findByUserAndSubscription(User, Subscription): Optional<SubscriptionAction> + + findByUserUsernameAndTimestampGreaterThanEqual(String, long): List<SubscriptionAction> + + findByUserUsernameAndAddedTrueAndTimestampGreaterThanEqual(String, long): List<SubscriptionAction> + } + + interface SubscriptionDao <<@Repository>> { + + findByUrl(String): Optional<Subscription> + + existsByUrl(String): boolean + } + } + + package service as subscription.service <<Frame>> { + + class SubscriptionService <<@Service>> { + + <<create>> SubscriptionService(RSSParser, AuthenticationDao, SubscriptionDao, SubscriptionActionDao, EpisodeActionDao, EpisodeActionService): + + getTitles(String): List<SubscriptionTitles> + + getSubscriptions(String): List<String> + + applySubscriptionDelta(String, SubscriptionDelta): int + + getSubscriptionDelta(String, long): SubscriptionDelta + + uploadSubscriptions(String, List<String>): int + } + } +} + +package util <<Frame>> { + + class RSSParser <<@Component>> { + + <<create>> RSSParser(EpisodeDao, SubscriptionDao): + + validate(Subscription): void + - parseTimeToSeconds(String): int + - parseEpisode(SyndEntry, Subscription): Episode + - saveEpisodes(List<Episode>): void + - fetchSubscriptionFeed(Subscription): Map<String, Episode>? + - saveSubscription(Subscription): void + - deleteSubscription(Subscription): void + - getFetchedEpisodeForURL(String, Map<String, Episode>): Episode + - deleteEpisodes(List<Episode>): void + } + + class Scheduler <<@Component>> { + + <<create>> Scheduler(): + + clean(): void + } + + class UpdateURLsWrapper { + + <<create>> UpdateURLsWrapper(): + + getTimestamp(): long + + getUpdateURLs(): List<Pair<String, String>> + } +} + +class ServerApplication <<@SpringBootApplication>> { + + <<create>> ServerApplication(): + + main(String[]): void +} + +database Datenbank +Datenbank <-[hidden]d- subscriptions_api +Datenbank <-[hidden]d- episode_actions_api +Datenbank <-[hidden]d- authentication_api +() SQL as SQLSub +() SQL as SQLAuth +() SQL as SQLEpisode + +Datenbank -- SQLSub +Datenbank -- SQLAuth +Datenbank -- SQLEpisode + +SubscriptionController ..o ServerApplication +AuthenticationController ..o ServerApplication +EpisodeActionController ..o ServerApplication + +ServerApplication --() HTTP + +SQLSub )-- SubscriptionActionDao: JPA +SQLSub )-- SubscriptionDao: JPA +SQLAuth )-- AuthenticationDao: JPA +SQLEpisode )-- EpisodeActionDao: JPA +SQLEpisode )-- EpisodeDao: JPA + +model .o Datenbank: ORM (User, SubscriptionAction, Subscription, EpisodeAction, Episode) +' Datenbank o.. Subscription: ORM +' Datenbank o.. SubscriptionAction: ORM +' Datenbank o.. Episode: ORM +' Datenbank o.. EpisodeAction: ORM +' Datenbank o.. User: ORM + +ApplicationConfig "1" *-[#595959,plain]-> "authenticationDao\n1" AuthenticationDao +ApplicationConfig -[#595959,dashed]-> AuthenticationValidatorInterceptor : "«create»" +AuthenticationController "1" *-[#595959,plain]-> "authenticationService\n1" AuthenticationService +AuthenticationController -[#595959,dashed]-> DeviceWrapper : "«create»" +AuthenticationController "1" *-[#595959,plain]-> "eMailConfigProperties\n1" EMailConfigProperties +AuthenticationService "1" *-[#595959,plain]-> "authenticationDao\n1" AuthenticationDao +AuthenticationService "1" *-[#595959,plain]-> "eMailService\n1" EMailServiceImpl +AuthenticationService "1" *-[#595959,plain]-> "encryptionService\n1" EncryptionService +AuthenticationService "1" *-[#595959,plain]-> "inputCheckService\n1" InputCheckService +AuthenticationService "1" *-[#595959,plain]-> "jwtService\n1" JwtService +AuthenticationService "1" *-[#595959,plain]-> "DEFAULT_USER\n1" Role +EMailServiceImpl "1" *-[#595959,plain]-> "eMailConfigProperties\n1" EMailConfigProperties +EMailServiceImpl "1" *-[#595959,plain]-> "jwtService\n1" JwtService +EncryptionService "1" *-[#595959,plain]-> "securityConfigProperties\n1" SecurityConfigProperties +Episode "1" *-[#595959,plain]-> "episodeActions\n*" EpisodeAction +Episode "1" *-[#595959,plain]-> "subscription\n1" Subscription +EpisodeAction "1" *-[#595959,plain]-> "action\n1" Action +EpisodeAction "1" *-[#595959,plain]-> "episode\n1" Episode +EpisodeAction -[#595959,dashed]-> EpisodeActionPost : "«create»" +EpisodeAction "1" *-[#595959,plain]-> "user\n1" User +EpisodeActionController -[#595959,dashed]-> EpisodeActionGetResponse : "«create»" +EpisodeActionController "1" *-[#595959,plain]-> "episodeActionService\n1" EpisodeActionService +EpisodeActionController -[#595959,dashed]-> UpdateURLsWrapper : "«create»" +EpisodeActionGetResponse "1" *-[#595959,plain]-> "actions\n*" EpisodeActionPost +EpisodeActionPost "1" *-[#595959,plain]-> "episodeAction\n1" EpisodeAction +EpisodeActionService "1" *-[#595959,plain]-> "authenticationDao\n1" AuthenticationDao +EpisodeActionService "1" *-[#595959,plain]-> "episodeActionDao\n1" EpisodeActionDao +EpisodeActionService "1" *-[#595959,plain]-> "episodeDao\n1" EpisodeDao +EpisodeActionService "1" *-[#595959,plain]-> "rssParser\n1" RSSParser +EpisodeActionService -[#595959,dashed]-> Subscription : "«create»" +EpisodeActionService "1" *-[#595959,plain]-> "subscriptionActionDao\n1" SubscriptionActionDao +EpisodeActionService "1" *-[#595959,plain]-> "subscriptionDao\n1" SubscriptionDao +JwtAuthenticationFilter "1" *-[#595959,plain]-> "jwtService\n1" JwtService +JwtService "1" *-[#595959,plain]-> "securityConfigProperties\n1" SecurityConfigProperties +RSSParser "1" *-[#595959,plain]-> "episodeDao\n1" EpisodeDao +RSSParser "1" *-[#595959,plain]-> "subscriptionDao\n1" SubscriptionDao +Scheduler "1" *-[#595959,plain]-> "authenticationService\n1" AuthenticationService +SecurityConfig "1" *-[#595959,plain]-> "jwtAuthFilter\n1" JwtAuthenticationFilter +Subscription "1" *-[#595959,plain]-> "episodes\n*" Episode +Subscription "1" *-[#595959,plain]-> "subscriptionActions\n*" SubscriptionAction +SubscriptionAction "1" *-[#595959,plain]-> "subscription\n1" Subscription +SubscriptionAction "1" *-[#595959,plain]-> "user\n1" User +SubscriptionController "1" *-[#595959,plain]-> "subscriptionService\n1" SubscriptionService +SubscriptionController -[#595959,dashed]-> UpdateURLsWrapper : "«create»" +SubscriptionService "1" *-[#595959,plain]-> "authenticationDao\n1" AuthenticationDao +SubscriptionService "1" *-[#595959,plain]-> "episodeActionDao\n1" EpisodeActionDao +SubscriptionService "1" *-[#595959,plain]-> "episodeActionService\n1" EpisodeActionService +SubscriptionService "1" *-[#595959,plain]-> "rssParser\n1" RSSParser +SubscriptionService "1" *-[#595959,plain]-> "subscriptionActionDao\n1" SubscriptionActionDao +SubscriptionService "1" *-[#595959,plain]-> "subscriptionDao\n1" SubscriptionDao +SubscriptionService -[#595959,dashed]-> SubscriptionDelta : "«create»" +SubscriptionService -[#595959,dashed]-> SubscriptionTitles : "«create»" +SubscriptionTitles "1" *-[#595959,plain]-> "subscription\n1" Subscription +User "1" *-[#595959,plain]-> "episodeActions\n*" EpisodeAction +User "1" *-[#595959,plain]-> "role\n1" Role +User "1" *-[#595959,plain]-> "subscriptionActions\n*" SubscriptionAction +@enduml |