Upgrade JS and Go deps versions (#517)
This commit is contained in:
@@ -19,7 +19,8 @@ func AESEncrypt(key, text []byte) ([]byte, error) {
|
||||
if _, err = io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: remove deprecated
|
||||
//nolint:staticcheck
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(ciphertext[aes.BlockSize:], text)
|
||||
|
||||
@@ -38,7 +39,8 @@ func AESDecrypt(key, ciphertext []byte) ([]byte, error) {
|
||||
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
ciphertext = ciphertext[aes.BlockSize:]
|
||||
|
||||
// TODO: remove deprecated
|
||||
//nolint:staticcheck
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
stream.XORKeyStream(ciphertext, ciphertext)
|
||||
|
||||
|
||||
@@ -4,20 +4,21 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"github.com/pquerna/otp/totp"
|
||||
"html/template"
|
||||
"image/png"
|
||||
"strings"
|
||||
|
||||
"github.com/pquerna/otp/totp"
|
||||
)
|
||||
|
||||
const secretSize = 16
|
||||
|
||||
func GenerateQRCode(username, siteUrl string, secret []byte) (string, template.URL, error, []byte) {
|
||||
func GenerateQRCode(username, siteUrl string, secret []byte) (string, template.URL, []byte, error) {
|
||||
var err error
|
||||
if secret == nil {
|
||||
secret, err = generateSecret()
|
||||
if err != nil {
|
||||
return "", "", err, nil
|
||||
return "", "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,22 +29,22 @@ func GenerateQRCode(username, siteUrl string, secret []byte) (string, template.U
|
||||
Secret: secret,
|
||||
})
|
||||
if err != nil {
|
||||
return "", "", err, nil
|
||||
return "", "", nil, err
|
||||
}
|
||||
|
||||
qrcode, err := otpKey.Image(320, 240)
|
||||
if err != nil {
|
||||
return "", "", err, nil
|
||||
return "", "", nil, err
|
||||
}
|
||||
|
||||
var imgBytes bytes.Buffer
|
||||
if err = png.Encode(&imgBytes, qrcode); err != nil {
|
||||
return "", "", err, nil
|
||||
return "", "", nil, err
|
||||
}
|
||||
|
||||
qrcodeImage := template.URL("data:image/png;base64," + base64.StdEncoding.EncodeToString(imgBytes.Bytes()))
|
||||
|
||||
return otpKey.Secret(), qrcodeImage, nil, secret
|
||||
return otpKey.Secret(), qrcodeImage, secret, nil
|
||||
}
|
||||
|
||||
func Validate(passcode, secret string) bool {
|
||||
|
||||
@@ -2,13 +2,14 @@ package webauthn
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/thomiceli/opengist/internal/config"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
var webAuthn *webauthn.WebAuthn
|
||||
@@ -101,7 +102,7 @@ func FinishDiscoverableLogin(jsonSession []byte, response *http.Request) (uint,
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return waUser.(*user).User.ID, nil
|
||||
return waUser.(*user).ID, nil
|
||||
}
|
||||
|
||||
func BeginLogin(dbUser *db.User) (credCreation *protocol.CredentialAssertion, jsonSession []byte, err error) {
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
func GetSetting(key string) (string, error) {
|
||||
var setting AdminSetting
|
||||
var err error
|
||||
switch db.Dialector.Name() {
|
||||
switch db.Name() {
|
||||
case "mysql", "sqlite":
|
||||
err = db.Where("`key` = ?", key).First(&setting).Error
|
||||
case "postgres":
|
||||
|
||||
@@ -395,7 +395,7 @@ func (gist *Gist) GetForks(currentUserId uint, offset int) ([]*Gist, error) {
|
||||
}
|
||||
|
||||
func (gist *Gist) CanWrite(user *User) bool {
|
||||
return !(user == nil) && (gist.UserID == user.ID)
|
||||
return user != nil && gist.UserID == user.ID
|
||||
}
|
||||
|
||||
func (gist *Gist) InitRepository() error {
|
||||
|
||||
@@ -16,7 +16,7 @@ type Invitation struct {
|
||||
|
||||
func GetAllInvitations() ([]*Invitation, error) {
|
||||
var invitations []*Invitation
|
||||
dialect := db.Dialector.Name()
|
||||
dialect := db.Name()
|
||||
query := db.Model(&Invitation{})
|
||||
|
||||
switch dialect {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
@@ -29,7 +30,7 @@ func (*binaryData) GormDataType() string {
|
||||
}
|
||||
|
||||
func (*binaryData) GormDBDataType(db *gorm.DB, _ *schema.Field) string {
|
||||
switch db.Dialector.Name() {
|
||||
switch db.Name() {
|
||||
case "sqlite":
|
||||
return "BLOB"
|
||||
case "mysql":
|
||||
@@ -67,7 +68,7 @@ func (*jsonData) GormDataType() string {
|
||||
}
|
||||
|
||||
func (*jsonData) GormDBDataType(db *gorm.DB, _ *schema.Field) string {
|
||||
switch db.Dialector.Name() {
|
||||
switch db.Name() {
|
||||
case "mysql", "sqlite":
|
||||
return "JSON"
|
||||
case "postgres":
|
||||
|
||||
@@ -268,6 +268,7 @@ type UserStyleDTO struct {
|
||||
RemovedLineColor string `form:"removedlinecolor" json:"removed_line_color" validate:"min=0,max=7"`
|
||||
AddedLineColor string `form:"addedlinecolor" json:"added_line_color" validate:"min=0,max=7"`
|
||||
GitLineColor string `form:"gitlinecolor" json:"git_line_color" validate:"min=0,max=7"`
|
||||
Theme string `form:"theme" json:"theme" validate:"oneof=light dark auto"`
|
||||
}
|
||||
|
||||
func (dto *UserStyleDTO) ToJson() string {
|
||||
|
||||
@@ -2,8 +2,9 @@ package db
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"time"
|
||||
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
)
|
||||
|
||||
type WebAuthnCredential struct {
|
||||
@@ -67,7 +68,7 @@ func GetUserByCredentialID(credID binaryData) (*User, error) {
|
||||
var credential WebAuthnCredential
|
||||
var err error
|
||||
|
||||
switch db.Dialector.Name() {
|
||||
switch db.Name() {
|
||||
case "postgres":
|
||||
hexCredID := hex.EncodeToString(credID)
|
||||
if err = db.Preload("User").Where("credential_id = decode(?, 'hex')", hexCredID).First(&credential).Error; err != nil {
|
||||
@@ -93,7 +94,7 @@ func GetCredentialByID(id binaryData) (*WebAuthnCredential, error) {
|
||||
var cred WebAuthnCredential
|
||||
var err error
|
||||
|
||||
switch db.Dialector.Name() {
|
||||
switch db.Name() {
|
||||
case "postgres":
|
||||
hexCredID := hex.EncodeToString(id)
|
||||
if err = db.Where("credential_id = decode(?, 'hex')", hexCredID).First(&cred).Error; err != nil {
|
||||
|
||||
@@ -50,9 +50,10 @@ func (store *LocaleStore) loadLocaleFromYAML(localeCode, path string) error {
|
||||
}
|
||||
|
||||
name := display.Self.Name(tag)
|
||||
if tag == language.AmericanEnglish {
|
||||
switch tag {
|
||||
case language.AmericanEnglish:
|
||||
name = "English"
|
||||
} else if tag == language.EuropeanSpanish {
|
||||
case language.EuropeanSpanish:
|
||||
name = "Español"
|
||||
}
|
||||
|
||||
|
||||
@@ -165,6 +165,10 @@ settings.style.removed-lines-color: Removed lines color
|
||||
settings.style.added-lines-color: Added lines color
|
||||
settings.style.git-lines-color: Git lines color
|
||||
settings.style.save-style: Save style
|
||||
settings.style.theme: Theme
|
||||
settings.style.theme-light: Light
|
||||
settings.style.theme-dark: Dark
|
||||
settings.style.theme-auto: Auto
|
||||
|
||||
auth.signup-disabled: Administrator has disabled signing up
|
||||
auth.login: Login
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/meilisearch/meilisearch-go"
|
||||
"github.com/rs/zerolog/log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/meilisearch/meilisearch-go"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type MeiliIndexer struct {
|
||||
@@ -82,7 +84,8 @@ func (i *MeiliIndexer) Add(gist *Gist) error {
|
||||
if gist == nil {
|
||||
return errors.New("failed to add nil gist to index")
|
||||
}
|
||||
_, err := (*atomicIndexer.Load()).(*MeiliIndexer).index.AddDocuments(gist, "GistID")
|
||||
primaryKey := "GistID"
|
||||
_, err := (*atomicIndexer.Load()).(*MeiliIndexer).index.AddDocuments(gist, &primaryKey)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -127,16 +130,20 @@ func (i *MeiliIndexer) Search(queryStr string, queryMetadata SearchGistMetadata,
|
||||
|
||||
gistIds := make([]uint, 0, len(response.Hits))
|
||||
for _, hit := range response.Hits {
|
||||
if gistID, ok := hit.(map[string]interface{})["GistID"].(float64); ok {
|
||||
gistIds = append(gistIds, uint(gistID))
|
||||
if gistIDRaw, ok := hit["GistID"]; ok {
|
||||
var gistID float64
|
||||
if err := json.Unmarshal(gistIDRaw, &gistID); err == nil {
|
||||
gistIds = append(gistIds, uint(gistID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
languageCounts := make(map[string]int)
|
||||
if facets, ok := response.FacetDistribution.(map[string]interface{})["Languages"]; ok {
|
||||
for language, count := range facets.(map[string]interface{}) {
|
||||
if countValue, ok := count.(float64); ok {
|
||||
languageCounts[language] = int(countValue)
|
||||
if len(response.FacetDistribution) > 0 {
|
||||
var facetDist map[string]map[string]int
|
||||
if err := json.Unmarshal(response.FacetDistribution, &facetDist); err == nil {
|
||||
if facets, ok := facetDist["Languages"]; ok {
|
||||
languageCounts = facets
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func (ctx *Context) ErrorRes(code int, message string, err error) error {
|
||||
}
|
||||
|
||||
func (ctx *Context) RedirectTo(location string) error {
|
||||
return ctx.Context.Redirect(302, config.C.ExternalUrl+location)
|
||||
return ctx.Redirect(302, config.C.ExternalUrl+location)
|
||||
}
|
||||
|
||||
func (ctx *Context) Html(template string) error {
|
||||
@@ -145,5 +145,6 @@ func (ctx *Context) Tr(key string, args ...any) string {
|
||||
var ManifestEntries map[string]Asset
|
||||
|
||||
type Asset struct {
|
||||
File string `json:"file"`
|
||||
File string `json:"file"`
|
||||
Css []string `json:"css"`
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/thomiceli/opengist/internal/auth/totp"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"github.com/thomiceli/opengist/internal/web/context"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func BeginTotp(ctx *context.Context) error {
|
||||
@@ -25,7 +26,7 @@ func BeginTotp(ctx *context.Context) error {
|
||||
sess := ctx.GetSession()
|
||||
generatedSecret, _ := sess.Values["generatedSecret"].([]byte)
|
||||
|
||||
totpSecret, qrcode, err, generatedSecret := totp.GenerateQRCode(ctx.User.Username, ogUrl.Hostname(), generatedSecret)
|
||||
totpSecret, qrcode, generatedSecret, err := totp.GenerateQRCode(ctx.User.Username, ogUrl.Hostname(), generatedSecret)
|
||||
if err != nil {
|
||||
return ctx.ErrorRes(500, "Cannot generate TOTP QR code", err)
|
||||
}
|
||||
|
||||
@@ -54,18 +54,19 @@ func AllGists(ctx *context.Context) error {
|
||||
|
||||
mode := ctx.GetData("mode")
|
||||
if fromUserStr == "" {
|
||||
if mode == "search" {
|
||||
switch mode {
|
||||
case "search":
|
||||
ctx.SetData("htmlTitle", ctx.TrH("gist.list.search-results"))
|
||||
ctx.SetData("searchQuery", ctx.QueryParam("q"))
|
||||
pagination.Query = ctx.QueryParam("q")
|
||||
urlPage = "search"
|
||||
gists, err = db.GetAllGistsFromSearch(currentUserId, ctx.QueryParam("q"), pageInt-1, sort, order, "")
|
||||
} else if mode == "topics" {
|
||||
case "topics":
|
||||
ctx.SetData("htmlTitle", ctx.TrH("gist.list.topic-results-topic", ctx.Param("topic")))
|
||||
ctx.SetData("topic", ctx.Param("topic"))
|
||||
urlPage = "topics/" + ctx.Param("topic")
|
||||
gists, err = db.GetAllGistsFromSearch(currentUserId, "", pageInt-1, sort, order, ctx.Param("topic"))
|
||||
} else if mode == "all" {
|
||||
case "all":
|
||||
ctx.SetData("htmlTitle", ctx.TrH("gist.list.all"))
|
||||
urlPage = "all"
|
||||
gists, err = db.GetAllGistsForCurrentUser(currentUserId, pageInt-1, sort, order)
|
||||
@@ -101,15 +102,16 @@ func AllGists(ctx *context.Context) error {
|
||||
ctx.SetData("countForked", countForked)
|
||||
}
|
||||
|
||||
if mode == "liked" {
|
||||
switch mode {
|
||||
case "liked":
|
||||
urlPage = fromUserStr + "/liked"
|
||||
ctx.SetData("htmlTitle", ctx.TrH("gist.list.all-liked-by", fromUserStr))
|
||||
gists, err = db.GetAllGistsLikedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order)
|
||||
} else if mode == "forked" {
|
||||
case "forked":
|
||||
urlPage = fromUserStr + "/forked"
|
||||
ctx.SetData("htmlTitle", ctx.TrH("gist.list.all-forked-by", fromUserStr))
|
||||
gists, err = db.GetAllGistsForkedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order)
|
||||
} else if mode == "fromUser" {
|
||||
case "fromUser":
|
||||
urlPage = fromUserStr
|
||||
|
||||
if languages, err := db.GetGistLanguagesForUser(fromUser.ID, currentUserId); err != nil {
|
||||
|
||||
@@ -22,10 +22,7 @@ func Create(ctx *context.Context) error {
|
||||
}
|
||||
|
||||
func ProcessCreate(ctx *context.Context) error {
|
||||
isCreate := false
|
||||
if ctx.Request().URL.Path == "/" {
|
||||
isCreate = true
|
||||
}
|
||||
isCreate := ctx.Request().URL.Path == "/"
|
||||
|
||||
err := ctx.Request().ParseForm()
|
||||
if err != nil {
|
||||
@@ -151,7 +148,7 @@ func ProcessCreate(ctx *context.Context) error {
|
||||
if err != nil {
|
||||
return ctx.ErrorRes(500, "Error creating an UUID", err)
|
||||
}
|
||||
gist.Uuid = strings.Replace(uuidGist.String(), "-", "", -1)
|
||||
gist.Uuid = strings.ReplaceAll(uuidGist.String(), "-", "")
|
||||
|
||||
gist.UserID = user.ID
|
||||
gist.User = *user
|
||||
|
||||
@@ -2,12 +2,13 @@ package gist
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"github.com/thomiceli/opengist/internal/web/context"
|
||||
"github.com/thomiceli/opengist/internal/web/handlers"
|
||||
"gorm.io/gorm"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Fork(ctx *context.Context) error {
|
||||
@@ -34,7 +35,7 @@ func Fork(ctx *context.Context) error {
|
||||
}
|
||||
|
||||
newGist := &db.Gist{
|
||||
Uuid: strings.Replace(uuidGist.String(), "-", "", -1),
|
||||
Uuid: strings.ReplaceAll(uuidGist.String(), "-", ""),
|
||||
Title: gist.Title,
|
||||
Preview: gist.Preview,
|
||||
PreviewFilename: gist.PreviewFilename,
|
||||
|
||||
@@ -97,8 +97,10 @@ func GistJson(ctx *context.Context) error {
|
||||
}
|
||||
|
||||
func GistJs(ctx *context.Context) error {
|
||||
theme := "light"
|
||||
if _, exists := ctx.QueryParams()["dark"]; exists {
|
||||
ctx.SetData("dark", "dark")
|
||||
theme = "dark"
|
||||
}
|
||||
|
||||
gist := ctx.GetData("gist").(*db.Gist)
|
||||
@@ -117,16 +119,21 @@ func GistJs(ctx *context.Context) error {
|
||||
}
|
||||
_ = w.Flush()
|
||||
|
||||
cssUrl, err := url.JoinPath(ctx.GetData("baseHttpUrl").(string), context.ManifestEntries["embed.css"].File)
|
||||
cssUrl, err := url.JoinPath(ctx.GetData("baseHttpUrl").(string), context.ManifestEntries["ts/embed.ts"].Css[0])
|
||||
if err != nil {
|
||||
return ctx.ErrorRes(500, "Error joining css url", err)
|
||||
}
|
||||
|
||||
js, err := escapeJavaScriptContent(htmlbuf.String(), cssUrl)
|
||||
themeUrl, err := url.JoinPath(ctx.GetData("baseHttpUrl").(string), context.ManifestEntries["ts/"+theme+".ts"].Css[0])
|
||||
if err != nil {
|
||||
return ctx.ErrorRes(500, "Error joining theme url", err)
|
||||
}
|
||||
|
||||
js, err := escapeJavaScriptContent(htmlbuf.String(), cssUrl, themeUrl)
|
||||
if err != nil {
|
||||
return ctx.ErrorRes(500, "Error escaping JavaScript content", err)
|
||||
}
|
||||
ctx.Response().Header().Set("Content-Type", "application/javascript")
|
||||
ctx.Response().Header().Set("Content-Type", "text/javascript")
|
||||
return ctx.PlainText(200, js)
|
||||
}
|
||||
|
||||
@@ -141,7 +148,7 @@ func Preview(ctx *context.Context) error {
|
||||
return ctx.PlainText(200, previewStr)
|
||||
}
|
||||
|
||||
func escapeJavaScriptContent(htmlContent, cssUrl string) (string, error) {
|
||||
func escapeJavaScriptContent(htmlContent, cssUrl, themeUrl string) (string, error) {
|
||||
jsonContent, err := gojson.Marshal(htmlContent)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to encode content: %w", err)
|
||||
@@ -152,11 +159,18 @@ func escapeJavaScriptContent(htmlContent, cssUrl string) (string, error) {
|
||||
return "", fmt.Errorf("failed to encode CSS URL: %w", err)
|
||||
}
|
||||
|
||||
jsonThemeUrl, err := gojson.Marshal(themeUrl)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to encode Theme URL: %w", err)
|
||||
}
|
||||
|
||||
js := fmt.Sprintf(`
|
||||
document.write('<link rel="stylesheet" href=%s>');
|
||||
document.write('<link rel="stylesheet" href=%s>');
|
||||
document.write(%s);
|
||||
`,
|
||||
string(jsonCssUrl),
|
||||
string(jsonThemeUrl),
|
||||
string(jsonContent),
|
||||
)
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ func createGist(user *db.User, url string) (*db.Gist, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gist.Uuid = strings.Replace(uuidGist.String(), "-", "", -1)
|
||||
gist.Uuid = strings.ReplaceAll(uuidGist.String(), "-", "")
|
||||
gist.Title = "gist:" + gist.Uuid
|
||||
|
||||
if url != "" {
|
||||
|
||||
@@ -92,6 +92,12 @@ func (s *Server) setFuncMap() {
|
||||
}
|
||||
return config.C.ExternalUrl + "/" + context.ManifestEntries[file].File
|
||||
},
|
||||
"assetCss": func(file string) string {
|
||||
if s.dev {
|
||||
return "http://localhost:16157/" + file
|
||||
}
|
||||
return config.C.ExternalUrl + "/" + context.ManifestEntries[file].Css[0]
|
||||
},
|
||||
"custom": func(file string) string {
|
||||
assetpath, err := url.JoinPath("/", "assets", file)
|
||||
if err != nil {
|
||||
@@ -186,6 +192,17 @@ func (s *Server) setFuncMap() {
|
||||
"humanDate": func(t int64) string {
|
||||
return time.Unix(t, 0).Format("02/01/2006 15:04")
|
||||
},
|
||||
"mainTheme": func(theme *db.UserStyleDTO) string {
|
||||
if theme == nil {
|
||||
return "auto"
|
||||
}
|
||||
|
||||
if theme.Theme == "" {
|
||||
return "auto"
|
||||
}
|
||||
|
||||
return theme.Theme
|
||||
},
|
||||
}
|
||||
|
||||
t := template.Must(template.New("t").Funcs(fm).ParseFS(templates.Files, "*/*.html"))
|
||||
@@ -206,7 +223,7 @@ func (s *Server) setFuncMap() {
|
||||
}
|
||||
|
||||
func (s *Server) parseManifestEntries() {
|
||||
file, err := public.Files.Open("manifest.json")
|
||||
file, err := public.Files.Open(".vite/manifest.json")
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to open manifest.json")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user