263 lines
6.0 KiB
Go
263 lines
6.0 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
d "playback-device-server/data"
|
|
m "playback-device-server/management"
|
|
|
|
"github.com/labstack/echo/v4"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
type UsersApiHandler struct {
|
|
router *echo.Echo
|
|
userManager *m.UserManager
|
|
}
|
|
|
|
func (r *UsersApiHandler) Initialize(authenticator *Authenticator) {
|
|
r.router.Use(authenticator.Authenticate("/api/users", []string{"/api/users/login"}))
|
|
usersApi := r.router.Group("/api/users")
|
|
usersApi.POST("/login", r.handleLogin)
|
|
usersApi.POST("/logout", r.handleLogout)
|
|
usersApi.GET("/session/info", r.handleGetSessionInfo)
|
|
usersApi.POST("/newpassword", r.handleChangePassword)
|
|
usersApi.PUT("/:id", r.handleUpdateConfig)
|
|
usersApi.GET("", r.handleGetUsers)
|
|
usersApi.POST("", r.handleCreateUser)
|
|
usersApi.DELETE("/:id", r.handleDeleteUser)
|
|
}
|
|
|
|
func (r UsersApiHandler) handleLogin(context echo.Context) error {
|
|
var loginData struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
}
|
|
|
|
var errorResponse struct {
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
error := context.Bind(&loginData)
|
|
|
|
if error != nil {
|
|
log.Info().Msgf("failed to bind login data: %s", error)
|
|
errorResponse.Error = fmt.Sprintf("%s", error)
|
|
context.JSON(400, errorResponse)
|
|
return error
|
|
}
|
|
|
|
token, error := r.userManager.Login(loginData.Username, loginData.Password)
|
|
|
|
if error != nil {
|
|
log.Info().Msgf("failed to login: %s", error)
|
|
errorResponse.Error = fmt.Sprintf("%s", error)
|
|
context.JSON(400, errorResponse)
|
|
return error
|
|
}
|
|
|
|
thirdyDays := 30 * 24 * 60 * 60
|
|
|
|
cookie := &http.Cookie{
|
|
Name: "token",
|
|
Value: token,
|
|
Path: "/",
|
|
HttpOnly: true,
|
|
MaxAge: thirdyDays,
|
|
}
|
|
|
|
context.SetCookie(cookie)
|
|
|
|
return context.JSON(200, "")
|
|
}
|
|
|
|
func (r UsersApiHandler) handleLogout(context echo.Context) error {
|
|
r.removeTokenCookie(&context)
|
|
context.JSON(200, "")
|
|
|
|
authContext := context.(AuthContext)
|
|
|
|
session := authContext.Session
|
|
r.userManager.DeleteSession(session.Token)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r UsersApiHandler) handleChangePassword(context echo.Context) error {
|
|
authContext := context.(AuthContext)
|
|
user := authContext.User
|
|
|
|
var data struct {
|
|
CurrentPassword string `json:"currentPassword"`
|
|
NewPassword string `json:"newPassword"`
|
|
}
|
|
|
|
error := context.Bind(&data)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to change password: %s", error))
|
|
return error
|
|
}
|
|
|
|
error = r.userManager.UpdatePassword(data.CurrentPassword, data.NewPassword, user)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to change password: %s", error))
|
|
}
|
|
return error
|
|
}
|
|
|
|
func (r UsersApiHandler) handleGetSessionInfo(context echo.Context) error {
|
|
authContext := context.(AuthContext)
|
|
user := authContext.User
|
|
|
|
response := struct {
|
|
UserId string `json:"user_id"`
|
|
Username string `json:"username"`
|
|
IsAdmin bool `json:"is_admin"`
|
|
}{
|
|
UserId: user.ID,
|
|
Username: user.Username,
|
|
IsAdmin: user.IsAdmin,
|
|
}
|
|
|
|
return context.JSON(200, response)
|
|
}
|
|
|
|
func (r UsersApiHandler) handleGetUsers(context echo.Context) error {
|
|
users, error := r.userManager.GetUsers()
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("failed to get user list: %s", error))
|
|
}
|
|
|
|
return context.JSON(200, users)
|
|
}
|
|
|
|
func (r UsersApiHandler) handleCreateUser(context echo.Context) error {
|
|
authContext := context.(AuthContext)
|
|
user := authContext.User
|
|
|
|
if !user.IsAdmin {
|
|
SendError(403, context, "permission denied")
|
|
log.Info().Msg("failed to delete user: permission denied")
|
|
return fmt.Errorf("permission denied")
|
|
}
|
|
|
|
var newUser d.User
|
|
error := context.Bind(&newUser)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to create user: %s", error))
|
|
return error
|
|
}
|
|
|
|
id, error := r.userManager.CreateUser(&newUser)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to create user: %s", error))
|
|
return error
|
|
}
|
|
|
|
user.ID = id
|
|
|
|
return context.JSON(200, user)
|
|
}
|
|
|
|
func (r UsersApiHandler) handleDeleteUser(context echo.Context) error {
|
|
authContext := context.(AuthContext)
|
|
user := authContext.User
|
|
|
|
if !user.IsAdmin {
|
|
SendError(403, context, "permission denied")
|
|
log.Info().Msg("failed to delete user: permission denied")
|
|
return fmt.Errorf("permission denied")
|
|
}
|
|
|
|
id := context.Param("id")
|
|
|
|
exists, error := r.userManager.UserIdExists(id)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to delete user: %s", error))
|
|
return error
|
|
}
|
|
|
|
if !exists {
|
|
SendError(404, context, fmt.Sprintf("Failed to delete user: Could not find user id %s", id))
|
|
return fmt.Errorf("not found")
|
|
}
|
|
|
|
error = r.userManager.DeleteUser(id)
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to delete user: %s", error))
|
|
return error
|
|
}
|
|
|
|
return context.JSON(200, "")
|
|
}
|
|
|
|
func (r *UsersApiHandler) removeTokenCookie(context *echo.Context) {
|
|
cookie := &http.Cookie{
|
|
Name: "token",
|
|
Path: "/",
|
|
HttpOnly: true,
|
|
MaxAge: -1,
|
|
}
|
|
|
|
(*context).SetCookie(cookie)
|
|
}
|
|
|
|
func (r *UsersApiHandler) handleUpdateConfig(context echo.Context) error {
|
|
authContext := context.(AuthContext)
|
|
user := authContext.User
|
|
|
|
if !user.IsAdmin {
|
|
SendError(403, context, "permission denied")
|
|
log.Info().Msg("failed to delete user: permission denied")
|
|
return fmt.Errorf("permission denied")
|
|
}
|
|
|
|
id := context.Param("id")
|
|
|
|
data := struct {
|
|
IsAdmin int `json:"is_admin"`
|
|
}{
|
|
IsAdmin: -1,
|
|
}
|
|
|
|
error := context.Bind(&data)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to update user config: %s", error))
|
|
return error
|
|
}
|
|
|
|
updatingUser, error := r.userManager.GetUserById(id)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to update user config: %s", error))
|
|
return error
|
|
}
|
|
|
|
if user.ID != id && data.IsAdmin != -1 {
|
|
updatingUser.IsAdmin = data.IsAdmin == 1
|
|
}
|
|
|
|
error = r.userManager.UpdateUser(updatingUser)
|
|
|
|
if error != nil {
|
|
SendError(500, context, fmt.Sprintf("Failed to update user config: %s", error))
|
|
return error
|
|
}
|
|
|
|
return context.JSON(200, updatingUser)
|
|
}
|
|
|
|
func (r *UsersApiHandler) SetRouter(router *echo.Echo) {
|
|
r.router = router
|
|
}
|
|
|
|
func (r *UsersApiHandler) SetUserManager(userManager *m.UserManager) {
|
|
r.userManager = userManager
|
|
}
|