auto logout

This commit is contained in:
Sas Andy
2024-12-12 09:53:29 +07:00
parent ecc5dfd9c0
commit 66333ea727
13 changed files with 611 additions and 23 deletions

View File

@@ -13,6 +13,7 @@ import (
"sismedika.com/sas/westone/services/error_log" "sismedika.com/sas/westone/services/error_log"
"sismedika.com/sas/westone/services/patient" "sismedika.com/sas/westone/services/patient"
"sismedika.com/sas/westone/services/person" "sismedika.com/sas/westone/services/person"
"sismedika.com/sas/westone/services/staff"
"sismedika.com/sas/westone/services/terminology" "sismedika.com/sas/westone/services/terminology"
"sismedika.com/sas/westone/services/user" "sismedika.com/sas/westone/services/user"
) )
@@ -63,9 +64,14 @@ func (s *APIServer) Run() error {
// md doctor // md doctor
doctorStore := doctor.NewStore(s.db) doctorStore := doctor.NewStore(s.db)
doctorHandler := doctor.NewHandler(doctorStore) doctorHandler := doctor.NewHandler(doctorStore, oauthStore)
doctorHandler.RegisterRoutes(subrouter) doctorHandler.RegisterRoutes(subrouter)
// md staff
staffStore := staff.NewStore(s.db)
staffHandler := staff.NewHandler(staffStore, oauthStore)
staffHandler.RegisterRoutes(subrouter)
// userHandler := user.NewHandler(userStore, errorLogStore) // userHandler := user.NewHandler(userStore, errorLogStore)
// userHandler.RegisterRoutes(subrouter) // userHandler.RegisterRoutes(subrouter)

View File

@@ -2,10 +2,27 @@ POST http://localhost:8080/westone/api/v1/auth/login
Content-Type: application/json Content-Type: application/json
{ {
"email":"joko@gmail.com", "email":"joko",
"password":"sas321" "password":"sas321"
} }
###
POST http://localhost:8080/westone/api/v1/staff/getstaff
Content-Type: application/json
Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBZ2VudCI6InZzY29kZS1yZXN0Y2xpZW50IiwiSVAiOiIxMjcuMC4wLjE6NDkyOTciLCJJc19Db3VyaWVyIjoiIiwiTGFzdExvZ2luIjoiMjAyNC0xMi0xMSAxMTo1MDoxMSIsIk1fU3RhZmZOYW1lIjoiSm9rbyIsIk1fVXNlckRlZmF1bHRUU2FtcGxlU3RhdGlvbklEIjoiIiwiTV9Vc2VyRW1haWwiOiIiLCJNX1VzZXJHcm91cERhc2hib2FyZCI6Indlc3RvbmUtdWkvbG9naW4tY29iYS8iLCJNX1VzZXJJRCI6MSwiTV9Vc2VyTmFtZSI6Impva28iLCJUaW1lX0F1dG9sb2dvdXQiOiIxMDAwMDAwMCIsIlR5cGVfQWt1biI6Indlc3RvbmUiLCJWZXJzaW9uIjoidjEifQ.XYGlF8p_Dwopnbd91biQQEl1y0bOlb8j_EYEelgKLbE"
{
"staffname":"joko",
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBZ2VudCI6InZzY29kZS1yZXN0Y2xpZW50IiwiSVAiOiIxMjcuMC4wLjE6NDkyOTciLCJJc19Db3VyaWVyIjoiIiwiTGFzdExvZ2luIjoiMjAyNC0xMi0xMSAxMTo1MDoxMSIsIk1fU3RhZmZOYW1lIjoiSm9rbyIsIk1fVXNlckRlZmF1bHRUU2FtcGxlU3RhdGlvbklEIjoiIiwiTV9Vc2VyRW1haWwiOiIiLCJNX1VzZXJHcm91cERhc2hib2FyZCI6Indlc3RvbmUtdWkvbG9naW4tY29iYS8iLCJNX1VzZXJJRCI6MSwiTV9Vc2VyTmFtZSI6Impva28iLCJUaW1lX0F1dG9sb2dvdXQiOiIxMDAwMDAwMCIsIlR5cGVfQWt1biI6Indlc3RvbmUiLCJWZXJzaW9uIjoidjEifQ.XYGlF8p_Dwopnbd91biQQEl1y0bOlb8j_EYEelgKLbE"
}
###
POST http://localhost:8080/westone/api/v1/staff/getstaff
Content-Type: application/json
Authorization: "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBZ2VudCI6InZzY29kZS1yZXN0Y2xpZW50IiwiSVAiOiIxMjcuMC4wLjE6NDkzMzUiLCJJc19Db3VyaWVyIjoiIiwiTGFzdExvZ2luIjoiMjAyNC0xMi0xMSAwODoyODowNyIsIk1fU3RhZmZOYW1lIjoiSm9rbyIsIk1fVXNlckRlZmF1bHRUU2FtcGxlU3RhdGlvbklEIjoiIiwiTV9Vc2VyRW1haWwiOiIiLCJNX1VzZXJHcm91cERhc2hib2FyZCI6Indlc3RvbmUtdWkvbG9naW4tY29iYS8iLCJNX1VzZXJJRCI6MSwiTV9Vc2VyTmFtZSI6Impva28iLCJUaW1lX0F1dG9sb2dvdXQiOiIxMDAwMDAwMCIsIlR5cGVfQWt1biI6Indlc3RvbmUiLCJWZXJzaW9uIjoidjEifQ.pwb3btxL74UrdRb9otnWTi36aL15plT4KKBRMmRPELU"
{
"staffname":"joko"
}
#### ####
# POST http://localhost:8080/api/v1/auth/google/linking # POST http://localhost:8080/api/v1/auth/google/linking
# Content-Type: application/json # Content-Type: application/json

View File

@@ -29,14 +29,16 @@ func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.UserAgent()) fmt.Println(r.UserAgent())
if err := utils.ParseJSON(r, &payload); err != nil { if err := utils.ParseJSON(r, &payload); err != nil {
utils.WriteError(w, http.StatusBadRequest, err) utils.WriteError(w, http.StatusBadRequest, err)
h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone") // h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone")
h.store.LogRISLogin(0, r.UserAgent(), payload.Email, err.Error(), "FAILED")
return return
} }
if err := utils.Validate.Struct(payload); err != nil { if err := utils.Validate.Struct(payload); err != nil {
errorz := err.(validator.ValidationErrors) errorz := err.(validator.ValidationErrors)
utils.WriteError(w, http.StatusBadRequest, fmt.Errorf("invalid payload: %v", errorz)) utils.WriteError(w, http.StatusBadRequest, fmt.Errorf("invalid payload: %v", errorz))
h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone") // h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone")
h.store.LogRISLogin(0, r.UserAgent(), payload.Email, err.Error(), "FAILED")
return return
} }
@@ -48,7 +50,8 @@ func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
h.errorz.CreateErrorLog(*logError) h.errorz.CreateErrorLog(*logError)
utils.WriteErrorLog(w, http.StatusBadRequest, *logError) utils.WriteErrorLog(w, http.StatusBadRequest, *logError)
} }
h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone") // h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone")
h.store.LogRISLogin(0, r.UserAgent(), response.M_StaffName, "FAILED", err.Error())
return return
} }
@@ -63,7 +66,34 @@ func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
utils.WriteError(w, http.StatusInternalServerError, err) utils.WriteError(w, http.StatusInternalServerError, err)
h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone") // h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone")
h.store.LogRISLogin(0, r.UserAgent(), payload.Email, err.Error(), "FAILED")
return
}
err = h.store.UpdateUserToken(response.M_UserID, token)
if err != nil {
fmt.Println("err diluar", err)
tst := h.store.LogRISLogin(0, r.UserAgent(), payload.Email, err.Error(), "FAILED")
if tst != nil {
fmt.Println("err log ris login", tst)
}
var logError *utils.LogError
if errors.As(err, &logError) {
h.errorz.CreateErrorLog(*logError)
utils.WriteErrorLog(w, http.StatusBadRequest, *logError)
}
return
}
err = h.store.LogRISLogin(response.M_UserID, r.UserAgent(), response.M_StaffName, "SUCCESS", "SUCCESS")
if err != nil {
var logError *utils.LogError
if errors.As(err, &logError) {
h.errorz.CreateErrorLog(*logError)
utils.WriteErrorLog(w, http.StatusBadRequest, *logError)
}
// h.store.LogSignIn(payload.Email, r.RemoteAddr, "FAILED", "LOGIN", "westone")
return return
} }

View File

@@ -2,6 +2,8 @@ package auth
import ( import (
"context" "context"
"fmt"
"strconv"
"time" "time"
"sismedika.com/sas/westone/types" "sismedika.com/sas/westone/types"
@@ -16,7 +18,7 @@ func (s *Store) SignInWestone(email string, password string) (*types.User, error
M_UserID, M_UserID,
M_UserName, M_UserName,
M_UserGroupDashboard, M_UserGroupDashboard,
IFNULL(M_UserFullName, "") as M_StaffName, M_StaffName,
10000000 as time_autologout 10000000 as time_autologout
FROM m_user FROM m_user
JOIN m_usergroup ON M_UserM_UserGroupID = M_UserGroupID JOIN m_usergroup ON M_UserM_UserGroupID = M_UserGroupID
@@ -66,11 +68,282 @@ func (s *Store) LogSignIn(email string, ip string, status string, tipe string, p
_, err = tx.NamedExec(qry, logval) _, err = tx.NamedExec(qry, logval)
if err != nil { if err != nil {
return err return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "email: " + email,
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
} }
if err = tx.Commit(); err != nil { if err = tx.Commit(); err != nil {
return err return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "email: " + email,
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
return nil
}
func (s *Store) LogRISLogin(userID int, userAgent string, userName string, message string, status string) error {
tx, err := s.db.BeginTxx(context.Background(), nil)
if err != nil {
return err
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
logval := types.LogRISLogin{
LogLoginM_UserID: strconv.Itoa(userID),
LogLoginDateTime: time.Now().Format("2006-01-02 15:04:05"),
LogLoginUserAgent: userAgent,
LogLoginUserName: userName,
LogLoginMessage: message,
LogLoginStatus: status,
}
qry := `INSERT INTO log_login
(Log_LoginM_UserID, Log_LoginDateTime, Log_LoginUserAgent, Log_LoginUserName, Log_LoginMessage, Log_LoginStatus)
VALUES (:Log_LoginM_UserID, :Log_LoginDateTime, :Log_LoginUserAgent, :Log_LoginUserName, :Log_LoginMessage, :Log_LoginStatus)`
_, err = tx.NamedExec(qry, logval)
if err != nil {
return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "userName: " + userName,
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
if err = tx.Commit(); err != nil {
return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "userName: " + userName,
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
return nil
}
func (s *Store) UpdateUserToken(userID int, token string) error {
tx, err := s.db.BeginTxx(context.Background(), nil)
if err != nil {
return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "",
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
qrySys := `SELECT Conf_SystemIsAutoLogOut, Conf_SystemAutoLogOutDuration FROM conf_system LIMIT 1`
var isAutoLogOut string
var autoLogOutDuration int
err = s.db.QueryRow(qrySys).Scan(&isAutoLogOut, &autoLogOutDuration)
if err != nil {
return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "AUTH",
Params: "",
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
expiredDate := time.Now().Add(time.Duration(autoLogOutDuration) * time.Minute)
qry := `UPDATE m_user SET M_UserToken = :token, M_UserExpiredToken = :expiredDate WHERE M_UserID = :userID`
_, err = tx.NamedExec(qry, map[string]interface{}{
"token": token,
"userID": userID,
"expiredDate": expiredDate.Format("2006-01-02 15:04:05"),
})
// fmt.Println("err", err)
if err != nil {
return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "",
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
if err = tx.Commit(); err != nil {
return &utils.LogError{
Code: "151",
TraceID: utils.RandomTraceID(15),
Type: "LOG AUTH",
Params: "",
Query: "-",
Message: err.Error(),
TimeStamp: time.Now().Format("2006-01-02 15:04:05"),
}
}
return nil
}
func (s *Store) UpdateExpiredToken(token string) error {
// fmt.Printf("Masuk expired token")
tx, err := s.db.BeginTxx(context.Background(), nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %v", err)
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
qrySys := `SELECT Conf_SystemIsAutoLogOut, Conf_SystemAutoLogOutDuration FROM conf_system LIMIT 1`
var isAutoLogOut string
var autoLogOutDuration int
err = s.db.QueryRow(qrySys).Scan(&isAutoLogOut, &autoLogOutDuration)
if err != nil {
return fmt.Errorf("failed to get system config: %v", err)
}
if isAutoLogOut == "Y" {
qryEt := `SELECT DATE_FORMAT(M_UserExpiredToken, '%Y-%m-%d %H:%i:%s') as M_UserExpiredToken FROM m_user WHERE M_UserToken = ?`
var expiredToken string
err = s.db.Get(&expiredToken, qryEt, token)
if err != nil {
return fmt.Errorf("failed to get expired token: %v", err)
}
timeNow := time.Now().Format("2006-01-02 15:04:05")
expiredTime, err := time.Parse("2006-01-02 15:04:05", expiredToken)
if err != nil {
return fmt.Errorf("failed to parse expired token: %v", err)
}
timeNowParsed, err := time.Parse("2006-01-02 15:04:05", timeNow)
if err != nil {
return fmt.Errorf("failed to parse current time: %v", err)
}
if timeNowParsed.After(expiredTime) {
fmt.Printf("timenow: %v, expiredTime: %v", timeNow, expiredTime)
// fmt.Println("token expired")
return fmt.Errorf("token expired")
} else {
// fmt.Println("token belum expired")
fmt.Printf("timenow: %v, expiredTime: %v", timeNow, expiredTime)
}
timeNowAdd := timeNowParsed.Add(time.Duration(autoLogOutDuration) * time.Minute)
qryUpdateExpiredToken := `UPDATE m_user SET M_UserExpiredToken = ? WHERE M_UserToken = ?`
_, err = tx.Exec(qryUpdateExpiredToken, timeNowAdd.Format("2006-01-02 15:04:05"), token)
if err != nil {
return fmt.Errorf("failed to update expired token: %v", err)
}
if err = tx.Commit(); err != nil {
return fmt.Errorf("failed to commit transaction: %v", err)
}
}
return nil
}
func (s *Store) UpdateExpiredTokenBu(userID int) error {
fmt.Printf("Masuk expired token")
tx, err := s.db.BeginTxx(context.Background(), nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %v", err)
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
qrySys := `SELECT Conf_SystemIsAutoLogOut, Conf_SystemAutoLogOutDuration FROM conf_system LIMIT 1`
var isAutoLogOut string
var autoLogOutDuration int
err = s.db.QueryRow(qrySys).Scan(&isAutoLogOut, &autoLogOutDuration)
if err != nil {
return fmt.Errorf("failed to get system config: %v", err)
}
if isAutoLogOut == "Y" {
qryEt := `SELECT DATE_FORMAT(M_UserExpiredToken, '%Y-%m-%d %H:%i:%s') as M_UserExpiredToken FROM m_user WHERE M_UserID = ?`
var expiredToken string
err = s.db.Get(&expiredToken, qryEt, userID)
if err != nil {
return fmt.Errorf("failed to get expired token: %v", err)
}
timeNow := time.Now().Format("2006-01-02 15:04:05")
expiredTime, err := time.Parse("2006-01-02 15:04:05", expiredToken)
if err != nil {
return fmt.Errorf("failed to parse expired token: %v", err)
}
timeNowParsed, err := time.Parse("2006-01-02 15:04:05", timeNow)
if err != nil {
return fmt.Errorf("failed to parse current time: %v", err)
}
if timeNowParsed.After(expiredTime) {
fmt.Printf("timenow: %v, expiredTime: %v", timeNow, expiredTime)
fmt.Println("token expired")
return fmt.Errorf("token expired")
} else {
fmt.Println("token belum expired")
fmt.Printf("timenow: %v, expiredTime: %v", timeNow, expiredTime)
}
timeNowAdd := timeNowParsed.Add(time.Duration(autoLogOutDuration) * time.Minute)
qryUpdateExpiredToken := `UPDATE m_user SET M_UserExpiredToken = ? WHERE M_UserID = ?`
_, err = tx.Exec(qryUpdateExpiredToken, timeNowAdd.Format("2006-01-02 15:04:05"), userID)
if err != nil {
return fmt.Errorf("failed to update expired token: %v", err)
}
if err = tx.Commit(); err != nil {
return fmt.Errorf("failed to commit transaction: %v", err)
}
} }
return nil return nil

View File

@@ -5,8 +5,10 @@ import (
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
"time"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
"github.com/jmoiron/sqlx"
"sismedika.com/sas/westone/configs" "sismedika.com/sas/westone/configs"
"sismedika.com/sas/westone/types" "sismedika.com/sas/westone/types"
"sismedika.com/sas/westone/utils" "sismedika.com/sas/westone/utils"
@@ -64,7 +66,7 @@ func CreateJWT(data types.DataJWT) (string, error) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"M_UserID": data.M_UserID, "M_UserID": data.M_UserID,
"M_UserEmail": data.M_UserEmail, "M_UserEmail": data.M_UserEmail,
"M_UserUsername": data.M_UserUsername, "M_UserName": data.M_UserName,
"M_UserGroupDashboard": data.M_UserGroupDashboard, "M_UserGroupDashboard": data.M_UserGroupDashboard,
"M_UserDefaultTSampleStationID": data.M_UserDefaultTSampleStationID, "M_UserDefaultTSampleStationID": data.M_UserDefaultTSampleStationID,
"M_StaffName": data.M_StaffName, "M_StaffName": data.M_StaffName,
@@ -88,7 +90,9 @@ func CreateJWT(data types.DataJWT) (string, error) {
func validateJWT(tokenString string) (*jwt.Token, error) { func validateJWT(tokenString string) (*jwt.Token, error) {
return jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) err := fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
fmt.Printf("Error validating JWT token: %v\n", err)
return nil, err
} }
return []byte(configs.Envs.JWTSecret), nil return []byte(configs.Envs.JWTSecret), nil
@@ -98,6 +102,9 @@ func validateJWT(tokenString string) (*jwt.Token, error) {
func permissionDenied(w http.ResponseWriter) { func permissionDenied(w http.ResponseWriter) {
utils.WriteError(w, http.StatusForbidden, fmt.Errorf("PERMISSION DENIED")) utils.WriteError(w, http.StatusForbidden, fmt.Errorf("PERMISSION DENIED"))
} }
func tokenExpired(w http.ResponseWriter) {
utils.WriteError(w, http.StatusForbidden, fmt.Errorf("TOKEN EXPIRED"))
}
func GetUserIDFromContext(ctx context.Context) int { func GetUserIDFromContext(ctx context.Context) int {
userID, ok := ctx.Value(UserContextKey).(int) userID, ok := ctx.Value(UserContextKey).(int)
@@ -132,3 +139,125 @@ func AuthMiddleware(next http.Handler) http.Handler {
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }
func WithAuthStore(store types.OauthStore) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "auth_store", store)
//start
tokenstr := utils.GetTokenFromRequest(r)
token, err := validateJWT(tokenstr)
if err != nil {
log.Printf("[ERROR] Failed to validate jwt token: %v", err)
permissionDenied(w)
return
}
if !token.Valid {
log.Println("[ERROR] Invalid token")
permissionDenied(w)
return
}
// claims := token.Claims.(jwt.MapClaims)
// userID := int(claims["M_UserID"].(float64))
// Ambil store dari context
// fmt.Printf("store: %v", store)
// store, ok := r.Context().Value("auth_store").(types.OauthStore)
// if !ok {
// log.Println("[ERROR] Auth store not found in context")
// permissionDenied(w)
// return
// }
// Update expired token
if err := store.UpdateExpiredToken(tokenstr); err != nil {
if err.Error() == "token expired" {
tokenExpired(w)
} else {
log.Printf("[ERROR] Failed to update token expiry: %v", err)
permissionDenied(w)
}
return
}
//end
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
func UpdateExpiredTokentest(userID int, db *sqlx.DB) error {
tx, err := db.BeginTxx(context.Background(), nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %v", err)
}
defer func() {
if err != nil {
tx.Rollback()
}
}()
qrySys := `SELECT Conf_SystemIsAutoLogOut, Conf_SystemAutoLogOutDuration FROM conf_system LIMIT 1`
var isAutoLogOut string
var autoLogOutDuration int
err = db.QueryRow(qrySys).Scan(&isAutoLogOut, &autoLogOutDuration)
if err != nil {
return fmt.Errorf("failed to get system config: %v", err)
}
if isAutoLogOut == "Y" {
qryEt := `SELECT DATE_FORMAT(M_UserExpiredToken, '%Y-%m-%d %H:%i:%s') as M_UserExpiredToken FROM m_user WHERE M_UserID = ?`
var expiredToken string
err = db.Get(&expiredToken, qryEt, userID)
if err != nil {
return fmt.Errorf("failed to get expired token: %v", err)
}
timeNow := time.Now()
expiredTime, err := time.Parse("2006-01-02 15:04:05", expiredToken)
if err != nil {
return fmt.Errorf("failed to parse expired token: %v", err)
}
if timeNow.After(expiredTime) {
return fmt.Errorf("token expired")
}
timeNowAdd := timeNow.Add(time.Duration(autoLogOutDuration) * time.Minute)
qryUpdateExpiredToken := `UPDATE m_user SET M_UserExpiredToken = ? WHERE M_UserID = ?`
_, err = tx.Exec(qryUpdateExpiredToken, timeNowAdd.Format("2006-01-02 15:04:05"), userID)
if err != nil {
return fmt.Errorf("failed to update expired token: %v", err)
}
qry := `UPDATE m_user SET M_UserExpiredToken = NOW() WHERE M_UserID = :userID`
_, err = tx.NamedExec(qry, map[string]interface{}{
"userID": userID,
})
fmt.Println("err", err)
if err != nil {
return fmt.Errorf("failed to update expired token: %v", err)
}
if err = tx.Commit(); err != nil {
return fmt.Errorf("failed to commit transaction: %v", err)
}
}
return nil
}
// Middleware untuk menyimpan store ke context
func WithStore(store *Store) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), "store", store)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}

View File

@@ -45,6 +45,7 @@ func (h *Handler) RegisterRoutes(router *mux.Router) {
authroute.HandleFunc("/{provider}/authcode", h.handlerRedirectCode).Methods(http.MethodGet) authroute.HandleFunc("/{provider}/authcode", h.handlerRedirectCode).Methods(http.MethodGet)
protec := authroute.PathPrefix("/redirect").Subrouter() protec := authroute.PathPrefix("/redirect").Subrouter()
protec.Use(AuthMiddleware) protec.Use(AuthMiddleware)
protec.HandleFunc("/dashboard", h.handleRedirectDash).Methods(http.MethodGet) protec.HandleFunc("/dashboard", h.handleRedirectDash).Methods(http.MethodGet)
} }

View File

@@ -12,15 +12,17 @@ import (
) )
type Handler struct { type Handler struct {
store types.DoctorStore store types.DoctorStore
authStore types.OauthStore
} }
func NewHandler(store types.DoctorStore) *Handler { func NewHandler(store types.DoctorStore, authStore types.OauthStore) *Handler {
return &Handler{store: store} return &Handler{store: store, authStore: authStore}
} }
func (h *Handler) RegisterRoutes(router *mux.Router) { func (h *Handler) RegisterRoutes(router *mux.Router) {
doctorroutes := router.PathPrefix("/mddoctor").Subrouter() doctorroutes := router.PathPrefix("/mddoctor").Subrouter()
doctorroutes.Use(auth.WithAuthStore(h.authStore))
doctorroutes.Use(auth.AuthMiddleware) doctorroutes.Use(auth.AuthMiddleware)
doctorroutes.HandleFunc("/searchdoctor", h.handlerSearchDoctor).Methods(http.MethodPost) doctorroutes.HandleFunc("/searchdoctor", h.handlerSearchDoctor).Methods(http.MethodPost)

View File

@@ -0,0 +1,61 @@
package staff
import (
"fmt"
"net/http"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
"sismedika.com/sas/westone/services/auth"
"sismedika.com/sas/westone/types"
"sismedika.com/sas/westone/utils"
)
type Handler struct {
store types.StaffStore
authStore types.OauthStore
}
func NewHandler(store types.StaffStore, authStore types.OauthStore) *Handler {
return &Handler{store: store, authStore: authStore}
}
func (h *Handler) RegisterRoutes(router *mux.Router) {
staffRoute := router.PathPrefix("/staff").Subrouter()
staffRoute.Use(auth.WithAuthStore(h.authStore))
staffRoute.HandleFunc("/getstaff", h.handelGetStaff).Methods(http.MethodPost)
staffRoute.HandleFunc("/", h.coba).Methods(http.MethodPost)
}
func (h *Handler) coba(w http.ResponseWriter, r *http.Request) {
var payload types.GetStaffPayload
if err := utils.ParseJSON(r, &payload); err != nil {
utils.WriteError(w, http.StatusBadRequest, err)
return
}
fmt.Printf("payload: %+v\n", payload)
fmt.Printf("COBA")
utils.WriteJSON(w, http.StatusOK, payload)
}
func (h *Handler) handelGetStaff(w http.ResponseWriter, r *http.Request) {
var payload types.GetStaffPayload
if err := utils.ParseJSON(r, &payload); err != nil {
utils.WriteError(w, http.StatusBadRequest, err)
return
}
if err := utils.Validate.Struct(payload); err != nil {
erros := err.(validator.ValidationErrors)
utils.WriteError(w, http.StatusBadRequest, fmt.Errorf("invalid payload: %v", erros))
return
}
response, err := h.store.GetStaff(payload.StaffName)
if err != nil {
utils.WriteError(w, http.StatusInternalServerError, err)
return
}
utils.WriteJSON(w, http.StatusOK, response)
}

View File

@@ -0,0 +1,34 @@
package staff
import (
"github.com/jmoiron/sqlx"
"sismedika.com/sas/westone/types"
)
type Store struct {
db *sqlx.DB
}
func NewStore(db *sqlx.DB) *Store {
return &Store{db: db}
}
func (s *Store) GetStaff(name string) (*types.Staff, error) {
term := new(types.Staff)
Keyword := "%" + name + "%"
qry := `SELECT
M_StaffID,
M_StaffName,
M_StaffEmail,
M_StaffNakesID,
M_StaffIsActive
FROM m_staff
WHERE (M_StaffName LIKE ? OR M_StaffEmail LIKE ? )
AND M_StaffIsActive = 'Y'
`
if err := s.db.Get(term, qry, Keyword, Keyword); err != nil {
return nil, err
}
return term, nil
}

View File

@@ -1,6 +1,8 @@
package types package types
import "github.com/markbates/goth" import (
"github.com/markbates/goth"
)
type OauthStore interface { type OauthStore interface {
AddGoolgeAccount(user UserGoogle) error AddGoolgeAccount(user UserGoogle) error
@@ -9,6 +11,9 @@ type OauthStore interface {
CompareAuthCode(authcode string, user goth.User, typez string) (int, error) CompareAuthCode(authcode string, user goth.User, typez string) (int, error)
SignInWestone(email string, password string) (*User, error) SignInWestone(email string, password string) (*User, error)
LogSignIn(email string, ip string, status string, tipe string, provider string) error LogSignIn(email string, ip string, status string, tipe string, provider string) error
LogRISLogin(userID int, userAgent string, userName string, message string, status string) error
UpdateUserToken(userID int, token string) error
UpdateExpiredToken(token string) error
} }
type UserGoogle struct { type UserGoogle struct {
@@ -41,7 +46,7 @@ type GenerateAuthCode struct {
} }
type SignInPayload struct { type SignInPayload struct {
Email string `json:"email" validate:"required,email"` Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required,min=6,max=130"` Password string `json:"password" validate:"required,min=6,max=130"`
} }
@@ -55,3 +60,11 @@ type LogLogin struct {
LogLoginIsActive string `db:"Log_LoginIsActive" json:"logLoginIsActive"` LogLoginIsActive string `db:"Log_LoginIsActive" json:"logLoginIsActive"`
LogLoginLastUpdated string `db:"Log_LoginLastUpdated" json:"logLoginLastUpdated"` LogLoginLastUpdated string `db:"Log_LoginLastUpdated" json:"logLoginLastUpdated"`
} }
type LogRISLogin struct {
LogLoginM_UserID string `db:"Log_LoginM_UserID" json:"LogLoginM_UserID"`
LogLoginDateTime string `db:"Log_LoginDateTime" json:"LogLoginDateTime"`
LogLoginUserAgent string `db:"Log_LoginUserAgent" json:"LogLoginUserAgent"`
LogLoginStatus string `db:"Log_LoginStatus" json:"LogLoginStatus"`
LogLoginUserName string `db:"Log_LoginUserName" json:"LogLoginUserName"`
LogLoginMessage string `db:"Log_LoginMessage" json:"LogLoginMessage"`
}

16
types/staff.types.go Normal file
View File

@@ -0,0 +1,16 @@
package types
type StaffStore interface {
GetStaff(name string) (*Staff, error)
}
type Staff struct {
M_StaffID int `json:"M_StaffID" db:"M_StaffID"`
M_StaffName string `json:"M_StaffName" db:"M_StaffName"`
M_StaffEmail string `json:"M_StaffEmail" db:"M_StaffEmail"`
M_StaffNakesID string `json:"M_StaffNakesID" db:"M_StaffNakesID"`
M_StaffIsActive string `json:"M_StaffIsActive" db:"M_StaffIsActive"`
}
type GetStaffPayload struct {
StaffName string `json:"staffname"`
}

View File

@@ -23,7 +23,8 @@ type RegisterUserPayload struct {
type User struct { type User struct {
M_UserID int `json:"M_UserID" db:"M_UserID"` M_UserID int `json:"M_UserID" db:"M_UserID"`
M_UserEmail string `json:"M_UserEmail" db:"M_UserEmail"` M_UserEmail string `json:"M_UserEmail" db:"M_UserEmail"`
M_UserUsername string `json:"M_UserUsername" db:"M_UserUsername"` M_UserName string `json:"M_UserName" db:"M_UserName"`
M_UserExpiredToken string `json:"M_UserExpiredToken" db:"M_UserExpiredToken"`
M_UserGroupDashboard string `json:"M_UserGroupDashboard" db:"M_UserGroupDashboard"` M_UserGroupDashboard string `json:"M_UserGroupDashboard" db:"M_UserGroupDashboard"`
M_UserDefaultTSampleStationID string `json:"M_UserDefaultT_SampleStationID" db:"M_UserDefaultT_SampleStationID"` M_UserDefaultTSampleStationID string `json:"M_UserDefaultT_SampleStationID" db:"M_UserDefaultT_SampleStationID"`
M_StaffName string `json:"M_StaffName" db:"M_StaffName"` M_StaffName string `json:"M_StaffName" db:"M_StaffName"`

View File

@@ -42,16 +42,21 @@ func ParseJSON(r *http.Request, v any) error {
} }
func GetTokenFromRequest(r *http.Request) string { func GetTokenFromRequest(r *http.Request) string {
tokenAuth := r.Header.Get("Authorization") // fmt.Printf("Request: %v\n", r.)
if strings.HasPrefix(tokenAuth, "Bearer ") { var tokenAuth string
return strings.TrimPrefix(tokenAuth, "Bearer ") tokenAuth = r.Header.Get("Authorization")
} // fmt.Printf("Token Auth: %v\n", tokenAuth)
tokenQuery := r.URL.Query().Get("token") tokenQuery := r.URL.Query().Get("token")
// fmt.Printf("Token Query: %v\n", tokenQuery)
if tokenQuery != "" { if tokenQuery != "" {
return tokenQuery tokenAuth = tokenQuery
} }
return "" tokenAuth = strings.TrimSpace(tokenAuth)
tokenAuth = strings.ReplaceAll(tokenAuth, "Bearer", "")
tokenAuth = strings.ReplaceAll(tokenAuth, "\"", "")
tokenAuth = strings.TrimSpace(tokenAuth)
return tokenAuth
} }
func MatchStruct(src interface{}, dst interface{}) error { func MatchStruct(src interface{}, dst interface{}) error {