busybar / internal / controllers / auth.controller.go
auth.controller.go
Raw
package controllers

import (
	"context"
	"fmt"
	"net/http"

	"github.com/danielrhuynh/busybar/internal/auth"
	"github.com/danielrhuynh/busybar/internal/models"
	"github.com/danielrhuynh/busybar/internal/services"
	"github.com/danielrhuynh/busybar/pkg/config"
	"github.com/jackc/pgx/v5"
	"github.com/labstack/echo/v4"
)

// func GetUserSession(c echo.Context) error {

// }

func GetAuthURL(c echo.Context) error {
	providerName := c.Param("provider")
	provider, ok := config.Config.OAuth[providerName]
	if !ok {
		return echo.NewHTTPError(http.StatusBadRequest, "bad provider")
	}

	authURL := provider.Config.AuthCodeURL("state")

	return c.JSON(http.StatusOK, envelope{
		"auth_url": authURL,
	})
}

func AuthCallback(c echo.Context) error {
	providerName := c.Param("provider")
	provider, ok := config.Config.OAuth[providerName]
	if !ok {
		return echo.NewHTTPError(http.StatusBadRequest, "bad provider")
	}
	providerConfig := provider.Config

	code := c.QueryParam("code")
	if code == "" {
		return echo.NewHTTPError(http.StatusBadRequest, "code is required")
	}

	token, err := providerConfig.Exchange(context.Background(), code)
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "failed to exchange token")
	}

	accountInfo, err := services.FetchAccountInfoFromProvider(provider, token)
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "failed to fetch account info")
	}

	var userSession *models.UserSession
	userSession, err = services.AuthGetUserSessionFromProvider(providerName, accountInfo["id"].(string))
	if err != nil && err != pgx.ErrNoRows {
		fmt.Println(err)
		return echo.NewHTTPError(http.StatusInternalServerError, "failed to get user session")
	}

	if userSession == nil {
		userSession, err = services.AuthCreateUserSession(providerName, accountInfo["id"].(string), token)
		if err != nil {
			return echo.NewHTTPError(http.StatusInternalServerError, "failed to create user session")
		}
	}

	session, err := services.AuthCreateSession(userSession.ID)
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "failed to create session")
	}

	redirectURL := fmt.Sprintf("busybar://auth?access_token=%s&refresh_token=%s", session.AccessToken, session.RefreshToken)
	return c.Redirect(http.StatusTemporaryRedirect, redirectURL)
}

func AuthGetSession(c echo.Context) error {
	user, err := auth.GetUser(c)
	if err != nil {
		return echo.NewHTTPError(http.StatusUnauthorized, "unauthorized")
	}

	return c.JSON(http.StatusOK, envelope{
		"user": user,
	})
}

func AuthLogout(c echo.Context) error {
	user, err := auth.GetUser(c)
	if err != nil {
		return echo.NewHTTPError(http.StatusUnauthorized, "unauthorized")
	}

	err = services.AuthDeleteSession(user.ID)
	if err != nil {
		return echo.NewHTTPError(http.StatusInternalServerError, "failed to delete session")
	}

	return c.NoContent(http.StatusNoContent)
}