@@ -730,3 +730,140 @@ func ResetPassword(ctx echo.Context) error {
730
730
"message" : "password reset successfully" ,
731
731
})
732
732
}
733
+
734
+ func AdminLogin (ctx echo.Context ) error {
735
+ var payload models.LoginRequest
736
+
737
+ if err := ctx .Bind (& payload ); err != nil {
738
+ return ctx .JSON (http .StatusBadRequest , map [string ]string {
739
+ "message" : err .Error (),
740
+ "status" : "fail" ,
741
+ })
742
+ }
743
+
744
+ if err := ctx .Validate (& payload ); err != nil {
745
+ return ctx .JSON (http .StatusBadRequest , map [string ]string {
746
+ "message" : err .Error (),
747
+ "status" : "fail" ,
748
+ })
749
+ }
750
+
751
+ payload .Email = strings .ToLower (payload .Email )
752
+
753
+ user , err := services .FindUserByEmail (payload .Email )
754
+ if err != nil {
755
+ if errors .Is (err , sql .ErrNoRows ) {
756
+ return ctx .JSON (http .StatusNotFound , map [string ]string {
757
+ "message" : "user does not exist" ,
758
+ "status" : "fail" ,
759
+ })
760
+ }
761
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
762
+ "messsage" : err .Error (),
763
+ "status" : "error" ,
764
+ })
765
+ }
766
+
767
+ if ! user .IsVerified {
768
+ return ctx .JSON (http .StatusForbidden , map [string ]string {
769
+ "message" : "User is not verified" ,
770
+ "status" : "fail" ,
771
+ })
772
+ }
773
+
774
+ if err := bcrypt .CompareHashAndPassword ([]byte (user .Password ), []byte (payload .Password )); err != nil {
775
+ if errors .Is (err , bcrypt .ErrMismatchedHashAndPassword ) {
776
+ return ctx .JSON (http .StatusConflict , map [string ]string {
777
+ "message" : "Invalid password" ,
778
+ "status" : "fail" ,
779
+ })
780
+ }
781
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
782
+ "message" : err .Error (),
783
+ "status" : "error" ,
784
+ })
785
+ }
786
+
787
+ tokenVersionStr , err := database .RedisClient .Get (
788
+ fmt .Sprintf ("token_version:%s" , user .User .Email ))
789
+ if err != nil && err != redis .Nil {
790
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
791
+ "status" : "error" ,
792
+ "message" : err .Error (),
793
+ })
794
+ }
795
+
796
+ tokenVersion , _ := strconv .Atoi (tokenVersionStr )
797
+
798
+ accessToken , err := utils .CreateToken (utils.TokenPayload {
799
+ Exp : time .Hour * 24 ,
800
+ Email : user .User .Email ,
801
+ Role : user .Role ,
802
+ TokenVersion : tokenVersion + 1 ,
803
+ }, utils .ACCESS_TOKEN )
804
+ if err != nil {
805
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
806
+ "message" : err .Error (),
807
+ "status" : "error" ,
808
+ })
809
+ }
810
+
811
+ refreshToken , err := utils .CreateToken (utils.TokenPayload {
812
+ Exp : time .Hour * 24 ,
813
+ Email : user .User .Email ,
814
+ }, utils .REFRESH_TOKEN )
815
+ if err != nil {
816
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
817
+ "message" : err .Error (),
818
+ "status" : "error" ,
819
+ })
820
+ }
821
+
822
+ if err := database .RedisClient .Set (fmt .Sprintf ("token_version:%s" , user .User .Email ),
823
+ fmt .Sprint (tokenVersion + 1 ), time .Hour * 1 ); err != nil {
824
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
825
+ "status" : "error" ,
826
+ "message" : err .Error (),
827
+ })
828
+ }
829
+
830
+ if err := database .RedisClient .Set (user .User .Email , refreshToken , time .Hour * 1 ); err != nil {
831
+ return ctx .JSON (http .StatusInternalServerError , map [string ]string {
832
+ "status" : "error" ,
833
+ "message" : err .Error (),
834
+ })
835
+ }
836
+
837
+ ctx .SetCookie (& http.Cookie {
838
+ Name : os .Getenv ("ACCESS_COOKIE_NAME" ),
839
+ Value : accessToken ,
840
+ HttpOnly : true ,
841
+ SameSite : http .SameSiteStrictMode ,
842
+ MaxAge : 86400 ,
843
+ Secure : true ,
844
+ })
845
+
846
+ ctx .SetCookie (& http.Cookie {
847
+ Name : os .Getenv ("REFRESH_COOKIE_NAME" ),
848
+ Value : refreshToken ,
849
+ HttpOnly : true ,
850
+ SameSite : http .SameSiteStrictMode ,
851
+ MaxAge : 86400 ,
852
+ Secure : true ,
853
+ })
854
+
855
+ if ! user .IsProfileComplete {
856
+ return ctx .JSON (http .StatusLocked , map [string ]interface {}{
857
+ "message" : "profile not completed" ,
858
+ "status" : "fail" ,
859
+ "data" : map [string ]interface {}{
860
+ "profile_complete" : user .IsProfileComplete ,
861
+ },
862
+ })
863
+ }
864
+
865
+ return ctx .JSON (http .StatusOK , map [string ]interface {}{
866
+ "message" : "login successful" ,
867
+ "status" : "success" ,
868
+ })
869
+ }
0 commit comments