1+ package  com .scalekit .api .impl ;
2+ 
3+ import  com .scalekit .Environment ;
4+ import  com .scalekit .api .PasswordlessClient ;
5+ import  com .scalekit .exceptions .APIException ;
6+ import  com .scalekit .grpc .scalekit .v1 .auth .passwordless .*;
7+ import  com .scalekit .internal .RetryExecuter ;
8+ import  com .scalekit .internal .ScalekitCredentials ;
9+ import  com .scalekit .internal .http .SendPasswordlessOptions ;
10+ import  com .scalekit .internal .http .VerifyPasswordlessOptions ;
11+ import  io .grpc .ManagedChannel ;
12+ import  io .grpc .StatusRuntimeException ;
13+ 
14+ import  java .util .concurrent .TimeUnit ;
15+ 
16+ public  class  ScalekitPasswordlessClient  implements  PasswordlessClient  {
17+ 
18+     private  final  PasswordlessServiceGrpc .PasswordlessServiceBlockingStub  passwordlessStub ;
19+     private  final  ScalekitCredentials  credentials ;
20+ 
21+     public  ScalekitPasswordlessClient (ManagedChannel  channel , ScalekitCredentials  credentials ) {
22+         try  {
23+             this .credentials  = credentials ;
24+             this .passwordlessStub  = PasswordlessServiceGrpc 
25+                     .newBlockingStub (channel )
26+                     .withCallCredentials (credentials );
27+         } catch  (StatusRuntimeException  e ) {
28+             throw  new  RuntimeException ("Error creating Passwordless client" , e );
29+         }
30+     }
31+ 
32+     /** 
33+      * Send a passwordless authentication email 
34+      * @param email The email address to send the passwordless link to 
35+      * @param options The options for sending the passwordless email 
36+      * @return SendPasswordlessResponse The response containing auth request details 
37+      */ 
38+     @ Override 
39+     public  SendPasswordlessResponse  sendPasswordlessEmail (String  email , SendPasswordlessOptions  options ) {
40+         if  (email  == null  || email .trim ().isEmpty ()) {
41+             throw  new  IllegalArgumentException ("Email must be a valid string" );
42+         }
43+ 
44+         return  RetryExecuter .executeWithRetry (() -> {
45+             SendPasswordlessRequest .Builder  requestBuilder  = SendPasswordlessRequest .newBuilder ()
46+                     .setEmail (email );
47+ 
48+             if  (options  != null ) {
49+                 if  (options .getTemplate () != null ) {
50+                     requestBuilder .setTemplate (options .getTemplate ());
51+                 }
52+                 if  (options .getState () != null  && !options .getState ().trim ().isEmpty ()) {
53+                     requestBuilder .setState (options .getState ());
54+                 }
55+                 if  (options .getMagiclinkAuthUri () != null  && !options .getMagiclinkAuthUri ().trim ().isEmpty ()) {
56+                     requestBuilder .setMagiclinkAuthUri (options .getMagiclinkAuthUri ());
57+                 }
58+                 if  (options .getExpiresIn () != null  && options .getExpiresIn () > 0 ) {
59+                     requestBuilder .setExpiresIn (options .getExpiresIn ());
60+                 }
61+                 if  (options .getTemplateVariables () != null  && !options .getTemplateVariables ().isEmpty ()) {
62+                     requestBuilder .putAllTemplateVariables (options .getTemplateVariables ());
63+                 }
64+             }
65+ 
66+             return  this .passwordlessStub 
67+                     .withDeadlineAfter (Environment .defaultConfig ().timeout , TimeUnit .MILLISECONDS )
68+                     .sendPasswordlessEmail (requestBuilder .build ());
69+         }, this .credentials );
70+     }
71+ 
72+     /** 
73+      * Send a passwordless authentication email with default options 
74+      * @param email The email address to send the passwordless link to 
75+      * @return SendPasswordlessResponse The response containing auth request details 
76+      */ 
77+     @ Override 
78+     public  SendPasswordlessResponse  sendPasswordlessEmail (String  email ) {
79+         return  sendPasswordlessEmail (email , null );
80+     }
81+ 
82+     /** 
83+      * Verify a passwordless authentication code or link token 
84+      * @param credential The credential to verify (code or linkToken) 
85+      * @param authRequestId Optional auth request ID from the send response 
86+      * @return VerifyPasswordLessResponse The response containing verification details 
87+      */ 
88+     @ Override 
89+     public  VerifyPasswordLessResponse  verifyPasswordlessEmail (VerifyPasswordlessOptions  credential , String  authRequestId ) {
90+         if  (credential  == null ) {
91+             throw  new  IllegalArgumentException ("Credential cannot be null" );
92+         }
93+         if  ((credential .getCode () == null  || credential .getCode ().trim ().isEmpty ()) &&
94+             (credential .getLinkToken () == null  || credential .getLinkToken ().trim ().isEmpty ())) {
95+             throw  new  IllegalArgumentException ("Either code or linkToken must be provided" );
96+         }
97+ 
98+         return  RetryExecuter .executeWithRetry (() -> {
99+             VerifyPasswordLessRequest .Builder  requestBuilder  = VerifyPasswordLessRequest .newBuilder ();
100+ 
101+             if  (credential .getCode () != null  && !credential .getCode ().trim ().isEmpty ()) {
102+                 requestBuilder .setCode (credential .getCode ());
103+             } else  if  (credential .getLinkToken () != null  && !credential .getLinkToken ().trim ().isEmpty ()) {
104+                 requestBuilder .setLinkToken (credential .getLinkToken ());
105+             }
106+ 
107+             if  (authRequestId  != null  && !authRequestId .trim ().isEmpty ()) {
108+                 requestBuilder .setAuthRequestId (authRequestId );
109+             }
110+ 
111+             return  this .passwordlessStub 
112+                     .withDeadlineAfter (Environment .defaultConfig ().timeout , TimeUnit .MILLISECONDS )
113+                     .verifyPasswordlessEmail (requestBuilder .build ());
114+         }, this .credentials );
115+     }
116+ 
117+     /** 
118+      * Verify a passwordless authentication code or link token without auth request ID 
119+      * @param credential The credential to verify (code or linkToken) 
120+      * @return VerifyPasswordLessResponse The response containing verification details 
121+      */ 
122+     @ Override 
123+     public  VerifyPasswordLessResponse  verifyPasswordlessEmail (VerifyPasswordlessOptions  credential ) {
124+         return  verifyPasswordlessEmail (credential , null );
125+     }
126+ 
127+     /** 
128+      * Resend a passwordless authentication email 
129+      * @param authRequestId The auth request ID from the original send response 
130+      * @return SendPasswordlessResponse The response containing new auth request details 
131+      */ 
132+     @ Override 
133+     public  SendPasswordlessResponse  resendPasswordlessEmail (String  authRequestId ) {
134+         if  (authRequestId  == null  || authRequestId .trim ().isEmpty ()) {
135+             throw  new  IllegalArgumentException ("Auth request ID must be provided" );
136+         }
137+ 
138+         return  RetryExecuter .executeWithRetry (() -> {
139+             ResendPasswordlessRequest  request  = ResendPasswordlessRequest .newBuilder ()
140+                     .setAuthRequestId (authRequestId )
141+                     .build ();
142+ 
143+             return  this .passwordlessStub 
144+                     .withDeadlineAfter (Environment .defaultConfig ().timeout , TimeUnit .MILLISECONDS )
145+                     .resendPasswordlessEmail (request );
146+         }, this .credentials );
147+     }
148+ } 
0 commit comments