/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 2 1 . Ġfan poll ĠAll Ġrights Ġreserved . Ċ Ġ*/ Ċ Ċ package Ġfan poll . ops . features Ċ Ċ import Ġfan poll . infra . auth . authorize Ċ import Ġfan poll . infra . auth . login . util . User Password Utils Ċ import Ġfan poll . infra . auth . principal . User Principal Ċ import Ġfan poll . infra . base . entity . Entity DTO Ċ import Ġfan poll . infra . base . entity . Entity Form Ċ import Ġfan poll . infra . base . exception . RequestException Ċ import Ġfan poll . infra . base . form . Form Ċ import Ġfan poll . infra . base . form . Validation Utils Ċ import Ġfan poll . infra . base . i 1 8 n . Lang Ċ import Ġfan poll . infra . base . json . Instant Serializer Ċ import Ġfan poll . infra . base . json . UUID Serializer Ċ import Ġfan poll . infra . base . location . UUID EntityId Location Ċ import Ġfan poll . infra . base . response . Code Response DTO Ċ import Ġfan poll . infra . base . response . Data Response DTO Ċ import Ġfan poll . infra . base . response . Inf ra Response Code Ċ import Ġfan poll . infra . base . response . respond Ċ import Ġfan poll . infra . database . custom . lang Ċ import Ġfan poll . infra . database . sql . UUID Table Ċ import Ġfan poll . infra . database . sql . insert Ċ import Ġfan poll . infra . database . sql . transaction Ċ import Ġfan poll . infra . database . sql . update Ċ import Ġfan poll . infra . database . util . Result Row DTO Mapper Ċ import Ġfan poll . infra . database . util . query DB Ċ import Ġfan poll . infra . database . util . to DTO Ċ import Ġfan poll . infra . notification . send ers . Notification Sender Ċ import Ġfan poll . infra . notification . util . Send Notification Form Ċ import Ġfan poll . infra . openapi . dynamic Query Ċ import Ġfan poll . infra . openapi . post Ċ import Ġfan poll . infra . openapi . put Ċ import Ġfan poll . infra . openapi . schema . operation . support . Open ApiModel Ċ import Ġfan poll . ops .* Ċ import Ġio . kon form . validation . Validation Ċ import Ġio . kon form . validation . json schema . maxLength Ċ import Ġio . ktor . application . call Ċ import Ġio . ktor . auth . principal Ċ import Ġio . ktor . http . HttpStatusCode Ċ import Ġio . ktor . response . respond Ċ import Ġio . ktor . routing . Routing Ċ import Ġio . ktor . routing . route Ċ import Ġkotlinx . serialization . Serializable Ċ import Ġkotlinx . serialization . Transient Ċ import Ġmu . Kotlin Logging Ċ import Ġorg . jetbrains . ex posed . dao . id . Entity ID Ċ import Ġorg . jetbrains . ex posed . sql . Column Ċ import Ġorg . jetbrains . ex posed . sql . jav atime . timestamp Ċ import Ġorg . jetbrains . ex posed . sql . select Ċ import Ġorg . jetbrains . ex posed . sql . update Ċ import Ġorg . k oin . ktor . ext . inject Ċ import Ġjava . time . Instant Ċ import Ġjava . util .* Ċ Ċ fun ĠRouting . ops User () Ġ{ ĊĊĠĠĠ Ġval Ġops UserService Ġby Ġinject < Ops UserService >() ĊĠĠĠ Ġval Ġnotification Sender Ġby Ġinject < Notification Sender >() ĊĊĠĠĠ Ġroute ("${ Ops Const . url RootPath }/ users ") Ġ{ ĊĊĠĠĠĠĠĠĠ Ġauthorize ( Ops Auth . Root ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost < Create User Form , ĠUUID >( Ops Open Api . Create User ) Ġ{ Ġform Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġid Ġ= Ġops UserService . createUser ( form ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( Data Response DTO . uuid ( id )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġput < UUID EntityId Location , ĠUpdate User Form , ĠUnit >( Ops Open Api . Update User ) Ġ{ Ġ_, Ġform Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġops UserService . update User ( form ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( HttpStatusCode . OK ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġdynamic Query < User DTO >( Ops Open Api . Find Users ) Ġ{ Ġdynamic Query Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( dynamic Query . query DB < User DTO >()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost < Send Notification Form , ĠUUID > ("/ send Notification ", ĠOps Open Api . Send Notification ) Ġ{ Ġform Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnotification Ġ= Ġform . to Notification ( Ops Notification . Send Notification ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnotification Sender . send ( notification ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( Data Response DTO . uuid ( notification . id )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġauthorize ( Ops Auth . User ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġput < Update User Password Form , ĠUnit > ("/ my Password ", ĠOps Open Api . Update My Password ) Ġ{ Ġform Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠuserId Ġ= Ġcall . principal < User Principal >() !!. userId ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġops UserService . update Password ( userId , Ġform ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( Code Response DTO . OK ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ class ĠOps UserService Ġ{ ĊĊĠĠĠ Ġval Ġlogger Ġ= ĠKotlin Logging . logger Ġ{} ĊĊĠĠĠ Ġfun Ġcreate User ( form : ĠCreate User Form ): ĠUUID Ġ{ ĊĠĠĠĠĠĠĠ Ġform . password Ġ= ĠUser Password Utils . hash Password ( form . password ) ĊĠĠĠĠĠĠĠ Ġreturn Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( Ops User Table . select Ġ{ ĠOps User Table . account Ġeq Ġform . account Ġ}. count () Ġ> Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠRequest Exception ( Inf ra Response Code . ENTITY _ AL READY _ EXISTS , Ġ"${ form . account } Ġalready Ġexists ") ĊĠĠĠĠĠĠĠĠĠĠĠ ĠOps User Table . insert ( form ) Ġas ĠUUID ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate User ( form : ĠUpdate User Form ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠOps User Table . update ( form ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun ĠgetUser ById ( userId : ĠUUID ): ĠUser DTO Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠOps User Table . select Ġ{ ĠOps User Table . id Ġeq ĠuserId Ġ}. single (). to DTO ( User DTO :: class ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġfun Ġupdate Password ( userId : ĠUUID , Ġform : ĠUpdate User Password Form ) Ġ{ ĊĠĠĠĠĠĠĠ Ġtransaction Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġhashed Password Ġ= ĠOps User Table . slice ( Ops User Table . password ). select Ġ{ ĠOps User Table . id Ġeq ĠuserId Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. single OrNull ()?. let Ġ{ Ġit [ Ops User Table . password ] Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠRequest Exception ( Inf ra Response Code . ENTITY _ NOT _ EXIST , Ġ" user Ġ$ userId Ġdoes Ġnot Ġexist ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( User Password Utils . verify Password ( form . old Password , Ġhashed Password )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠOps User Table . update ({ ĠOps User Table . id Ġeq ĠuserId Ġ}) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit [ password ] Ġ= ĠUser Password Utils . hash Password ( form . new Password ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġthrow ĠRequest Exception ( Inf ra Response Code . AUTH _ BAD _ PASSWORD ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Open ApiModel ( propertyName Order Ġ= Ġ[" account ", Ġ" password ", Ġ" enabled ", Ġ" role ", Ġ" name "]) Ċ @ Serializable Ċ data Ġclass ĠCreate User Form ( ĊĠĠĠ Ġval Ġaccount : ĠString , ĊĠĠĠ Ġvar Ġpassword : ĠString , ĊĠĠĠ Ġval Ġenabled : ĠBoolean Ġ= Ġtrue , ĊĠĠĠ Ġval Ġrole : ĠOps UserRole , ĊĠĠĠ Ġval Ġname : ĠString , ĊĠĠĠ Ġval Ġemail : ĠString , ĊĠĠĠ Ġval Ġmobile : ĠString ? Ġ= Ġnull , ĊĠĠĠ Ġval Ġlang : ĠLang ? Ġ= Ġnull , Ċ ) Ġ: ĠEntity Form < Create User Form , ĠString , ĠUUID >() Ġ{ ĊĊĠĠĠ Ġ@ Transient ĊĠĠĠ Ġval Ġid : ĠUUID Ġ= ĠUUID . randomUUID () ĊĊĠĠĠ Ġoverride Ġfun Ġget EntityId (): ĠUUID Ġ= Ġid ĊĊĠĠĠ Ġoverride Ġfun Ġget Dto Id (): ĠString Ġ= Ġaccount ĊĊĠĠĠ Ġoverride Ġfun Ġvalidator (): ĠValidation < Create User Form > Ġ= ĠVALID ATOR ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠVALID ATOR : ĠValidation < Create User Form > Ġ= ĠValidation Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCreate User Form :: account Ġrequired Ġ{ Ġrun ( Validation Utils . EMAIL _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCreate User Form :: password Ġrequired Ġ{ Ġrun ( Validation Utils . PASSWORD _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCreate User Form :: name Ġrequired Ġ{ ĠmaxLength ( USER _ NAME _ LENGTH ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCreate User Form :: email Ġrequired Ġ{ Ġrun ( Validation Utils . EMAIL _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCreate User Form :: mobile Ġif Present Ġ{ Ġrun ( Validation Utils . TA IW AN _ MOB ILE _ NUMBER _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Open ApiModel ( propertyName Order Ġ= Ġ[" id ", Ġ" enabled ", Ġ" role ", Ġ" name "]) Ċ @ Serializable Ċ data Ġclass ĠUpdate User Form ( ĊĠĠĠ Ġ@ Serializable ( with Ġ= ĠUUID Serializer :: class ) Ġval Ġid : ĠUUID , ĊĠĠĠ Ġval Ġenabled : ĠBoolean ? Ġ= Ġnull , ĊĠĠĠ Ġval Ġrole : ĠOps UserRole ? Ġ= Ġnull , ĊĠĠĠ Ġval Ġname : ĠString ? Ġ= Ġnull , ĊĠĠĠ Ġval Ġemail : ĠString ? Ġ= Ġnull , ĊĠĠĠ Ġval Ġmobile : ĠString ? Ġ= Ġnull , ĊĠĠĠ Ġval Ġlang : ĠLang ? Ġ= Ġnull Ċ ) Ġ: ĠEntity Form < Update User Form , ĠString , ĠUUID >() Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġget EntityId (): ĠUUID Ġ= Ġid ĊĊĠĠĠ Ġoverride Ġfun Ġvalidator (): ĠValidation < Update User Form > Ġ= ĠVALID ATOR ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠVALID ATOR : ĠValidation < Update User Form > Ġ= ĠValidation Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate User Form :: name Ġif Present Ġ{ ĠmaxLength ( USER _ NAME _ LENGTH ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate User Form :: email Ġif Present Ġ{ Ġrun ( Validation Utils . EMAIL _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate User Form :: mobile Ġif Present Ġ{ Ġrun ( Validation Utils . TA IW AN _ MOB ILE _ NUMBER _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Open ApiModel ( propertyName Order Ġ= Ġ[" id ", Ġ" account ", Ġ" enabled ", Ġ" role ", Ġ" name "]) Ċ @ Serializable Ċ data Ġclass ĠUser DTO (@ Jvm Field Ġ@ Serializable ( with Ġ= ĠUUID Serializer :: class ) Ġval Ġid : ĠUUID ) Ġ: ĠEntity DTO < UUID > Ġ{ ĊĊĠĠĠ Ġvar Ġaccount : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġenabled : ĠBoolean ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġrole : ĠOps UserRole ? Ġ= Ġnull ĊĊĠĠĠ Ġvar Ġname : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġemail : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġmobile : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġlang : ĠLang ? Ġ= Ġnull ĊĊĠĠĠ Ġ@ Transient ĊĠĠĠ Ġvar Ġpassword : ĠString ? Ġ= Ġnull ĊĊĠĠĠ Ġ@ Serializable ( with Ġ= ĠInstant Serializer :: class ) ĊĠĠĠ Ġvar ĠcreatedAt : ĠInstant ? Ġ= Ġnull ĊĊĠĠĠ Ġoverride Ġfun ĠgetId (): ĠUUID Ġ= Ġid ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmapper : ĠResult Row DTO Mapper < User DTO > Ġ= ĠResult Row DTO Mapper ( User DTO :: class , ĠOps User Table ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ @ Serializable Ċ data Ġclass ĠUpdate User Password Form ( val Ġold Password : ĠString , Ġval Ġnew Password : ĠString ) Ġ: ĠForm < Update User Password Form >() Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġvalidator (): ĠValidation < Update User Password Form > Ġ= ĠVALID ATOR ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠVALID ATOR : ĠValidation < Update User Password Form > Ġ= ĠValidation Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate User Password Form :: old Password Ġrequired Ġ{ Ġrun ( Validation Utils . PASSWORD _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUpdate User Password Form :: new Password Ġrequired Ġ{ Ġrun ( Validation Utils . PASSWORD _ VALID ATOR ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ object ĠOps User Table Ġ: ĠUUID Table ( name Ġ= Ġ" ops _ user ") Ġ{ ĊĊĠĠĠ Ġval Ġaccount Ġ= Ġvarchar (" account ", ĠValidation Utils . EMAIL _ MAX _ LENGTH ) Ġ// unique ĊĠĠĠ Ġval Ġenabled Ġ= Ġbool (" enabled ") ĊĠĠĠ Ġval Ġrole Ġ= Ġenumeration ByName (" role ", Ġ 2 0 , ĠOps UserRole :: class ) ĊĊĠĠĠ Ġval Ġname Ġ= Ġvarchar (" name ", ĠUSER _ NAME _ LENGTH ) ĊĠĠĠ Ġval Ġemail Ġ= Ġvarchar (" email ", ĠValidation Utils . EMAIL _ MAX _ LENGTH ) ĊĠĠĠ Ġval Ġmobile Ġ= Ġvarchar (" mobile ", ĠValidation Utils . TA IW AN _ MOB ILE _ NUMBER _ LENGTH ). nullable () ĊĠĠĠ Ġval Ġlang Ġ= Ġlang (" lang "). nullable () ĊĊĠĠĠ Ġval Ġpassword Ġ= Ġvarchar (" password ", Ġ 1 0 0 0 ) ĊĠĠĠ Ġval ĠcreatedAt Ġ= Ġtimestamp (" created _ at ") ĊĠĠĠĠĠĠĠ Ġ. default Expression ( org . jetbrains . ex posed . sql . jav atime . Current Timestamp ()) ĊĠĠĠ Ġval ĠupdatedAt Ġ= Ġtimestamp (" updated _ at ") ĊĠĠĠĠĠĠĠ Ġ. default Expression ( org . jetbrains . ex posed . sql . jav atime . Current Timestamp ()) ĊĊĠĠĠ Ġoverride Ġval Ġnatural Keys : ĠList < Column < out ĠAny >> Ġ= ĠlistOf ( account ) ĊĠĠĠ Ġoverride Ġval Ġsur rogate Key : ĠColumn < Entity ID < UUID >> Ġ= Ġid Ċ } Ċ Ċ private Ġconst Ġval ĠUSER _ NAME _ LENGTH Ġ= Ġ 3 0