119 lines
2.6 KiB
Go
119 lines
2.6 KiB
Go
package rest
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"net/http"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"goAuth/internal/invite"
|
||
|
|
)
|
||
|
|
|
||
|
|
type createInviteRequest struct {
|
||
|
|
Quota int `json:"quota"`
|
||
|
|
ExpiresInHours int `json:"expiresInHours"`
|
||
|
|
ExpiresAt string `json:"expiresAt"`
|
||
|
|
}
|
||
|
|
|
||
|
|
type inviteResponse struct {
|
||
|
|
Token string `json:"token"`
|
||
|
|
Quota int `json:"quota"`
|
||
|
|
Uses int `json:"uses"`
|
||
|
|
ExpiresAt time.Time `json:"expiresAt"`
|
||
|
|
CreatedAt time.Time `json:"createdAt"`
|
||
|
|
Valid bool `json:"valid"`
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) listInvites(w http.ResponseWriter, r *http.Request) {
|
||
|
|
limit, offset := pagination(r)
|
||
|
|
invites, err := h.invites.Invites(r.Context(), limit, offset)
|
||
|
|
if err != nil {
|
||
|
|
h.fail(w, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
result := make([]inviteResponse, 0, len(invites))
|
||
|
|
for _, i := range invites {
|
||
|
|
result = append(result, newInviteResponse(i))
|
||
|
|
}
|
||
|
|
|
||
|
|
writeJson(w, http.StatusOK, result)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) getInvite(w http.ResponseWriter, r *http.Request) {
|
||
|
|
token := r.PathValue("token")
|
||
|
|
invite, err := h.invites.InviteByToken(r.Context(), token)
|
||
|
|
if err != nil {
|
||
|
|
h.fail(w, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
writeJson(w, http.StatusOK, newInviteResponse(invite))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) createInvite(w http.ResponseWriter, r *http.Request) {
|
||
|
|
var req createInviteRequest
|
||
|
|
if err := decodeJson(r, &req); err != nil {
|
||
|
|
writeError(w, http.StatusBadRequest, "invalid request body")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
quota := req.Quota
|
||
|
|
if quota <= 0 {
|
||
|
|
quota = 1
|
||
|
|
}
|
||
|
|
|
||
|
|
expiresAt, err := inviteExpiry(req)
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusBadRequest, "invalid expiration")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
invite, err := h.invites.CreateInvite(r.Context(), quota, expiresAt)
|
||
|
|
if err != nil {
|
||
|
|
h.fail(w, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
writeJson(w, http.StatusCreated, newInviteResponse(invite))
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) deleteInvite(w http.ResponseWriter, r *http.Request) {
|
||
|
|
token := r.PathValue("token")
|
||
|
|
invite, err := h.invites.InviteByToken(r.Context(), token)
|
||
|
|
if err != nil {
|
||
|
|
h.fail(w, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := h.invites.DeleteInvite(r.Context(), invite); err != nil {
|
||
|
|
h.fail(w, err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
writeNoContent(w)
|
||
|
|
}
|
||
|
|
|
||
|
|
func newInviteResponse(i *invite.Invite) inviteResponse {
|
||
|
|
return inviteResponse{
|
||
|
|
Token: i.Token,
|
||
|
|
Quota: i.Quota,
|
||
|
|
Uses: i.Uses,
|
||
|
|
ExpiresAt: i.ExpiresAt,
|
||
|
|
CreatedAt: i.CreatedAt,
|
||
|
|
Valid: i.IsValid(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func inviteExpiry(req createInviteRequest) (time.Time, error) {
|
||
|
|
if req.ExpiresAt != "" {
|
||
|
|
parsed, err := time.Parse(time.RFC3339, req.ExpiresAt)
|
||
|
|
if err != nil {
|
||
|
|
return time.Time{}, err
|
||
|
|
}
|
||
|
|
return parsed.UTC(), nil
|
||
|
|
}
|
||
|
|
|
||
|
|
hours := req.ExpiresInHours
|
||
|
|
if hours <= 0 {
|
||
|
|
hours = 24 * 7
|
||
|
|
}
|
||
|
|
return time.Now().UTC().Add(time.Duration(hours) * time.Hour), nil
|
||
|
|
}
|