first commit

This commit is contained in:
Sas Andy
2024-12-09 09:51:19 +07:00
commit ecc5dfd9c0
69 changed files with 5365 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
package user
import (
"fmt"
"net/http"
"github.com/golang-jwt/jwt/v5"
"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.UserStore
errorStore types.ErrorLogStore
}
func NewHandler(store types.UserStore, errorStore types.ErrorLogStore) *Handler {
return &Handler{
store: store,
errorStore: errorStore,
}
}
func (h *Handler) RegisterRoutes(router *mux.Router) {
router.HandleFunc("/login", h.handleLogin).Methods("POST")
router.HandleFunc("/register", h.handleRegister).Methods("POST")
// admin routes
// router.HandleFunc("/users/{userID}", auth.WithJWTAuth(h.handleGetUser)).Methods(http.MethodGet)
}
func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
// var payload types.SignInPayload
// if err := utils.ParseJSON(r, &payload); err != nil {
// utils.WriteError(w, http.StatusBadRequest, err)
// return
// }
// if err := utils.Validate.Struct(payload); err != nil {
// errors := err.(validator.ValidationErrors)
// utils.WriteError(w, http.StatusBadRequest, fmt.Errorf("invalid payload: %v", errors))
// return
// }
// hashedPassword := auth.HashWithMD5(payload.Password)
// response, err := h.store.SignIn(payload.Email, hashedPassword)
// if err != nil {
// var logError *utils.LogError
// if errors.As(err, &logError) {
// h.errorStore.CreateErrorLog(*logError)
// utils.WriteErrorLog(w, http.StatusBadRequest, *logError)
// }
// return
// }
// // remoteAddr := r.RemoteAddr
// // userAgent := r.UserAgent()
// // response.IP = remoteAddr
// // response.Agent = userAgent
// secret := []byte(configs.Envs.JWTSecret)
// token, err := auth.CreateJWT(secret, *response)
// if err != nil {
// utils.WriteError(w, http.StatusInternalServerError, err)
// return
// }
// utils.WriteJSONLogin(w, http.StatusOK, response, token, "westone")
}
func (h *Handler) handleRegister(w http.ResponseWriter, r *http.Request) {
// var user types.RegisterUserPayload
// if err := utils.ParseJSON(r, &user); err != nil {
// utils.WriteError(w, http.StatusBadRequest, err)
// return
// }
// if err := utils.Validate.Struct(user); err != nil {
// errors := err.(validator.ValidationErrors)
// utils.WriteError(w, http.StatusBadRequest, fmt.Errorf("invalid payload: %v", errors))
// return
// }
// // check if user exists
// _, err := h.store.GetUserByEmail(user.Email)
// if err == nil {
// utils.WriteError(w, http.StatusBadRequest, fmt.Errorf("user with email %s already exists", user.Email))
// return
// }
// // hash password
// hashedPassword, err := auth.HashPassword(user.Password)
// if err != nil {
// utils.WriteError(w, http.StatusInternalServerError, err)
// return
// }
// err = h.store.CreateUser(types.User{
// FirstName: user.FirstName,
// LastName: user.LastName,
// Email: user.Email,
// Password: hashedPassword,
// })
// if err != nil {
// utils.WriteError(w, http.StatusInternalServerError, err)
// return
// }
// utils.WriteJSON(w, http.StatusCreated, nil)
}
func (h *Handler) handleGetUser(w http.ResponseWriter, r *http.Request) {
claims, ok := r.Context().Value(auth.UserContextKey).(jwt.MapClaims)
if !ok {
utils.WriteError(w, http.StatusInternalServerError, fmt.Errorf("token not found in context"))
return
}
email := claims["M_UserEmail"]
utils.WriteJSON(w, http.StatusOK, email)
}

View File

@@ -0,0 +1,77 @@
package user
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gorilla/mux"
"sismedika.com/sas/westone/types"
"sismedika.com/sas/westone/utils"
)
func TestUserServiceHandlers(t *testing.T) {
userStore := &mockUserStore{}
errorStore := &mockErrorLogStore{}
handler := NewHandler(userStore, errorStore)
t.Run("should fail if the user ID is not a number", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "/user/abc", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
router := mux.NewRouter()
router.HandleFunc("/user/{userID}", handler.handleGetUser).Methods(http.MethodGet)
router.ServeHTTP(rr, req)
if rr.Code != http.StatusBadRequest {
t.Errorf("expected status code %d, got %d", http.StatusBadRequest, rr.Code)
}
})
t.Run("should handle get user by ID", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "/user/42", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
router := mux.NewRouter()
router.HandleFunc("/user/{userID}", handler.handleGetUser).Methods(http.MethodGet)
router.ServeHTTP(rr, req)
if rr.Code != http.StatusOK {
t.Errorf("expected status code %d, got %d", http.StatusOK, rr.Code)
}
})
}
type mockUserStore struct{}
func (m *mockUserStore) UpdateUser(u types.User) error {
return nil
}
func (m *mockUserStore) SignIn(email string, password string) (*types.User, error) {
return &types.User{}, nil
}
func (m *mockUserStore) CreateUser(u types.User) error {
return nil
}
func (m *mockUserStore) GetUserByID(id int) (*types.User, error) {
return &types.User{}, nil
}
type mockErrorLogStore struct{}
func (n *mockErrorLogStore) CreateErrorLog(errval utils.LogError) error {
return nil
}

View File

@@ -0,0 +1,70 @@
package user
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) CreateUser(user types.User) error {
// Start a new transaction
// tx, err := s.db.BeginTxx(context.Background(), nil)
// if err != nil {
// return err
// }
// // Defer rollback to ensure the transaction is rolled back in case of an error
// defer func() {
// if err != nil {
// tx.Rollback()
// }
// }()
// query := `INSERT INTO users (firstName, lastName, email, password)
// VALUES (:firstName, :lastName, :email, :password)`
// // Using tx.NamedExec to insert the user within the transaction
// _, err = tx.NamedExec(query, user)
// if err != nil {
// return err
// }
// // Commit the transaction if everything succeeded
// if err = tx.Commit(); err != nil {
// return err
// }
return nil
}
func (s *Store) GetUserByID(id int) (*types.User, error) {
user := new(types.User)
qryget := `
SELECT
M_UserID,
M_UserEmail,
M_UserEmail as M_UserUsername,
M_UserGroupDashboard,
1 as M_UserDefaultT_SampleStationID,
IFNULL(M_UserFullName, "") as M_StaffName,
IFNULL(M_StaffIsCourier, "N") as is_courier,
IFNULL(S_SystemsAutoLogoutTime,0) as time_autologout
FROM m_user
JOIN m_usergroup ON M_UserM_UserGroupID = M_UserGroupID
LEFT JOIN m_staff on M_UserM_StaffID = M_StaffID
JOIN conf_systems ON S_SystemsIsActive = 'Y'
WHERE M_UserID = ?
`
if err := s.db.Get(user, qryget, id); err != nil {
return nil, err
}
return user, nil
}