Properly handle error and improve error messages

This commit is contained in:
2024-09-21 11:26:25 +07:00
parent 557e7313b2
commit bcdcbd5049
25 changed files with 258 additions and 234 deletions

View File

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/app"
googleOauthSetupHandler "github.com/fossyy/filekeeper/handler/auth/google/setup" googleOauthSetupHandler "github.com/fossyy/filekeeper/handler/auth/google/setup"
signinHandler "github.com/fossyy/filekeeper/handler/signin"
"github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/session"
"github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types"
"github.com/fossyy/filekeeper/utils" "github.com/fossyy/filekeeper/utils"
@ -49,7 +48,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
_, err := app.Server.Cache.GetCache(r.Context(), "CsrfTokens:"+r.URL.Query().Get("state")) _, err := app.Server.Cache.GetCache(r.Context(), "CsrfTokens:"+r.URL.Query().Get("state"))
if err != nil { if err != nil {
if errors.Is(err, redis.Nil) { if errors.Is(err, redis.Nil) {
w.WriteHeader(http.StatusUnauthorized) http.Redirect(w, r, fmt.Sprintf("/signin?error=%s", "csrf_token_error"), http.StatusFound)
return return
} }
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
@ -155,7 +154,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
} }
userAgent := r.Header.Get("User-Agent") userAgent := r.Header.Get("User-Agent")
browserInfo, osInfo := signinHandler.ParseUserAgent(userAgent) browserInfo, osInfo := utils.ParseUserAgent(userAgent)
sessionInfo := session.SessionInfo{ sessionInfo := session.SessionInfo{
SessionID: storeSession.ID, SessionID: storeSession.ID,
@ -168,17 +167,24 @@ func GET(w http.ResponseWriter, r *http.Request) {
} }
storeSession.Save(w) storeSession.Save(w)
session.AddSessionInfo(oauthUser.Email, &sessionInfo) err = session.AddSessionInfo(oauthUser.Email, &sessionInfo)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
cookie, err := r.Cookie("redirect") cookie, err := r.Cookie("redirect")
if errors.Is(err, http.ErrNoCookie) { if errors.Is(err, http.ErrNoCookie) {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
http.SetCookie(w, &http.Cookie{ http.SetCookie(w, &http.Cookie{
Name: "redirect", Name: "redirect",
MaxAge: -1, MaxAge: -1,
}) })
http.Redirect(w, r, cookie.Value, http.StatusSeeOther) http.Redirect(w, r, cookie.Value, http.StatusSeeOther)
return return
} }

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/app"
signinHandler "github.com/fossyy/filekeeper/handler/signin"
"github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/session"
"github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types"
"github.com/fossyy/filekeeper/types/models" "github.com/fossyy/filekeeper/types/models"
@ -121,11 +120,12 @@ func POST(w http.ResponseWriter, r *http.Request) {
}) })
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
userAgent := r.Header.Get("User-Agent") userAgent := r.Header.Get("User-Agent")
browserInfo, osInfo := signinHandler.ParseUserAgent(userAgent) browserInfo, osInfo := utils.ParseUserAgent(userAgent)
sessionInfo := session.SessionInfo{ sessionInfo := session.SessionInfo{
SessionID: storeSession.ID, SessionID: storeSession.ID,
@ -138,7 +138,12 @@ func POST(w http.ResponseWriter, r *http.Request) {
} }
storeSession.Save(w) storeSession.Save(w)
session.AddSessionInfo(unregisteredUser.Email, &sessionInfo) err = session.AddSessionInfo(unregisteredUser.Email, &sessionInfo)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
http.Redirect(w, r, "/user", http.StatusSeeOther) http.Redirect(w, r, "/user", http.StatusSeeOther)
return return

View File

@ -2,13 +2,13 @@ package totpHandler
import ( import (
"errors" "errors"
"github.com/fossyy/filekeeper/app"
"github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/session"
"github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types"
"github.com/fossyy/filekeeper/utils" "github.com/fossyy/filekeeper/utils"
"github.com/fossyy/filekeeper/view/client/totp" "github.com/fossyy/filekeeper/view/client/totp"
"github.com/xlzd/gotp" "github.com/xlzd/gotp"
"net/http" "net/http"
"strings"
"time" "time"
) )
@ -31,7 +31,12 @@ func GET(w http.ResponseWriter, r *http.Request) {
} }
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
r.ParseForm() err := r.ParseForm()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
code := r.Form.Get("code") code := r.Form.Get("code")
_, user, key := session.GetSession(r) _, user, key := session.GetSession(r)
totp := gotp.NewDefaultTOTP(user.Totp) totp := gotp.NewDefaultTOTP(user.Totp)
@ -46,13 +51,12 @@ func POST(w http.ResponseWriter, r *http.Request) {
}) })
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
if err != nil {
return
}
userAgent := r.Header.Get("User-Agent") userAgent := r.Header.Get("User-Agent")
browserInfo, osInfo := ParseUserAgent(userAgent) browserInfo, osInfo := utils.ParseUserAgent(userAgent)
sessionInfo := session.SessionInfo{ sessionInfo := session.SessionInfo{
SessionID: storeSession.ID, SessionID: storeSession.ID,
@ -65,7 +69,12 @@ func POST(w http.ResponseWriter, r *http.Request) {
} }
storeSession.Save(w) storeSession.Save(w)
session.AddSessionInfo(user.Email, &sessionInfo) err = session.AddSessionInfo(user.Email, &sessionInfo)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
cookie, err := r.Cookie("redirect") cookie, err := r.Cookie("redirect")
if errors.Is(err, http.ErrNoCookie) { if errors.Is(err, http.ErrNoCookie) {
@ -91,64 +100,3 @@ func POST(w http.ResponseWriter, r *http.Request) {
} }
} }
func ParseUserAgent(userAgent string) (map[string]string, map[string]string) {
browserInfo := make(map[string]string)
osInfo := make(map[string]string)
if strings.Contains(userAgent, "Firefox") {
browserInfo["browser"] = "Firefox"
parts := strings.Split(userAgent, "Firefox/")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
browserInfo["version"] = version
}
} else if strings.Contains(userAgent, "Chrome") {
browserInfo["browser"] = "Chrome"
parts := strings.Split(userAgent, "Chrome/")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
browserInfo["version"] = version
}
} else {
browserInfo["browser"] = "Unknown"
browserInfo["version"] = "Unknown"
}
if strings.Contains(userAgent, "Windows") {
osInfo["os"] = "Windows"
parts := strings.Split(userAgent, "Windows ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "Macintosh") {
osInfo["os"] = "Mac OS"
parts := strings.Split(userAgent, "Mac OS X ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "Linux") {
osInfo["os"] = "Linux"
osInfo["version"] = "Unknown"
} else if strings.Contains(userAgent, "Android") {
osInfo["os"] = "Android"
parts := strings.Split(userAgent, "Android ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "iPhone") || strings.Contains(userAgent, "iPad") || strings.Contains(userAgent, "iPod") {
osInfo["os"] = "iOS"
parts := strings.Split(userAgent, "OS ")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
osInfo["version"] = version
}
} else {
osInfo["os"] = "Unknown"
osInfo["version"] = "Unknown"
}
return browserInfo, osInfo
}

View File

@ -15,6 +15,7 @@ func DELETE(w http.ResponseWriter, r *http.Request) {
file, err := app.Server.Database.GetFile(fileID) file, err := app.Server.Database.GetFile(fileID)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -26,12 +27,14 @@ func DELETE(w http.ResponseWriter, r *http.Request) {
err = app.Server.Database.DeleteFile(fileID) err = app.Server.Database.DeleteFile(fileID)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
err = app.Server.Storage.Delete(r.Context(), fmt.Sprintf("%s/%s", file.OwnerID.String(), file.ID.String())) err = app.Server.Storage.Delete(r.Context(), fmt.Sprintf("%s/%s", file.OwnerID.String(), file.ID.String()))
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }

View File

@ -15,7 +15,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
fileID := r.PathValue("id") fileID := r.PathValue("id")
file, err := app.Server.Database.GetFile(fileID) file, err := app.Server.Database.GetFile(fileID)
if err != nil { if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
@ -31,17 +31,6 @@ func GET(w http.ResponseWriter, r *http.Request) {
} }
} }
//uploadDir := "uploads"
//currentDir, _ := os.Getwd()
//basePath := filepath.Join(currentDir, uploadDir)
//saveFolder := filepath.Join(basePath, file.OwnerID.String(), file.ID.String())
//
//if filepath.Dir(saveFolder) != filepath.Join(basePath, file.OwnerID.String()) {
// http.Error(w, "Invalid Path", http.StatusInternalServerError)
// app.Server.Logger.Error("invalid path")
// return
//}
rangeHeader := r.Header.Get("Range") rangeHeader := r.Header.Get("Range")
if rangeHeader != "" { if rangeHeader != "" {
rangeParts := strings.Split(strings.TrimPrefix(rangeHeader, "bytes="), "-") rangeParts := strings.Split(strings.TrimPrefix(rangeHeader, "bytes="), "-")
@ -94,7 +83,7 @@ func sendFileChunk(w http.ResponseWriter, file *models.File, start, end int64) {
chunkKey := fmt.Sprintf("%s/%s/chunk_%d", file.OwnerID.String(), file.ID.String(), i) chunkKey := fmt.Sprintf("%s/%s/chunk_%d", file.OwnerID.String(), file.ID.String(), i)
chunkData, err := app.Server.Storage.Get(context.TODO(), chunkKey) chunkData, err := app.Server.Storage.Get(context.TODO(), chunkKey)
if err != nil { if err != nil {
http.Error(w, fmt.Sprintf("Error retrieving chunk: %v", err), http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
@ -112,7 +101,7 @@ func sendFileChunk(w http.ResponseWriter, file *models.File, start, end int64) {
_, err = w.Write(dataToSend) _, err = w.Write(dataToSend)
if err != nil { if err != nil {
http.Error(w, fmt.Sprintf("Error writing chunk: %v", err), http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
@ -120,7 +109,6 @@ func sendFileChunk(w http.ResponseWriter, file *models.File, start, end int64) {
if i == int64(file.TotalChunk)-1 { if i == int64(file.TotalChunk)-1 {
err := app.Server.Database.IncrementDownloadCount(file.ID.String()) err := app.Server.Database.IncrementDownloadCount(file.ID.String())
if err != nil { if err != nil {
http.Error(w, fmt.Sprintf("Error updating download count: %v", err), http.StatusInternalServerError)
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }

View File

@ -15,8 +15,8 @@ func GET(w http.ResponseWriter, r *http.Request) {
userSession := r.Context().Value("user").(types.User) userSession := r.Context().Value("user").(types.User)
files, err := app.Server.Database.GetFiles(userSession.UserID.String(), "", types.All) files, err := app.Server.Database.GetFiles(userSession.UserID.String(), "", types.All)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
var filesData []types.FileData var filesData []types.FileData
@ -46,13 +46,14 @@ func GET(w http.ResponseWriter, r *http.Request) {
allowance, err := app.Server.Database.GetAllowance(userSession.UserID) allowance, err := app.Server.Database.GetAllowance(userSession.UserID)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
usage, err := app.Server.Service.GetUserStorageUsage(userSession.UserID.String()) usage, err := app.Server.Service.GetUserStorageUsage(userSession.UserID.String())
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -71,8 +72,8 @@ func GET(w http.ResponseWriter, r *http.Request) {
err = component.Render(r.Context(), w) err = component.Render(r.Context(), w)
if err != nil { if err != nil {
fmt.Println(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
} }

View File

@ -26,8 +26,8 @@ func GET(w http.ResponseWriter, r *http.Request) {
files, err := app.Server.Database.GetFiles(userSession.UserID.String(), query, fileStatus) files, err := app.Server.Database.GetFiles(userSession.UserID.String(), query, fileStatus)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -38,8 +38,8 @@ func GET(w http.ResponseWriter, r *http.Request) {
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix) existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -61,10 +61,12 @@ func GET(w http.ResponseWriter, r *http.Request) {
err := component.Render(r.Context(), w) err := component.Render(r.Context(), w)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
return return
} }
w.WriteHeader(http.StatusForbidden) w.WriteHeader(http.StatusForbidden)
return
} }

View File

@ -18,6 +18,7 @@ func PATCH(w http.ResponseWriter, r *http.Request) {
file, err := app.Server.Database.GetFile(fileID) file, err := app.Server.Database.GetFile(fileID)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -34,6 +35,7 @@ func PATCH(w http.ResponseWriter, r *http.Request) {
newFile, err := app.Server.Database.RenameFile(fileID, newName) newFile, err := app.Server.Database.RenameFile(fileID, newName)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -41,8 +43,8 @@ func PATCH(w http.ResponseWriter, r *http.Request) {
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix) existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -62,8 +64,8 @@ func PATCH(w http.ResponseWriter, r *http.Request) {
err = component.Render(r.Context(), w) err = component.Render(r.Context(), w)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
fileView.JustFile(fileData) return
w.WriteHeader(http.StatusOK)
} }

View File

@ -12,6 +12,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
fileID := r.PathValue("id") fileID := r.PathValue("id")
if err := r.ParseMultipartForm(32 << 20); err != nil { if err := r.ParseMultipartForm(32 << 20); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -25,28 +26,30 @@ func POST(w http.ResponseWriter, r *http.Request) {
rawIndex := r.FormValue("index") rawIndex := r.FormValue("index")
index, err := strconv.Atoi(rawIndex) index, err := strconv.Atoi(rawIndex)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
fileByte, _, err := r.FormFile("chunk") fileByte, _, err := r.FormFile("chunk")
if err != nil { if err != nil {
app.Server.Logger.Error("error getting upload info: " + err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error("error getting upload info: " + err.Error())
return return
} }
defer fileByte.Close() defer fileByte.Close()
buffer, err := io.ReadAll(fileByte) buffer, err := io.ReadAll(fileByte)
if err != nil { if err != nil {
app.Server.Logger.Error("error copying byte to file dst: " + err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error("error copying byte to file dst: " + err.Error())
return return
} }
err = app.Server.Storage.Add(r.Context(), fmt.Sprintf("%s/%s/chunk_%d", file.OwnerID.String(), file.ID.String(), index), buffer) err = app.Server.Storage.Add(r.Context(), fmt.Sprintf("%s/%s/chunk_%d", file.OwnerID.String(), file.ID.String(), index), buffer)
if err != nil { if err != nil {
app.Server.Logger.Error("error copying byte to file dst: " + err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error("error copying byte to file dst: " + err.Error())
return return
} }

View File

@ -36,8 +36,8 @@ func PUT(w http.ResponseWriter, r *http.Request) {
existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix) existingChunks, err := app.Server.Storage.ListObjects(r.Context(), prefix)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -55,6 +55,7 @@ func PUT(w http.ResponseWriter, r *http.Request) {
err = component.Render(r.Context(), w) err = component.Render(r.Context(), w)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
} }

View File

@ -12,7 +12,6 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/redis/go-redis/v9" "github.com/redis/go-redis/v9"
"net/http" "net/http"
"sync"
"time" "time"
"github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types"
@ -24,8 +23,6 @@ import (
type ForgotPassword struct { type ForgotPassword struct {
User *models.User User *models.User
Code string Code string
mu sync.Mutex
CreateTime time.Time
} }
func GET(w http.ResponseWriter, r *http.Request) { func GET(w http.ResponseWriter, r *http.Request) {
@ -39,6 +36,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
return
} }
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
@ -52,6 +50,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
emailForm := r.Form.Get("email") emailForm := r.Form.Get("email")
user, err := app.Server.Service.GetUser(r.Context(), emailForm) user, err := app.Server.Service.GetUser(r.Context(), emailForm)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
component := forgotPasswordView.Main("Filekeeper - Forgot Password Page", types.Message{ component := forgotPasswordView.Main("Filekeeper - Forgot Password Page", types.Message{
Code: 0, Code: 0,
@ -65,6 +64,10 @@ func POST(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
userData := &models.User{ userData := &models.User{
UserID: uuid.UUID{}, UserID: uuid.UUID{},
@ -101,7 +104,6 @@ func verifyForgot(user *models.User) error {
userData = &ForgotPassword{ userData = &ForgotPassword{
User: user, User: user,
Code: code, Code: code,
CreateTime: time.Now(),
} }
newForgotUser, err := json.Marshal(userData) newForgotUser, err := json.Marshal(userData)

View File

@ -30,6 +30,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
return return
} }
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -43,6 +44,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
return
} }
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
@ -58,6 +60,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
err = json.Unmarshal([]byte(data), &userData) err = json.Unmarshal([]byte(data), &userData)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -98,12 +101,33 @@ func POST(w http.ResponseWriter, r *http.Request) {
return return
} }
app.Server.Cache.DeleteCache(r.Context(), "ForgotPasswordCode:"+userData.User.Email) err = app.Server.Cache.DeleteCache(r.Context(), "ForgotPasswordCode:"+userData.User.Email)
app.Server.Cache.DeleteCache(r.Context(), "ForgotPassword:"+code) if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
session.RemoveAllSessions(userData.User.Email) err = app.Server.Cache.DeleteCache(r.Context(), "ForgotPassword:"+code)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
app.Server.Service.DeleteUser(userData.User.Email) err = session.RemoveAllSessions(userData.User.Email)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
err = app.Server.Service.DeleteUser(userData.User.Email)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
component := forgotPasswordView.ChangeSuccess("Filekeeper - Forgot Password Page") component := forgotPasswordView.ChangeSuccess("Filekeeper - Forgot Password Page")
err = component.Render(r.Context(), w) err = component.Render(r.Context(), w)

View File

@ -16,4 +16,5 @@ func GET(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
return
} }

View File

@ -1,7 +1,6 @@
package logoutHandler package logoutHandler
import ( import (
"errors"
"github.com/fossyy/filekeeper/app" "github.com/fossyy/filekeeper/app"
"github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types"
"net/http" "net/http"
@ -14,25 +13,23 @@ func GET(w http.ResponseWriter, r *http.Request) {
userSession := r.Context().Value("user").(types.User) userSession := r.Context().Value("user").(types.User)
cookie, err := r.Cookie("Session") cookie, err := r.Cookie("Session")
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
storeSession := session.Get(cookie.Value) storeSession := session.Get(cookie.Value)
if err != nil {
if errors.Is(err, &session.SessionNotFoundError{}) {
storeSession.Destroy(w)
}
w.WriteHeader(http.StatusInternalServerError)
return
}
err = storeSession.Delete() err = storeSession.Delete()
if err != nil { if err != nil {
app.Server.Logger.Error(err) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
err = session.RemoveSessionInfo(userSession.Email, cookie.Value) err = session.RemoveSessionInfo(userSession.Email, cookie.Value)
if err != nil { if err != nil {
app.Server.Logger.Error(err) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }

View File

@ -9,15 +9,10 @@ import (
"github.com/fossyy/filekeeper/utils" "github.com/fossyy/filekeeper/utils"
"github.com/fossyy/filekeeper/view/client/signin" "github.com/fossyy/filekeeper/view/client/signin"
"net/http" "net/http"
"strings"
) )
var errorMessages = make(map[string]string) var errorMessages = make(map[string]string)
func init() {
}
func init() { func init() {
errorMessages = map[string]string{ errorMessages = map[string]string{
"redirect_uri_mismatch": "The redirect URI provided does not match the one registered with our service. Please contact the administrator for assistance.", "redirect_uri_mismatch": "The redirect URI provided does not match the one registered with our service. Please contact the administrator for assistance.",
@ -36,7 +31,7 @@ func init() {
"login_required": "You need to log in again to proceed. Please try logging in again.", "login_required": "You need to log in again to proceed. Please try logging in again.",
"account_selection_required": "Please select an account to proceed with the request.", "account_selection_required": "Please select an account to proceed with the request.",
"consent_required": "Consent is required to proceed. Please provide consent to continue.", "consent_required": "Consent is required to proceed. Please provide consent to continue.",
"csrf_token_error": "The CSRF token is missing or invalid. Please refresh the page and try again.", "csrf_token_error": "The CSRF token is missing or invalid. Please try again.",
"suspicious_session": "We've detected unusual activity on your account. Please log in again to confirm it's you.", "suspicious_session": "We've detected unusual activity on your account. Please log in again to confirm it's you.",
} }
} }
@ -49,7 +44,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
message = "Unknown error occurred. Please contact support at bagas@fossy.my.id for assistance." message = "Unknown error occurred. Please contact support at bagas@fossy.my.id for assistance."
} }
component = signinView.Main("Sign in Page", types.Message{ component = signinView.Main("Filekeeper - Sign in Page", types.Message{
Code: 0, Code: 0,
Message: message, Message: message,
}) })
@ -66,6 +61,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
return
} }
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
@ -95,7 +91,6 @@ func POST(w http.ResponseWriter, r *http.Request) {
if email == userData.Email && utils.CheckPasswordHash(password, userData.Password) { if email == userData.Email && utils.CheckPasswordHash(password, userData.Password) {
if userData.Totp != "" { if userData.Totp != "" {
storeSession, err := session.Create(types.User{ storeSession, err := session.Create(types.User{
UserID: userData.UserID, UserID: userData.UserID,
Email: email, Email: email,
@ -105,6 +100,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
}) })
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
storeSession.Save(w) storeSession.Save(w)
@ -120,10 +116,11 @@ func POST(w http.ResponseWriter, r *http.Request) {
}) })
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
userAgent := r.Header.Get("User-Agent") userAgent := r.Header.Get("User-Agent")
browserInfo, osInfo := ParseUserAgent(userAgent) browserInfo, osInfo := utils.ParseUserAgent(userAgent)
sessionInfo := session.SessionInfo{ sessionInfo := session.SessionInfo{
SessionID: storeSession.ID, SessionID: storeSession.ID,
@ -136,7 +133,12 @@ func POST(w http.ResponseWriter, r *http.Request) {
} }
storeSession.Save(w) storeSession.Save(w)
session.AddSessionInfo(email, &sessionInfo) err = session.AddSessionInfo(email, &sessionInfo)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
cookie, err := r.Cookie("redirect") cookie, err := r.Cookie("redirect")
if errors.Is(err, http.ErrNoCookie) { if errors.Is(err, http.ErrNoCookie) {
@ -160,65 +162,5 @@ func POST(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
} return
func ParseUserAgent(userAgent string) (map[string]string, map[string]string) {
browserInfo := make(map[string]string)
osInfo := make(map[string]string)
if strings.Contains(userAgent, "Firefox") {
browserInfo["browser"] = "Firefox"
parts := strings.Split(userAgent, "Firefox/")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
browserInfo["version"] = version
}
} else if strings.Contains(userAgent, "Chrome") {
browserInfo["browser"] = "Chrome"
parts := strings.Split(userAgent, "Chrome/")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
browserInfo["version"] = version
}
} else {
browserInfo["browser"] = "Unknown"
browserInfo["version"] = "Unknown"
}
if strings.Contains(userAgent, "Windows") {
osInfo["os"] = "Windows"
parts := strings.Split(userAgent, "Windows ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "Macintosh") {
osInfo["os"] = "Mac OS"
parts := strings.Split(userAgent, "Mac OS X ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "Linux") {
osInfo["os"] = "Linux"
osInfo["version"] = "Unknown"
} else if strings.Contains(userAgent, "Android") {
osInfo["os"] = "Android"
parts := strings.Split(userAgent, "Android ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "iPhone") || strings.Contains(userAgent, "iPad") || strings.Contains(userAgent, "iPod") {
osInfo["os"] = "iOS"
parts := strings.Split(userAgent, "OS ")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
osInfo["version"] = version
}
} else {
osInfo["os"] = "Unknown"
osInfo["version"] = "Unknown"
}
return browserInfo, osInfo
} }

View File

@ -22,7 +22,6 @@ import (
type UnverifiedUser struct { type UnverifiedUser struct {
User *models.User User *models.User
Code string Code string
CreateTime time.Time
} }
func GET(w http.ResponseWriter, r *http.Request) { func GET(w http.ResponseWriter, r *http.Request) {
@ -36,6 +35,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
return
} }
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
@ -125,7 +125,6 @@ func verifyEmail(user *models.User) error {
unverifiedUser := UnverifiedUser{ unverifiedUser := UnverifiedUser{
User: user, User: user,
Code: code, Code: code,
CreateTime: time.Now(),
} }
newUnverifiedUser, err := json.Marshal(unverifiedUser) newUnverifiedUser, err := json.Marshal(unverifiedUser)
if err != nil { if err != nil {

View File

@ -15,7 +15,6 @@ import (
func GET(w http.ResponseWriter, r *http.Request) { func GET(w http.ResponseWriter, r *http.Request) {
code := r.PathValue("code") code := r.PathValue("code")
userDataStr, err := app.Server.Cache.GetCache(context.Background(), "UnverifiedUser:"+code) userDataStr, err := app.Server.Cache.GetCache(context.Background(), "UnverifiedUser:"+code)
if err != nil { if err != nil {
if errors.Is(err, redis.Nil) { if errors.Is(err, redis.Nil) {
@ -53,11 +52,15 @@ func GET(w http.ResponseWriter, r *http.Request) {
err = app.Server.Cache.DeleteCache(context.Background(), "UnverifiedUser:"+code) err = app.Server.Cache.DeleteCache(context.Background(), "UnverifiedUser:"+code)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
} }
err = app.Server.Cache.DeleteCache(context.Background(), "VerificationCode:"+unverifiedUser.User.Email) err = app.Server.Cache.DeleteCache(context.Background(), "VerificationCode:"+unverifiedUser.User.Email)
if err != nil { if err != nil {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
} }
component := signupView.VerifySuccess("Filekeeper - Verify Page") component := signupView.VerifySuccess("Filekeeper - Verify Page")
@ -67,4 +70,5 @@ func GET(w http.ResponseWriter, r *http.Request) {
app.Server.Logger.Error(err.Error()) app.Server.Logger.Error(err.Error())
return return
} }
return
} }

View File

@ -9,19 +9,26 @@ import (
) )
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
r.ParseForm() err := r.ParseForm()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
userSession := r.Context().Value("user").(types.User) userSession := r.Context().Value("user").(types.User)
currentPassword := r.Form.Get("currentPassword") currentPassword := r.Form.Get("currentPassword")
password := r.Form.Get("password") password := r.Form.Get("password")
user, err := app.Server.Service.GetUser(r.Context(), userSession.Email) user, err := app.Server.Service.GetUser(r.Context(), userSession.Email)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
hashPassword, err := utils.HashPassword(password) hashPassword, err := utils.HashPassword(password)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -33,11 +40,23 @@ func POST(w http.ResponseWriter, r *http.Request) {
err = app.Server.Database.UpdateUserPassword(user.Email, hashPassword) err = app.Server.Database.UpdateUserPassword(user.Email, hashPassword)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
session.RemoveAllSessions(userSession.Email) err = session.RemoveAllSessions(userSession.Email)
app.Server.Service.DeleteUser(userSession.Email) if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
err = app.Server.Service.DeleteUser(userSession.Email)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
http.Redirect(w, r, "/signin", http.StatusSeeOther) http.Redirect(w, r, "/signin", http.StatusSeeOther)
return return

View File

@ -1,6 +1,7 @@
package userSessionTerminateHandler package userSessionTerminateHandler
import ( import (
"github.com/fossyy/filekeeper/app"
"github.com/fossyy/filekeeper/session" "github.com/fossyy/filekeeper/session"
"github.com/fossyy/filekeeper/types" "github.com/fossyy/filekeeper/types"
"github.com/fossyy/filekeeper/view/client/user" "github.com/fossyy/filekeeper/view/client/user"
@ -16,11 +17,24 @@ func DELETE(w http.ResponseWriter, r *http.Request) {
return return
} }
otherSession.Delete() err := otherSession.Delete()
session.RemoveSessionInfo(mySession.Email, otherSession.ID) if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
err = session.RemoveSessionInfo(mySession.Email, otherSession.ID)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
sessions, err := session.GetSessions(mySession.Email) sessions, err := session.GetSessions(mySession.Email)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
component := userView.SessionTable(sessions) component := userView.SessionTable(sessions)
@ -30,4 +44,5 @@ func DELETE(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
return return
} }
return
} }

View File

@ -37,8 +37,8 @@ func GET(w http.ResponseWriter, r *http.Request) {
uri := totp.ProvisioningUri(userSession.Email, "filekeeper") uri := totp.ProvisioningUri(userSession.Email, "filekeeper")
base64Str, err := generateQRCode(uri) base64Str, err := generateQRCode(uri)
if err != nil { if err != nil {
fmt.Printf("%v\n", err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -56,6 +56,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
} }
if err := component.Render(r.Context(), w); err != nil { if err := component.Render(r.Context(), w); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
} }
@ -63,6 +64,7 @@ func GET(w http.ResponseWriter, r *http.Request) {
func POST(w http.ResponseWriter, r *http.Request) { func POST(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
@ -74,17 +76,23 @@ func POST(w http.ResponseWriter, r *http.Request) {
base64Str, err := generateQRCode(uri) base64Str, err := generateQRCode(uri)
if err != nil { if err != nil {
fmt.Printf("%v\n", err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
var component templ.Component var component templ.Component
if totp.Verify(code, time.Now().Unix()) { if totp.Verify(code, time.Now().Unix()) {
if err := app.Server.Database.InitializeTotp(userSession.Email, secret); err != nil { if err := app.Server.Database.InitializeTotp(userSession.Email, secret); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return
}
err := app.Server.Service.DeleteUser(userSession.Email)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
app.Server.Service.DeleteUser(userSession.Email)
if r.Header.Get("hx-request") == "true" { if r.Header.Get("hx-request") == "true" {
component = userTotpSetupView.MainContent("Filekeeper - 2FA Setup Page", base64Str, secret, userSession, types.Message{ component = userTotpSetupView.MainContent("Filekeeper - 2FA Setup Page", base64Str, secret, userSession, types.Message{
Code: 1, Code: 1,
@ -99,6 +107,7 @@ func POST(w http.ResponseWriter, r *http.Request) {
if err := component.Render(r.Context(), w); err != nil { if err := component.Render(r.Context(), w); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
return return
@ -116,7 +125,9 @@ func POST(w http.ResponseWriter, r *http.Request) {
} }
if err := component.Render(r.Context(), w); err != nil { if err := component.Render(r.Context(), w); err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
return
} }
} }

View File

@ -55,7 +55,8 @@ func GET(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("upgrade") == "websocket" { if r.Header.Get("upgrade") == "websocket" {
upgrade, err := upgrader.Upgrade(w, r, nil) upgrade, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
panic(err) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
handlerWS(upgrade, userSession) handlerWS(upgrade, userSession)
@ -64,18 +65,21 @@ func GET(w http.ResponseWriter, r *http.Request) {
sessions, err := session.GetSessions(userSession.Email) sessions, err := session.GetSessions(userSession.Email)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
allowance, err := app.Server.Database.GetAllowance(userSession.UserID) allowance, err := app.Server.Database.GetAllowance(userSession.UserID)
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }
usage, err := app.Server.Service.GetUserStorageUsage(userSession.UserID.String()) usage, err := app.Server.Service.GetUserStorageUsage(userSession.UserID.String())
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
app.Server.Logger.Error(err.Error())
return return
} }

View File

@ -59,11 +59,12 @@ func (r *Service) GetUser(ctx context.Context, email string) (*models.User, erro
return &user, nil return &user, nil
} }
func (r *Service) DeleteUser(email string) { func (r *Service) DeleteUser(email string) error {
err := r.cache.DeleteCache(context.Background(), "UserCache:"+email) err := r.cache.DeleteCache(context.Background(), "UserCache:"+email)
if err != nil { if err != nil {
return return err
} }
return nil
} }
func (r *Service) GetUserStorageUsage(ownerID string) (uint64, error) { func (r *Service) GetUserStorageUsage(ownerID string) (uint64, error) {

View File

@ -31,7 +31,6 @@ type SessionInfo struct {
} }
type UserStatus string type UserStatus string
type SessionNotFoundError struct{}
const ( const (
Authorized UserStatus = "authorized" Authorized UserStatus = "authorized"
@ -40,10 +39,6 @@ const (
Suspicious UserStatus = "suspicious" Suspicious UserStatus = "suspicious"
) )
func (e *SessionNotFoundError) Error() string {
return "session not found"
}
func Get(id string) *Session { func Get(id string) *Session {
return &Session{ID: id} return &Session{ID: id}
} }

View File

@ -88,7 +88,7 @@ type CachingServer interface {
type Services interface { type Services interface {
GetUser(ctx context.Context, email string) (*models.User, error) GetUser(ctx context.Context, email string) (*models.User, error)
DeleteUser(email string) DeleteUser(email string) error
GetFile(id string) (*models.File, error) GetFile(id string) (*models.File, error)
GetUserFile(name, ownerID string) (*FileWithDetail, error) GetUserFile(name, ownerID string) (*FileWithDetail, error)
GetUserStorageUsage(ownerID string) (uint64, error) GetUserStorageUsage(ownerID string) (uint64, error)

View File

@ -145,12 +145,63 @@ func GenerateCSRFToken() (string, error) {
return csrfToken, nil return csrfToken, nil
} }
func SanitizeFilename(filename string) string { func ParseUserAgent(userAgent string) (map[string]string, map[string]string) {
invalidChars := []string{"\\", "/", ":", "*", "?", "\"", "<", ">", "|"} browserInfo := make(map[string]string)
osInfo := make(map[string]string)
for _, char := range invalidChars { if strings.Contains(userAgent, "Firefox") {
filename = strings.ReplaceAll(filename, char, "_") browserInfo["browser"] = "Firefox"
parts := strings.Split(userAgent, "Firefox/")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
browserInfo["version"] = version
}
} else if strings.Contains(userAgent, "Chrome") {
browserInfo["browser"] = "Chrome"
parts := strings.Split(userAgent, "Chrome/")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
browserInfo["version"] = version
}
} else {
browserInfo["browser"] = "Unknown"
browserInfo["version"] = "Unknown"
} }
return filename if strings.Contains(userAgent, "Windows") {
osInfo["os"] = "Windows"
parts := strings.Split(userAgent, "Windows ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "Macintosh") {
osInfo["os"] = "Mac OS"
parts := strings.Split(userAgent, "Mac OS X ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "Linux") {
osInfo["os"] = "Linux"
osInfo["version"] = "Unknown"
} else if strings.Contains(userAgent, "Android") {
osInfo["os"] = "Android"
parts := strings.Split(userAgent, "Android ")
if len(parts) > 1 {
version := strings.Split(parts[1], ";")[0]
osInfo["version"] = version
}
} else if strings.Contains(userAgent, "iPhone") || strings.Contains(userAgent, "iPad") || strings.Contains(userAgent, "iPod") {
osInfo["os"] = "iOS"
parts := strings.Split(userAgent, "OS ")
if len(parts) > 1 {
version := strings.Split(parts[1], " ")[0]
osInfo["version"] = version
}
} else {
osInfo["os"] = "Unknown"
osInfo["version"] = "Unknown"
}
return browserInfo, osInfo
} }