package Ġnet . jam mos . utils . auth . dao Ċ Ċ import Ġcom . google . common . base . Strings Ċ import Ġcom . lamb d aw ork s . redis . Redis Client Ċ import Ġmu . K Logging Ċ import Ġnet . jam mos . utils . Byte Arrays . random Bytes Ċ import Ġnet . jam mos . utils . auth .* Ċ import Ġnet . jam mos . utils . auth . Username . Username . username Ċ import Ġnet . jam mos . utils . auth . crypto . Crypto Manager Ċ import Ġnet . jam mos . utils . extensions . minutes Ċ import Ġnet . jam mos . utils . json . fromJson Ċ import Ġnet . jam mos . utils . json . toJson Ċ import Ġnet . jam mos . utils . types . Big Unsigned Integer Ċ import Ġjava . net . Inet Address Ċ import Ġjava . nio . charset . StandardCharsets . UTF _ 8 Ċ import Ġjava . time . Duration Ċ import Ġjava . time . Instant Ċ import Ġjava . time . format . DateTime ParseException Ċ Ċ class ĠRedis Auth Dao ( ĊĠĠĠĠĠĠĠ Ġredis Client : ĠRedis Client , ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġcrypto Manager : ĠCrypto Manager ) Ġ: ĠAuth Dao Ġ{ ĊĠĠĠ Ġprivate Ġval Ġconn Ġ= Ġredis Client . connect (). sync () ĊĊĠĠĠ Ġprivate Ġcompanion Ġobject : ĠK Logging () Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠAUTH _ FAILURE S _ TTL : ĠDuration Ġ= Ġ 3 0 . minutes ĊĊĠĠĠĠĠĠĠ Ġfun Ġusername Auth Key ( username : ĠUsername ) Ġ= Ġ" username :$ username : auth " ĊĠĠĠĠĠĠĠ Ġfun Ġuser Username Key ( userId : ĠUserId ) Ġ= Ġ" user :$ userId : username " ĊĠĠĠĠĠĠĠ Ġfun Ġuser Auth Failures Key ( userId : ĠUserId ) Ġ= Ġ" user :$ userId : auth _ failure _ count " ĊĠĠĠĠĠĠĠ Ġfun Ġuser Sus pension Key ( userId : ĠUserId ) Ġ= Ġ" user :$ userId : sus pension " ĊĠĠĠĠĠĠĠ Ġfun Ġuser Session Key Key ( userId : ĠUserId ) Ġ= Ġ" user :$ userId : session _ key " ĊĠĠĠĠĠĠĠ Ġfun Ġip Sus pension Key ( ip : ĠInet Address ) Ġ= Ġ" ip :$ ip : sus pended _ until " ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġlast UserId Key Ġ= Ġ" user :_ last Id " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetUser Auth ( username : ĠUsername ): ĠUser Auth ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġconn . get ( username Auth Key ( username )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . fromJson < User Auth >() ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . copy ( username Ġ= Ġusername ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetUser Username ( userId : ĠUserId ) Ġ= Ġconn . get ( user Username Key ( userId )) ?. let Ġ{ Ġusername ( it ) Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetUser Sus pension ( userId : ĠUserId ): ĠUser Sus pension ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġconn . get ( user Sus pension Key ( userId )) ?. fromJson () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġcreate User ( username : ĠUsername , Ġpassword : ĠString ): ĠUser Auth Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠVerify Ġwhether Ġthe Ġuser Ġexists Ġand Ġbail Ġif Ġso ĊĠĠĠĠĠĠĠ ĠgetUser Auth ( username )?. let Ġ{ Ġthrow ĠUser AlreadyExists Exception ( username ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġ// ĠCreate Ġa Ġuser ĠID ĊĠĠĠĠĠĠĠ Ġval ĠuserId Ġ= Ġnext UserId () ĊĊĠĠĠĠĠĠĠ Ġval Ġsalt Ġ= ĠS alt ByteArray ( random Bytes ( 3 2 )) ĊĠĠĠĠĠĠĠ Ġval Ġpassword Upper Ġ= Ġpassword . toUpperCase () ĊĊĠĠĠĠĠĠĠ Ġval Ġlogin Hash Ġ= Ġcrypto Manager . create PrivateKey ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġusername . bytes , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpassword Upper . toByteArray ( UTF _ 8 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsalt ) ĊĊĠĠĠĠĠĠĠ Ġval Ġuser Ġ= ĠUser Auth ( userId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġusername Ġ= Ġusername , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsalt Ġ= Ġsalt , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġverifier Ġ= Ġcrypto Manager . createUser Verifier ( login Hash )) ĊĊĠĠĠĠĠĠĠ Ġ// Ġsave Ġin Ġredis ĊĠĠĠĠĠĠĠ Ġconn . set ( username Auth Key ( username ), Ġuser . toJson ()) ĊĠĠĠĠĠĠĠ Ġconn . set ( user Username Key ( userId ), Ġusername . toString ()) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġuser ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġsuspend User ( userId : ĠUserId , Ġstart : ĠInstant , Ġend : ĠInstant ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġconn . set ( user Sus pension Key ( userId ), ĠUser Sus pension ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstart Ġ= Ġstart , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġend Ġ= Ġend ). toJson ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġupdate User Session Key ( userId : ĠUserId , Ġsession Key : ĠBig Unsigned Integer ) Ġ{ ĊĠĠĠĠĠĠĠ Ġconn . set ( user Session Key Key ( userId ), Ġsession Key . toString ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠgetUser Session Key ( userId : ĠUserId ): ĠBig Unsigned Integer ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġconn . get ( user Session Key Key ( userId )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ ĠBig Unsigned Integer . of HexString ( it ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġrecord User Auth Failure ( userId : ĠUserId ): ĠLong Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġkey Ġ= Ġuser Auth Failures Key ( userId ) ĊĠĠĠĠĠĠĠ Ġreturn Ġconn . incr ( key ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġexpire Ġthe Ġauth Ġfailures Ġafter ĠTTL ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . apply Ġ{ Ġconn . expire ( key , ĠAUTH _ FAILURE S _ TTL . seconds ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġ 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġsuspend Ip ( ip : ĠInet Address , Ġend : ĠInstant ?) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġkey Ġ= Ġip Sus pension Key ( ip ) ĊĊĠĠĠĠĠĠĠ Ġ// Ġset Ġsus pension ĊĠĠĠĠĠĠĠ Ġconn . set ( key , Ġend ?. toString () Ġ?: Ġ"") ĊĊĠĠĠĠĠĠĠ Ġ// Ġexpire Ġsus pension Ġkey Ġwhen Ġthe Ġsus pension Ġis Ġover , Ġif Ġit Ġhas Ġan Ġend ĊĠĠĠĠĠĠĠ Ġend ?. apply Ġ{ Ġconn . expire at ( key , Ġepoch Second ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Ip Sus pension ( ip : ĠInet Address ): ĠIp Sus pension ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġconn . get ( ip Sus pension Key ( ip )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġempty Ġstring Ġmeans Ġforever ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ ĠIp Sus pension ( Strings . empty To Null ( it )?. let ( Instant :: parse )) Ġ} ĊĊĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠDateTime ParseException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( e ) Ġ{ Ġ" Failed Ġto Ġparse Ġexpiry Ġdate " Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġnext UserId () Ġ= ĠUserId ( conn . incr ( last UserId Key ). toString ()) ĊĊĠĠĠ Ġclass ĠUser AlreadyExists Exception ( username : ĠUsername ): ĠIllegalArgumentException (" User Ġalready Ġexists : Ġ$ username ") Ċ } Ċ Ċ /* ĊĠĠĠ Ġuser :< username >: auth Ġ= Ġ{ ĊĠĠĠĠĠĠĠ Ġpassword _ sha Ġ= Ġ< binary >, ĊĠĠĠĠĠĠĠ Ġsalt : Ġ< binary >, ĊĠĠĠĠĠĠĠ Ġverifier : Ġ< binary >, ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġuser :< userid >: username Ġ= Ġ< string > ĊĠĠĠ Ġuser :< userid >: session _ key Ġ= Ġ< binary > ĊĠĠĠ Ġuser :< userid >: auth _ failure _ count Ġ= Ġ< int > ĊĊĊĠĠĠ Ġuser :< userid >: sus pension : Ġ{ ĊĠĠĠĠĠĠĠ Ġstart : Ġ< time >, ĊĠĠĠĠĠĠĠ Ġend : Ġ< time > ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġio :< ip >: sus pended _ until : Ġ< time > Ċ Ġ*/