This commit is contained in:
Jordan Knott
2022-05-06 16:41:52 -05:00
parent 4f5aa2deb8
commit 64093e19f6
2156 changed files with 29717 additions and 80267 deletions

78
internal/api/api.go Normal file
View File

@ -0,0 +1,78 @@
package api
import (
"database/sql"
"time"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/cors"
"github.com/jordanknott/taskcafe/internal/db"
"github.com/sirupsen/logrus"
)
type TaskcafeApi struct {
Data db.Repository
}
func NewRouter(dbConnection *sql.DB) (chi.Router, error) {
formatter := new(logrus.TextFormatter)
formatter.TimestampFormat = "02-01-2006 15:04:05"
formatter.FullTimestamp = true
routerLogger := logrus.New()
routerLogger.SetLevel(logrus.InfoLevel)
routerLogger.Formatter = formatter
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
// r.Use(logger.NewStructuredLogger(routerLogger))
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second))
r.Use(cors.Handler(cors.Options{
AllowedOrigins: []string{"https://*", "http://*"},
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Cookie", "Content-Type", "X-CSRF-Token"},
ExposedHeaders: []string{"Link"},
AllowCredentials: true,
MaxAge: 300,
}))
repository := db.NewRepository(dbConnection)
taskcafeApi := TaskcafeApi{*repository}
r.Group(func(mux chi.Router) {
mux.Post("/auth/login", taskcafeApi.AuthLogin)
mux.Post("/public_settings", taskcafeApi.PublicSettings)
// mux.Post("/auth/logout", taskcafeApi.AuthLogout)
// mux.Post("/auth/me", taskcafeApi.AuthMe)
/*
mux.Handle("/__graphql", graph.NewPlaygroundHandler("/graphql"))
mux.Mount("/uploads/", http.StripPrefix("/uploads/", imgServer))
mux.Post("/auth/confirm", taskcafeHandler.ConfirmUser)
mux.Post("/auth/register", taskcafeHandler.RegisterUser)
mux.Get("/settings", taskcafeHandler.PublicSettings)
mux.Post("/logger", taskcafeHandler.HandleClientLog)
*/
})
/*
auth := AuthenticationMiddleware{*repository}
jobQueue := jobs.JobQueue{
Repository: *repository,
AppConfig: appConfig,
Server: jobServer,
}
r.Group(func(mux chi.Router) {
mux.Use(auth.Middleware)
mux.Post("/users/me/avatar", taskcafeHandler.ProfileImageUpload)
mux.Mount("/graphql", graph.NewHandler(*repository, appConfig, jobQueue, redisClient))
})
*/
// frontend := FrontendHandler{staticPath: "build", indexPath: "index.html"}
// r.Handle("/*", frontend)
return r, nil
}

View File

@ -0,0 +1,62 @@
package api
import (
"encoding/json"
"net/http"
"time"
"github.com/jordanknott/taskcafe/internal/util"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
)
type AuthLoginRequestData struct {
Username string `json:"username"`
Password string `json:"password"`
}
type AuthLoginResponseData struct {
UserID string `json:"userId`
}
func (api *TaskcafeApi) AuthLogin(w http.ResponseWriter, r *http.Request) {
var request AuthLoginRequestData
ctx := r.Context()
err := json.NewDecoder(r.Body).Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
logrus.WithError(err).Warn("bad request body")
return
}
userAccount, err := api.Data.GetUserAccountByUsername(ctx, request.Username)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
logrus.WithError(err).Debug("error while getting user account by username")
return
}
err = bcrypt.CompareHashAndPassword([]byte(userAccount.PasswordHash), []byte(request.Password))
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
logrus.WithError(err).Debug("error while hashing and comparing passwords")
}
createdAt := time.Now().UTC()
expiresAt := createdAt.AddDate(0, 0, 7)
token, err := util.GenerateAccessToken()
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
logrus.WithError(err).Error("error while creating new access token")
}
w.Header().Set("Content-type", "application/json")
http.SetCookie(w, &http.Cookie{
Name: "accessToken",
Value: token,
Expires: expiresAt,
Path: "/",
HttpOnly: true,
})
json.NewEncoder(w).Encode(AuthLoginResponseData{UserID: userAccount.UserID.String()})
}

56
internal/api/auth_me.go Normal file
View File

@ -0,0 +1,56 @@
package api
import (
"encoding/json"
"net/http"
"time"
"github.com/jordanknott/taskcafe/internal/util"
"github.com/sirupsen/logrus"
)
type AuthMeResponseData struct {
UserID string `json:"userId`
}
func (api *TaskcafeApi) AuthMe(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
c, err := r.Cookie("Authorization")
if err != nil {
logrus.WithError(err).Error("error while getting cookie")
w.WriteHeader(http.StatusUnauthorized)
return
}
token, err := api.Data.GetAccessToken(ctx, c.Value)
if err != nil {
logrus.WithError(err).Error("error while getting access cookie")
w.WriteHeader(http.StatusUnauthorized)
return
}
userAccount, err := api.Data.GetUserAccountByID(ctx, token.UserID)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
logrus.WithError(err).Debug("error while getting user account by username")
return
}
createdAt := time.Now().UTC()
expiresAt := createdAt.AddDate(0, 0, 7)
nextToken, err := util.GenerateAccessToken()
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
logrus.WithError(err).Error("error while creating new access token")
}
w.Header().Set("Content-type", "application/json")
http.SetCookie(w, &http.Cookie{
Name: "accessToken",
Value: nextToken,
Expires: expiresAt,
Path: "/",
HttpOnly: true,
})
json.NewEncoder(w).Encode(AuthLoginResponseData{UserID: userAccount.UserID.String()})
}

23
internal/api/settings.go Normal file
View File

@ -0,0 +1,23 @@
package api
import (
"encoding/json"
"net/http"
"github.com/sirupsen/logrus"
)
type PublicSettingsResponseData struct {
IsInstalled bool `json:"isInstalled"`
AllowPublicRegistration bool `json:"allowPublicRegistration`
}
func (api *TaskcafeApi) PublicSettings(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
isInstalled, err := api.Data.HasAnyUserAccount(ctx)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
logrus.WithError(err).Error()
}
json.NewEncoder(w).Encode(PublicSettingsResponseData{IsInstalled: isInstalled, AllowPublicRegistration: false})
}