Files
uPortal/internal/web/jitsi.go
T

113 lines
2.9 KiB
Go
Raw Normal View History

2026-10-15 23:25:46 +03:00
package web
import (
"fmt"
"net/http"
"strconv"
"uPortal/internal/auth"
)
// HandleJitsi renders the Jitsi room form on GET and redirects to Jitsi Meet on POST.
func (s *WebService) HandleJitsi(w http.ResponseWriter, r *http.Request) {
data, ok := s.basicViewData(w, r, "Jitsi")
if !ok {
http.Redirect(w, r, "/signin", http.StatusSeeOther)
return
}
switch r.Method {
case http.MethodGet:
s.render(w, r, "jitsi/token.html", data)
case http.MethodPost:
if err := auth.ValidateCsrf(r, CsrfCookieName, CsrfFieldName); err != nil {
data.Error = "Invalid form, please try again"
s.render(w, r, "jitsi/token.html", data)
return
}
if s.jitsiCfg == nil || s.jitsiCfg.Secret == "" {
data.Error = "Jitsi is not configured"
s.render(w, r, "jitsi/token.html", data)
return
}
room := r.FormValue("room")
if room == "" {
data.Error = "Room name is required"
s.render(w, r, "jitsi/token.html", data)
return
}
avatar := avatarURL(r, s, data.User.Id)
token, err := s.jitsiCfg.GenerateToken(
strconv.FormatInt(data.User.Id, 10),
data.User.EffectiveDisplayName(),
room,
data.User.SuperUser,
avatar,
)
if err != nil {
data.Error = "Could not generate token"
s.render(w, r, "jitsi/token.html", data)
return
}
http.Redirect(w, r, s.jitsiCfg.MeetURL(room, token), http.StatusSeeOther)
}
}
// HandleJitsiGo is a GET endpoint that reads a "room" query parameter,
// generates a JWT token, and redirects to the Jitsi Meet URL.
func (s *WebService) HandleJitsiGo(w http.ResponseWriter, r *http.Request) {
if s.jitsiCfg == nil || s.jitsiCfg.Secret == "" {
http.Error(w, "Jitsi is not configured", http.StatusInternalServerError)
return
}
user, err := s.currentUser(r)
if err != nil {
http.Redirect(w, r, "/signin", http.StatusSeeOther)
return
}
room := r.URL.Query().Get("room")
if room == "" {
http.Redirect(w, r, "/jitsi", http.StatusSeeOther)
return
}
avatar := avatarURL(r, s, user.Id)
token, err := s.jitsiCfg.GenerateToken(
strconv.FormatInt(user.Id, 10),
user.EffectiveDisplayName(),
room,
user.SuperUser,
avatar,
)
if err != nil {
http.Error(w, "Could not generate token", http.StatusInternalServerError)
return
}
http.Redirect(w, r, s.jitsiCfg.MeetURL(room, token), http.StatusSeeOther)
}
// avatarURL returns the app's avatar URL for the given user id, or an empty
// string if the user has no stored avatar. If the Jitsi site domain is
// configured, an absolute https:// URL is returned so Jitsi (running on a
// different domain) can load the avatar; otherwise a relative URL is used.
func avatarURL(r *http.Request, s *WebService, id int64) string {
data, err := s.users.GetAvatar(r.Context(), id)
if err != nil || len(data) == 0 {
return ""
}
path := fmt.Sprintf("/avatar/%d", id)
if s.jitsiCfg != nil && s.jitsiCfg.SiteDomain != "" {
return fmt.Sprintf("https://%s%s", s.jitsiCfg.SiteDomain, path)
}
return path
}