invitea/router/routes.go

180 lines
4.1 KiB
Go

package router
import (
"crypto/rand"
"database/sql"
"encoding/hex"
"net/http"
"strconv"
"time"
"go.jolheiser.com/invitea/api"
"go.jolheiser.com/invitea/database"
"go.jolheiser.com/invitea/static"
"code.gitea.io/sdk/gitea"
"github.com/go-chi/chi/v5"
"github.com/rs/zerolog/log"
)
type Routes struct {
DB *database.Queries
Gitea *gitea.Client
GiteaURL string
}
func (ro *Routes) Index(w http.ResponseWriter, r *http.Request) {
var isAdmin bool
if ia, ok := r.Context().Value("isAdmin").(bool); ok {
isAdmin = ia
}
dbInvites, err := ro.DB.ListInvites(r.Context())
if err != nil {
log.Err(err).Msg("")
}
if err := static.Templates.ExecuteTemplate(w, "index.tmpl", map[string]any{
"isAdmin": isAdmin,
"username": r.Context().Value("username"),
"invites": api.InvitesFromDB(dbInvites...),
}); err != nil {
log.Err(err).Msg("")
}
}
func (ro *Routes) IndexPost(w http.ResponseWriter, r *http.Request) {
action := r.FormValue("action")
if action == "" {
http.Redirect(w, r, "/", http.StatusBadRequest)
return
}
switch action {
case "delete":
id, err := strconv.ParseInt(r.FormValue("id"), 10, 64)
if err != nil {
http.Error(w, "invalid ID", http.StatusBadRequest)
return
}
if err := ro.DB.DeleteInvite(r.Context(), id); err != nil {
log.Err(err).Msg("could not delete invite")
http.Error(w, "could not delete invite", http.StatusInternalServerError)
return
}
case "create":
u := r.FormValue("uses")
var uses int64
if u != "" {
var err error
if uses, err = strconv.ParseInt(u, 10, 64); err != nil {
http.Error(w, "invalid uses", http.StatusBadRequest)
return
}
}
e := r.FormValue("expiration")
var expiration int64
if e != "" {
ex, err := time.Parse("2006-01-02", e)
if err != nil {
http.Error(w, "invalid expiration", http.StatusBadRequest)
return
}
expiration = ex.Unix()
}
code := make([]byte, 5)
if _, err := rand.Read(code); err != nil {
log.Err(err).Msg("could not generate code")
http.Error(w, "could not generate code", http.StatusInternalServerError)
return
}
if _, err := ro.DB.CreateInvite(r.Context(), database.CreateInviteParams{
Code: hex.EncodeToString(code),
Total: sql.NullInt64{
Int64: uses,
Valid: true,
},
Expiration: sql.NullInt64{
Int64: expiration,
Valid: true,
},
}); err != nil {
log.Err(err).Msg("could not create invite")
http.Error(w, "could not create invite", http.StatusInternalServerError)
return
}
}
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func (ro *Routes) Invite(w http.ResponseWriter, r *http.Request) {
code := chi.URLParam(r, "code")
dbInvite, err := ro.DB.GetInvite(r.Context(), code)
if err != nil {
log.Err(err).Str("code", code).Msg("could not get invite")
http.NotFound(w, r)
return
}
invite := api.InviteFromDB(dbInvite)
if !invite.Valid() {
http.NotFound(w, r)
return
}
if err := static.Templates.ExecuteTemplate(w, "invite.tmpl", map[string]any{
"invite": invite,
}); err != nil {
log.Err(err).Msg("")
}
}
func (ro *Routes) InvitePost(w http.ResponseWriter, r *http.Request) {
code := chi.URLParam(r, "code")
dbInvite, err := ro.DB.GetInvite(r.Context(), code)
if err != nil {
log.Err(err).Msg(code)
http.NotFound(w, r)
return
}
invite := api.InviteFromDB(dbInvite)
if !invite.Valid() {
http.NotFound(w, r)
return
}
username := r.FormValue("username")
password := r.FormValue("password")
email := r.FormValue("email")
var b bool
if _, _, err := ro.Gitea.AdminCreateUser(gitea.CreateUserOption{
Username: username,
Email: email,
Password: password,
MustChangePassword: &b,
}); err != nil {
log.Err(err).Msg("could not create user")
http.Error(w, "could not create user", http.StatusInternalServerError)
return
}
if err := ro.DB.UpdateInvite(r.Context(), database.UpdateInviteParams{
ID: dbInvite.ID,
Uses: dbInvite.Uses + 1,
}); err != nil {
log.Err(err).Msg("could not update invite")
http.Error(w, "could not update invite", http.StatusInternalServerError)
return
}
http.Redirect(w, r, ro.GiteaURL+"/user/login", http.StatusSeeOther)
}