From 51b9f2159691ebc2ddd5317dc47c2f62a75720cf Mon Sep 17 00:00:00 2001 From: Ada Conway Date: Mon, 10 Nov 2025 10:32:41 -0700 Subject: [PATCH] feat: wrap up user API functionality --- api/controllers/userController.go | 90 +++++++++++++++++++++++++++++++ api/main.go | 22 +++++--- api/queries/OrderQueries.go | 0 api/queries/UserQueries.go | 42 +++++++++++++-- 4 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 api/queries/OrderQueries.go diff --git a/api/controllers/userController.go b/api/controllers/userController.go index 42742c2..42cab92 100644 --- a/api/controllers/userController.go +++ b/api/controllers/userController.go @@ -9,6 +9,7 @@ import ( "strconv" "github.com/gin-gonic/gin" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) @@ -146,3 +147,92 @@ func GetUserTable(pool *pgxpool.Pool) gin.HandlerFunc { ctx.JSON(http.StatusOK, users) } } + +func GetCurrentAuthenticatedUser(pool *pgxpool.Pool) gin.HandlerFunc { + return func(ctx *gin.Context) { + conn, conn_err := pool.Acquire(ctx) + if conn_err != nil { + log.Printf("GetUserTable(): ERROR: Failed to connect... %s", conn_err.Error()) + ctx.AbortWithStatus(http.StatusInternalServerError) + } + defer conn.Release() + + user_profile, _ := ctx.Get("user_profile") + + sub_id := user_profile.(dto.UserProfileResponse).Sub + + var user dto.UserResponse + + query_err := conn.QueryRow(context.Background(), queries.GET_CURRENT_USER_OBJECT, sub_id).Scan(&user.Id, &user.Name, &user.Job_Position, &user.Active, &user.Admin) + if query_err != nil { + ctx.String(http.StatusInternalServerError, "GetCurrentAuthenticatedUser(): ERROR.... Failed to query") + log.Printf("GetCurrentAuthenticatedUser(): ERROR in querying user table... %s", query_err.Error()) + return + } + + ctx.JSON(http.StatusOK, user) + } +} + +func CreatePosition(pool *pgxpool.Pool) gin.HandlerFunc { + return func(ctx *gin.Context) { + conn, conn_err := pool.Acquire(ctx) + if conn_err != nil { + log.Printf("GetUserTable(): ERROR: Failed to connect... %s", conn_err.Error()) + ctx.AbortWithStatus(http.StatusInternalServerError) + return + } + defer conn.Release() + + position_name := ctx.Query("position_name") + if position_name == "" { + ctx.String(http.StatusBadRequest, "CreatePosition(): ERROR... Position name not supplied!") + return + } + + _, exec_err := conn.Exec(context.Background(), queries.CREATE_POSITION, position_name) + if exec_err != nil { + ctx.String(http.StatusInternalServerError, "CreatePosition(): ERROR... exec failed") + log.Println("CreatePosition(): ERROR... exec failed... %s", exec_err.Error()) + return + } + } +} + +func SetUserPosition(pool *pgxpool.Pool) gin.HandlerFunc { + return func(ctx *gin.Context) { + conn, conn_err := pool.Acquire(ctx) + if conn_err != nil { + log.Printf("GetUserTable(): ERROR: Failed to connect... %s", conn_err.Error()) + ctx.AbortWithStatus(http.StatusInternalServerError) + } + defer conn.Release() + + position_name := ctx.Query("position") + user_id := ctx.Query("user_id") + + if position_name == "" || user_id == "" { + ctx.String(http.StatusBadRequest, "SetUserPosition(): ERROR... Missing required parameter") + } + + var position_id string + var position_name_query string + query_err := conn.QueryRow(context.Background(), queries.POSITION_GET_POSITION, position_name).Scan(&position_id, &position_name_query) + if query_err != nil { + if query_err == pgx.ErrNoRows { + ctx.String(http.StatusBadRequest, "SetUserPosition(): ERROR... No such position exists.") + return + } + ctx.String(http.StatusInternalServerError, "SetUserPosition(): ERROR... Failed to query") + log.Println("SetUserPosition(): ERROR... Failed to query position table... %s", query_err.Error()) + return + } + + _, exec_err := conn.Exec(context.Background(), queries.USER_SET_POSITION, position_id, user_id) + if exec_err != nil { + ctx.String(http.StatusInternalServerError, "SetUserPosition(): ERROR... failed to update user object") + log.Println("SetUserPosition(): ERROR... Failed to update user object... %s", exec_err.Error()) + return + } + } +} diff --git a/api/main.go b/api/main.go index 87a9a4a..390aac3 100644 --- a/api/main.go +++ b/api/main.go @@ -56,19 +56,29 @@ func main() { store := cookie.NewStore([]byte(os.Getenv("COOKIE_SECRET"))) router.Use(sessions.Sessions("auth-session", store)) + // Middleware Function Declarations + user_authenticated := middleware.IsAuthenticated(authenticator) + user_in_db := middleware.UserInDatabase(pool) + user_active := middleware.UserIsActive(pool) + user_is_admin := middleware.IsAdmin(pool) + gob.Register(map[string]interface{}{}) - router.GET("/", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, controllers.BaseFunction) + router.GET("/", user_authenticated, middleware.GetUserProfile, controllers.BaseFunction) router.GET("/auth/login", auth.LoginHandler(authenticator)) router.GET("/auth/logout", auth.LogoutHandler) router.GET("/auth/logout_callback", auth.LogoutCallbackHandler(store)) router.GET("/callback", auth.AuthenticationCallbackHandler(authenticator)) - router.GET("/users", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, middleware.UserInDatabase(pool), middleware.UserIsActive(pool), middleware.IsAdmin(pool), controllers.GetUserTable(pool)) + router.GET("/users", user_authenticated, middleware.GetUserProfile, user_in_db, user_active, user_is_admin, controllers.GetUserTable(pool)) + router.GET("/user/current", user_authenticated, middleware.GetUserProfile, user_in_db, controllers.GetCurrentAuthenticatedUser(pool)) - router.POST("/user/name", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, middleware.UserInDatabase(pool), middleware.UserIsActive(pool), controllers.SetUserName(pool)) + router.POST("/user/name", user_authenticated, middleware.GetUserProfile, user_in_db, user_active, controllers.SetUserName(pool)) + router.POST("/position/create", user_authenticated, middleware.GetUserProfile, user_in_db, user_active, user_is_admin, controllers.CreatePosition(pool)) - router.PUT("/user/promote", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, middleware.UserInDatabase(pool), middleware.UserIsActive(pool), middleware.IsAdmin(pool), controllers.PromoteUser(pool)) - router.PUT("/user/demote", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, middleware.UserInDatabase(pool), middleware.UserIsActive(pool), middleware.IsAdmin(pool), controllers.DemoteUser(pool)) - router.DELETE("/user/deactivate", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, middleware.UserInDatabase(pool), middleware.UserIsActive(pool), middleware.IsAdmin(pool), controllers.DeactivateUser(pool)) + router.PUT("/user/promote", user_authenticated, middleware.GetUserProfile, user_in_db, user_active, user_is_admin, controllers.PromoteUser(pool)) + router.PUT("/user/demote", user_authenticated, middleware.GetUserProfile, user_in_db, user_active, user_is_admin, controllers.DemoteUser(pool)) + router.PUT("/user/position", user_authenticated, middleware.GetUserProfile, user_in_db, user_active, user_is_admin, controllers.SetUserPosition(pool)) + + router.DELETE("/user/deactivate", middleware.IsAuthenticated(authenticator), middleware.GetUserProfile, user_in_db, user_active, user_is_admin, controllers.DeactivateUser(pool)) router.Run("localhost:8080") } diff --git a/api/queries/OrderQueries.go b/api/queries/OrderQueries.go new file mode 100644 index 0000000..e69de29 diff --git a/api/queries/UserQueries.go b/api/queries/UserQueries.go index 62a281a..d77c828 100644 --- a/api/queries/UserQueries.go +++ b/api/queries/UserQueries.go @@ -22,14 +22,48 @@ UPDATE ordr_user SET active = FALSE WHERE id = $1; const USER_GET_TABLE_DATA string = ` SELECT - id, + ordr_user.id, user_name, - job_position, + position_name, active, is_admin FROM ordr_user + INNER JOIN ordr_position + ON job_position = ordr_position.id ORDER BY user_name -OFFSET $2 -LIMIT $3; +OFFSET $1 +LIMIT $2; +` + +const GET_CURRENT_USER_OBJECT string = ` +SELECT + ordr_user.id, + user_name, + position_name, + active, + is_admin +FROM + ordr_user + INNER JOIN ordr_position + ON job_position = ordr_position.id + AND ordr_user.sub_id = $1; +` + +const USER_SET_POSITION string = ` +UPDATE ordr_user SET job_position = $1 WHERE id = $2; +` + +const POSITION_GET_POSITION string = ` +SELECT + id, + position_name +FROM + ordr_position +WHERE + position_name LIKE '%' || $1 || '%' +` + +const CREATE_POSITION string = ` +INSERT INTO ordr_position(position_name) VALUES ($1) `