@@ -2,18 +2,21 @@ package dao
2
2
3
3
import (
4
4
"OPP/auth/api"
5
+ "OPP/auth/auth/otp"
5
6
"OPP/auth/db"
6
7
"context"
7
8
"errors"
8
9
"fmt"
9
10
"strings"
11
+ "time"
10
12
)
11
13
12
14
var (
13
15
ErrUserAlreadyExists = errors .New ("user already exists" )
14
16
ErrInvalidUser = errors .New ("invalid user data" )
15
17
ErrUserNotFound = errors .New ("user not found" )
16
18
ErrInvalidPassword = errors .New ("invalid password" )
19
+ ErrOTPNotFound = errors .New ("OTP not found" )
17
20
)
18
21
19
22
type UserDao struct {
@@ -240,3 +243,59 @@ func (d *UserDao) DeleteUserById(c context.Context, id int64) error {
240
243
}
241
244
return nil
242
245
}
246
+
247
+ func (d * UserDao ) GenerateOTP (c context.Context , username string ) (api.OTPResponse , error ) {
248
+ user , err := d .GetUserByUsername (c , username )
249
+ if err != nil {
250
+ return api.OTPResponse {}, fmt .Errorf ("failed to get user: %w" , err )
251
+ }
252
+
253
+ // Create OTP
254
+ otpCode , exp_date , err := otp .GenerateOTP ()
255
+ if err != nil {
256
+ return api.OTPResponse {}, fmt .Errorf ("failed to generate OTP: %w" , err )
257
+ }
258
+ query := "INSERT INTO otps (user_id, otp_code, expires_at) VALUES ($1, $2, $3) RETURNING otp_id"
259
+ row := d .db .QueryRow (c , query , user .Id , otpCode , exp_date )
260
+ var otpId int64
261
+ err = row .Scan (& otpId )
262
+ if err != nil {
263
+ if strings .Contains (err .Error (), "UNIQUE constraint failed" ) {
264
+ return api.OTPResponse {}, ErrUserAlreadyExists
265
+ }
266
+ return api.OTPResponse {}, fmt .Errorf ("failed to insert OTP: %w" , err )
267
+ }
268
+ return api.OTPResponse {
269
+ Otp : otpCode ,
270
+ ValidUntil : exp_date ,
271
+ }, nil
272
+ }
273
+
274
+ func (d * UserDao ) ValidateOTP (c context.Context , otpCode string ) (bool , error ) {
275
+ // Check for currently valid OTP
276
+ query := `
277
+ SELECT otp_id, user_id, expires_at FROM otps
278
+ WHERE otp_code = $1 AND expires_at > CURRENT_TIMESTAMP
279
+ ORDER BY created_at DESC LIMIT 1
280
+ `
281
+ var otpID int64
282
+ var userID int64
283
+ var expiresAt time.Time
284
+
285
+ row := d .db .QueryRow (c , query , otpCode )
286
+ if err := row .Scan (& otpID , & userID , & expiresAt ); err != nil {
287
+ if strings .Contains (err .Error (), "no rows in result set" ) {
288
+ return false , nil
289
+ }
290
+ return false , fmt .Errorf ("failed to validate OTP: %w" , err )
291
+ }
292
+
293
+ // Delete already used OTP
294
+ deleteQuery := "DELETE FROM otps WHERE otp_id = $1"
295
+ _ , err := d .db .Exec (c , deleteQuery , otpID )
296
+ if err != nil {
297
+ fmt .Printf ("Failed to delete used OTP: %v\n " , err )
298
+ }
299
+
300
+ return true , nil
301
+ }
0 commit comments