package Ġcom . posts . api . web Ċ Ċ import Ġcom . posts . api . conf . Jwt Token Util Ċ import Ġcom . posts . api . conf . Publisher S se Ċ import Ġcom . posts . api . conf . X _ AUTH _ TOKEN Ċ import Ġcom . posts . api . error . Field Exception Ċ import Ġcom . posts . api . follow s . Follow Id Ċ import Ġcom . posts . api . follow s . Follow Service Ċ import Ġcom . posts . api . posts . Post Ċ import Ġcom . posts . api . posts . Post Service Ċ import Ġcom . posts . api . users . User Ċ import Ġcom . posts . api . users . UserService Ċ import Ġcom . posts . api . votes . Vote Id Ċ import Ġcom . posts . api . votes . Vote Service Ċ import Ġcom . posts . api . web . sse . Feed S se Ċ import Ġorg . springframework . beans . factory . annotation . Value Ċ import Ġorg . springframework . http . HttpHeaders Ċ import Ġorg . springframework . http . HttpStatus . CREATED Ċ import Ġorg . springframework . http . HttpStatus . NO _ CONTENT Ċ import Ġorg . springframework . http . Response Entity Ċ import Ġorg . springframework . security . core . Authentication Ċ import Ġorg . springframework . security . core . annotation . Authentication Principal Ċ import Ġorg . springframework . security . crypto . password . Password Encoder Ċ import Ġorg . springframework . web . bind . annotation .* Ċ import Ġorg . springframework . web . servlet . mvc . method . annotation . S se Emitter Ċ import Ġjava . net . URI Ċ import Ġjavax . validation . Valid Ċ Ċ const Ġval ĠAUTH _ API Ġ= Ġ"/ api / auth " Ċ const Ġval ĠUSER S _ API Ġ= Ġ"/ api / users " Ċ const Ġval ĠPOST S _ API Ġ= Ġ"/ api / posts " Ċ const Ġval ĠV OT ES _ API Ġ= Ġ"/ api / votes " Ċ const Ġval ĠFOL LO WS _ API Ġ= Ġ"/ api / follow s " Ċ const Ġval ĠPOST S _ LIMIT Ġ= Ġ 2 0 Ċ Ċ @ RestController Ċ @ RequestMapping ( AUTH _ API ) Ċ class ĠAuth Controller ( ĊĠ Ġprivate Ġvar ĠuserService : ĠUserService , ĊĠ Ġprivate Ġval Ġjwt Token Util : ĠJwt Token Util , ĊĠ Ġprivate Ġval Ġpassword Encoder : ĠPassword Encoder , Ċ ) Ġ{ ĊĊĠ Ġ@ PostMapping ĊĠ Ġfun Ġcreate (@ Valid Ġ@ RequestBody Ġauth Dto Req : ĠAuth Dto Req ): ĠString Ġ{ ĊĠĠĠ Ġval Ġuser Ġ= ĠuserService . getUser With Pass By Email ( auth Dto Req . email ) ĊĠĠĠ Ġif Ġ(! password Encoder . matches ( auth Dto Req . password , ĊĠĠĠĠĠĠĠ Ġuser . password ) ĊĠĠĠ Ġ) Ġthrow ĠField Exception ( mutable Map Of (" password " Ġto Ġ" incorrect Ġemail Ġor Ġpassword ")) ĊĠĠĠ Ġreturn Ġjwt Token Util . generate Token ( user ) ĊĠ Ġ} Ċ } Ċ Ċ @ RestController Ċ @ RequestMapping ( USERS _ API ) Ċ class ĠUser Controller ( ĊĠ Ġprivate Ġval ĠuserService : ĠUserService , ĊĠ Ġprivate Ġval Ġjwt Token Util : ĠJwt Token Util , ĊĠ Ġprivate Ġval Ġpassword Encoder : ĠPassword Encoder , Ċ ) Ġ{ ĊĊĠ Ġ@ GetMapping ĊĠ Ġfun ĠfindAll (): ĠIterable < User Dto > Ġ= ĠuserService . findAll (). map Ġ{ Ġit . to Dto () Ġ} ĊĊĠ Ġ@ GetMapping ("/ { id }") ĊĠ Ġfun Ġfind One (@ PathVariable Ġid : ĠLong ): ĠUser Dto Ġ= ĠuserService . findOne ( id ). to Dto () ĊĊĠ Ġ@ GetMapping ("/ me ") ĊĠ Ġfun Ġfind Me ( auth : ĠAuthentication ): ĠUser Dto Ġ= Ġ( auth . principal Ġas ĠUser ). to Dto () ĊĊĠ Ġ@ PostMapping ĊĠ Ġ@ ResponseStatus ( CREATED ) ĊĠ Ġfun Ġcreate (@ Valid Ġ@ RequestBody Ġnew User Create : ĠUser Create Dto Req ): ĠResponseEntity < User Dto > Ġ{ ĊĠĠĠ Ġval Ġuser Ġ= ĊĠĠĠĠĠ ĠuserService . create ( new User Create . to Entity (), Ġpassword Encoder . encode ( new User Create . password )) ĊĠĠĠ Ġval Ġheaders Ġ= Ġget Headers With Token ( user ) ĊĠĠĠ Ġreturn ĠResponseEntity . created ( URI ("$ USERS _ API /${ user . id } ")). headers ( headers ). body ( user . to Dto ()) ĊĠ Ġ} ĊĊĠ Ġ@ Put Mapping ("/ { id }") ĊĠ Ġfun Ġupdate ( ĊĠĠĠ Ġ@ PathVariable Ġid : ĠLong , ĊĠĠĠ Ġ@ Valid Ġ@ RequestBody Ġupdated User : ĠUser Update Dto Req , ĊĠ Ġ): ĠResponseEntity < User Dto > Ġ{ ĊĠĠĠ Ġval Ġuser Ġ= ĠuserService . update ( id , Ġupdated User . to Entity ()) ĊĠĠĠ Ġval Ġheaders Ġ= Ġget Headers With Token ( user ) ĊĠĠĠ Ġreturn ĠResponseEntity . ok (). headers ( headers ). body ( user . to Dto ()) ĊĠ Ġ} ĊĊĠ Ġ@ Delete Mapping ("/ { id }") ĊĠ Ġ@ ResponseStatus ( NO _ CONTENT ) ĊĠ Ġfun Ġdelete (@ PathVariable Ġid : ĠLong ) Ġ= ĠuserService . delete ( id ) ĊĊĠ Ġprivate Ġfun Ġget Headers With Token ( user : ĠUser ): ĠHttp Headers Ġ{ ĊĠĠĠ Ġval Ġheaders Ġ= ĠHttp Headers () ĊĠĠĠ Ġheaders . set ( X _ AUTH _ TOKEN , Ġjwt Token Util . generate Token ( user )) ĊĠĠĠ Ġheaders . set (" access - control - expose - headers ", ĠX _ AUTH _ TOKEN ) ĊĠĠĠ Ġreturn Ġheaders ĊĠ Ġ} Ċ } Ċ Ċ @ RestController Ċ @ RequestMapping ( POST S _ API ) Ċ class ĠPost Controller ( ĊĠ Ġprivate Ġval Ġpost Service : ĠPost Service , ĊĠ Ġprivate Ġval Ġfollow Service : ĠFollow Service , ĊĠ Ġprivate Ġval Ġvote Service : ĠV ote Service , ĊĠ Ġprivate Ġval Ġfeed S se : ĠFeed S se , ĊĠ Ġprivate Ġval Ġpublisher S se : ĠPublisher S se , ĊĠ Ġ@ Value ("\ ${ sse . connection . timeout . ms }") Ġval Ġtimeout S se : ĠLong Ċ ) Ġ{ ĊĊĠ Ġ@ GetMapping ("/ see - feeds /{ userId }") ĊĠ Ġfun Ġs se Feed (@ PathVariable ĠuserId : ĠLong ): ĠS se Emitter Ġ{ ĊĠĠĠ Ġval Ġemitter Ġ= ĠS se Emitter ( timeout S se ) ĊĠĠĠ Ġemitter . on Completion Ġ{ Ġfeed S se . remove Emitter ( userId ) Ġ} ĊĠĠĠ Ġemitter . on Timeout Ġ{ Ġfeed S se . remove Emitter ( userId ) Ġ} ĊĠĠĠ Ġfeed S se . add Emitter ( userId , Ġemitter ) ĊĠĠĠ Ġreturn Ġemitter ĊĠ Ġ} ĊĊĠ Ġ@ GetMapping ("/") ĊĠ Ġfun ĠfindAll ( ĊĠĠĠ Ġ@ RequestParam Ġcursor : ĠString , ĊĠĠĠ Ġ@ RequestParam Ġsearch : ĠString , ĊĠĠĠ Ġ@ Authentication Principal Ġuser : ĠUser ?, ĊĠ Ġ): ĠPost Feed Dto Ġ{ ĊĠĠĠ Ġvar Ġposts Ġ= Ġpost Service . findAll ( cursor , Ġsearch , Ġuser , ĠPOST S _ LIMIT Ġ+ Ġ 1 ) ĊĠĠĠ Ġif Ġ( user Ġ!= Ġnull ) Ġposts Ġ= Ġadd Follow s And Votes ( user . id , Ġposts ) ĊĠĠĠ Ġreturn ĠPost Feed Dto ( posts . toList (). map Ġ{ Ġit . to Snippet Dto () Ġ}. take ( POST S _ LIMIT ), ĊĠĠĠĠĠ Ġposts . size Ġ== ĠPOST S _ LIMIT Ġ+ Ġ 1 ) ĊĠ Ġ} ĊĊĠ Ġ@ GetMapping ("/ { id }") ĊĠ Ġfun Ġfind One (@ PathVariable Ġid : ĠLong , Ġ@ Authentication Principal Ġuser : ĠUser ?): ĠPost Dto Ġ{ ĊĠĠĠ Ġvar Ġpost Ġ= Ġpost Service . findOne ( id , Ġuser ) ĊĠĠĠ Ġif Ġ( user Ġ!= Ġnull ) Ġpost Ġ= Ġadd Follow And Vote ( user . id , Ġpost ) ĊĠĠĠ Ġreturn Ġpost . to Dto () ĊĠ Ġ} ĊĊĠ Ġ@ PostMapping ĊĠ Ġ@ ResponseStatus ( CREATED ) ĊĠ Ġfun Ġcreate ( ĊĠĠĠ Ġ@ Valid Ġ@ RequestBody Ġnew Post : ĠPost Dto Req , ĊĠĠĠ Ġauth : ĠAuthentication , ĊĠ Ġ): ĠResponseEntity < Post Dto > Ġ{ ĊĠĠĠ Ġval Ġpost Ġ= Ġpost Service . create ( new Post . to Entity ( auth . principal Ġas ĠUser )) ĊĠĠĠ Ġpublisher S se . publish ( post . user . name , Ġpost . user . id ) ĊĠĠĠ Ġreturn ĠResponseEntity . created ( URI ("$ POST S _ API /${ post . id } ")). body ( post . to Dto ()) ĊĠ Ġ} ĊĊĠ Ġ@ Put Mapping ("/ { id }") ĊĠ Ġfun Ġupdate ( ĊĠĠĠ Ġ@ PathVariable Ġid : ĠLong , ĊĠĠĠ Ġ@ Valid Ġ@ RequestBody Ġupdated Post : ĠPost Dto Req , ĊĠĠĠ Ġauth : ĠAuthentication , ĊĠ Ġ): ĠPost Dto Ġ= Ġpost Service . update ( id , Ġupdated Post . to Entity ( auth . principal Ġas ĠUser )). to Dto () ĊĊĠ Ġ@ Delete Mapping ("/ { id }") ĊĠ Ġ@ ResponseStatus ( NO _ CONTENT ) ĊĠ Ġfun Ġdelete (@ PathVariable Ġid : ĠLong , Ġauth : ĠAuthentication ) Ġ= ĊĠĠĠ Ġpost Service . delete ( id , Ġauth . principal Ġas ĠUser ) ĊĊĠ Ġprivate Ġfun Ġadd Follow And Vote ( userId : ĠLong , Ġpost : ĠPost ): ĠPost Ġ{ ĊĠĠĠ Ġpost . is Follow Ġ= Ġfollow Service . exists ById ( Follow Id ( userId , Ġpost . user . id )) ĊĠĠĠ Ġval Ġuser Vote Ġ= Ġvote Service . findById OrNull ( Vote Id ( userId , Ġpost . id )) ĊĠĠĠ Ġif Ġ( user Vote Ġ!= Ġnull ) Ġpost . vote Value Ġ= Ġuser Vote . value ĊĠĠĠ Ġreturn Ġpost ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġadd Follow s And Votes ( ĊĠĠĠ ĠuserId : ĠLong , ĊĠĠĠ Ġposts : ĠList < Post >, ĊĠ Ġ): ĠList < Post > Ġ{ ĊĠĠĠ Ġval Ġfollow ees Ġ= Ġget Follow ees ( userId ) ĊĠĠĠ Ġval Ġpost Id To Value Ġ= Ġget Map Of User Posts Votes ( userId ) ĊĠĠĠ Ġreturn Ġposts . map Ġ{ Ġpost Ġ-> ĊĠĠĠĠĠ Ġif Ġ( post . user . id Ġin Ġfollow ees ) Ġpost . is Follow Ġ= Ġtrue ĊĠĠĠĠĠ Ġif Ġ( post . id Ġin Ġpost Id To Value ) Ġpost . vote Value Ġ= Ġpost Id To Value . getValue ( post . id ) ĊĠĠĠĠĠ Ġpost ĊĠĠĠ Ġ} ĊĠ Ġ} ĊĊĠ Ġprivate Ġfun Ġget Follow ees ( userId : ĠLong ) Ġ= ĊĠĠĠ Ġfollow Service . findAll By From Id ( userId ). map Ġ{ Ġit . to . id Ġ}. toSet () ĊĊĠ Ġprivate Ġfun Ġget Map Of User Posts Votes ( userId : ĠLong ): ĠMap < Long , ĠInt > Ġ{ ĊĠĠĠ Ġval Ġpost Id To Value Ġ= Ġmutable Map Of < Long , ĠInt >() ĊĠĠĠ Ġfor Ġ( user Vote Ġin Ġvote Service . findAll By UserId ( userId )) Ġ{ ĊĠĠĠĠĠ Ġpost Id To Value [ user Vote . post . id ] Ġ= Ġuser Vote . value ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġpost Id To Value ĊĠ Ġ} Ċ } Ċ Ċ @ RestController Ċ @ RequestMapping ( V OT ES _ API ) Ċ class ĠV ote Controller ( ĊĠ Ġprivate Ġval Ġvote Service : ĠV ote Service , ĊĠ Ġprivate Ġval Ġpost Service : ĠPost Service , Ċ ) Ġ{ ĊĊĠ Ġ@ PostMapping ĊĠ Ġ@ ResponseStatus ( CREATED ) ĊĠ Ġfun Ġcreate (@ Valid Ġ@ RequestBody Ġnew Vote : ĠV ote Create Dto Req , Ġauth : ĠAuthentication ): ĠInt Ġ{ ĊĠĠĠ Ġval Ġpost Ġ= Ġpost Service . findOne ( new Vote . post Id , Ġnull ) ĊĠĠĠ Ġpost . points Ġ= Ġvote Service . create ( new Vote . is Up Vote , Ġpost , Ġauth . principal Ġas ĠUser ) ĊĠĠĠ Ġpost Service . update ( post . id , Ġpost ) ĊĠĠĠ Ġreturn Ġpost . points ĊĠ Ġ} Ċ } Ċ Ċ @ RestController Ċ @ RequestMapping ( FOL LO WS _ API ) Ċ class ĠFollow Controller ( ĊĠ Ġprivate Ġval Ġfollow Service : ĠFollow Service , ĊĠ Ġprivate Ġval ĠuserService : ĠUserService , Ċ ) Ġ{ ĊĊĠ Ġ@ PostMapping ĊĠ Ġ@ ResponseStatus ( CREATED ) ĊĠ Ġfun Ġcreate (@ Valid Ġ@ RequestBody Ġnew Follow : ĠFollow Create Dto Req , Ġauth : ĠAuthentication ): ĠString Ġ= ĊĠĠĠ Ġfollow Service . create ( auth . principal Ġas ĠUser , ĠuserService . findOne ( new Follow . to Id )) ĊĊĠ Ġ@ GetMapping ("/ { id }") ĊĠ Ġfun Ġfind Follow s (@ PathVariable Ġid : ĠLong ): ĠList < User Dto > Ġ= ĊĠĠĠ Ġfollow Service . find Follow s ( id ). map Ġ{ Ġit . to Dto () Ġ} ĊĊĠ Ġ@ GetMapping ("/ to /{ id }") ĊĠ Ġfun Ġfind Follow ers (@ PathVariable Ġid : ĠLong ): ĠList < User Dto > Ġ= ĊĠĠĠ Ġfollow Service . find Follow ers ( id ). map Ġ{ Ġit . to Dto From () Ġ} Ċ }