From 0ebc30814b1d745e2e7ce06c9ad5cd4f92d5654e Mon Sep 17 00:00:00 2001 From: Wim Brand Date: Wed, 10 Mar 2021 20:13:32 +0100 Subject: [PATCH] Support embedded viewer --- go.mod | 7 ++++-- res/include/script/file_viewer/Viewer.js | 18 ++++++++++++++ res/include/style/viewer.css | 3 +++ res/template/file_viewer.html | 1 + webcontroller/admin_panel.go | 4 +-- webcontroller/file_viewer.go | 31 ++++++++++++++++-------- webcontroller/misc.go | 2 +- webcontroller/opengraph.go | 6 ++--- webcontroller/subscription_activate.go | 8 +++--- webcontroller/templates.go | 10 +++----- webcontroller/user_account.go | 12 +++++---- webcontroller/user_export.go | 4 +-- webcontroller/user_settings.go | 12 ++++----- webcontroller/web_controller.go | 8 +++--- 14 files changed, 81 insertions(+), 45 deletions(-) diff --git a/go.mod b/go.mod index 2279371..fb47331 100644 --- a/go.mod +++ b/go.mod @@ -1,18 +1,21 @@ module fornaxian.tech/pixeldrain_web -go 1.14 +go 1.16 replace ( fornaxian.tech/pd_database => ../pd_database + fornaxian.tech/pixeldrain_api_client => ../pixeldrain_api_client fornaxian.tech/pixeldrain_server/api => ../pixeldrain_server/api fornaxian.tech/pixeldrain_server/database => ../pixeldrain_server/database fornaxian.tech/pixeldrain_server/pixelstore => ../pixeldrain_server/pixelstore fornaxian.tech/pixeldrain_server/util => ../pixeldrain_server/util + github.com/gocql/gocql => github.com/scylladb/gocql v1.5.0 ) require ( - fornaxian.tech/pixeldrain_server/api v0.0.0-00010101000000-000000000000 + fornaxian.tech/pixeldrain_api_client v0.0.0-00010101000000-000000000000 fornaxian.tech/pixeldrain_server/util v0.0.0-00010101000000-000000000000 + github.com/BurntSushi/toml v0.3.1 // indirect github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70 github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3 github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145 diff --git a/res/include/script/file_viewer/Viewer.js b/res/include/script/file_viewer/Viewer.js index 8f4ae74..0f398f2 100644 --- a/res/include/script/file_viewer/Viewer.js +++ b/res/include/script/file_viewer/Viewer.js @@ -25,6 +25,24 @@ function Viewer(type, viewToken, data) { this.toolbar.toggle() } + if (embeddedViewer) { + // Remove padding from the headerbar + document.getElementById("file_viewer_headerbar").classList += " file_viewer_headerbar_embedded" + + // Hide toolbar by default + if (this.toolbar.visible) { + this.toolbar.toggle() + } + + // Alter home button to open in a new tab + document.getElementById("button_home").setAttribute("target", "_blank") + + // Remove sponsor bar if ads are disabled + if (!data.show_ads) { + document.getElementById("sponsors").remove() + } + } + if (type === "file") { this.isFile = true this.title = data.name diff --git a/res/include/style/viewer.css b/res/include/style/viewer.css index a59cf97..3c01419 100644 --- a/res/include/style/viewer.css +++ b/res/include/style/viewer.css @@ -25,6 +25,9 @@ z-index: 10; box-shadow: none; } +.file_viewer > .file_viewer_headerbar_embedded { + padding: 2px; +} /* Headerbar components */ .file_viewer > .file_viewer_headerbar > * { diff --git a/res/template/file_viewer.html b/res/template/file_viewer.html index e7122cb..c6ffd56 100644 --- a/res/template/file_viewer.html +++ b/res/template/file_viewer.html @@ -277,6 +277,7 @@ 'use strict'; let apiEndpoint = '{{.APIEndpoint}}'; let captchaKey = '{{.Other.CaptchaKey}}'; + let embeddedViewer = {{.Other.Embedded}}; let highlightColor = '#{{.Style.HighlightColor.RGB}}'; {{template `util.js`}} {{template `drawGraph.js`}} diff --git a/webcontroller/admin_panel.go b/webcontroller/admin_panel.go index e08e79d..7d79166 100644 --- a/webcontroller/admin_panel.go +++ b/webcontroller/admin_panel.go @@ -5,7 +5,7 @@ import ( "html/template" "net/http" - "fornaxian.tech/pixeldrain_server/api/restapi/apiclient" + "fornaxian.tech/pixeldrain_api_client/pixelapi" "github.com/Fornaxian/log" ) @@ -65,7 +65,7 @@ func (wc *WebController) adminGlobalsForm(td *TemplateData, r *http.Request) (f // Value changed, try to update global setting if err = td.PixelAPI.AdminSetGlobals(v.Name, v.EnteredValue); err != nil { - if apiErr, ok := err.(apiclient.Error); ok { + if apiErr, ok := err.(pixelapi.Error); ok { f.SubmitMessages = append(f.SubmitMessages, template.HTML(apiErr.Message)) } else { log.Error("%s", err) diff --git a/webcontroller/file_viewer.go b/webcontroller/file_viewer.go index 5e1aa50..3f227ba 100644 --- a/webcontroller/file_viewer.go +++ b/webcontroller/file_viewer.go @@ -10,8 +10,7 @@ import ( "strings" "time" - "fornaxian.tech/pixeldrain_server/api/restapi/apiclient" - "fornaxian.tech/pixeldrain_server/api/restapi/apitype" + "fornaxian.tech/pixeldrain_api_client/pixelapi" "github.com/Fornaxian/log" pdmimetype "github.com/Fornaxian/pd_mime_type" "github.com/julienschmidt/httprouter" @@ -72,6 +71,7 @@ type viewerData struct { AdType int FileAdsEnabled bool UserAdsEnabled bool + Embedded bool APIResponse interface{} } @@ -87,17 +87,17 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request, templateData := wc.newTemplateData(w, r) - var files []apitype.ListFile + var files []pixelapi.ListFile for _, id := range ids { inf, err := templateData.PixelAPI.GetFileInfo(id) if err != nil { - if apiclient.ErrIsServerError(err) { + if pixelapi.ErrIsServerError(err) { wc.templates.Get().ExecuteTemplate(w, "500", templateData) return } continue } - files = append(files, apitype.ListFile{FileInfo: inf}) + files = append(files, pixelapi.ListFile{FileInfo: inf}) } if len(files) == 0 { @@ -115,10 +115,11 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request, FileAdsEnabled: files[0].ShowAds, UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay), } + if len(ids) > 1 { templateData.Title = fmt.Sprintf("%d files on pixeldrain", len(files)) vd.Type = "list" - vd.APIResponse = apitype.ListInfo{ + vd.APIResponse = pixelapi.ListInfo{ Success: true, Title: "Multiple files", DateCreated: time.Now(), @@ -129,6 +130,11 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request, vd.Type = "file" vd.APIResponse = files[0].FileInfo } + + if _, ok := r.URL.Query()["embed"]; ok { + vd.Embedded = true + } + templateData.Other = vd var templateName = "file_viewer" @@ -184,9 +190,9 @@ func (wc *WebController) serveFileViewerDemo(w http.ResponseWriter, r *http.Requ // ServeListViewer controller for GET /l/:id func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) { var templateData = wc.newTemplateData(w, r) - var list, err = templateData.PixelAPI.GetList(p.ByName("id")) + var list, err = templateData.PixelAPI.GetListID(p.ByName("id")) if err != nil { - if err, ok := err.(apiclient.Error); ok && err.Status == http.StatusNotFound { + if err, ok := err.(pixelapi.Error); ok && err.Status == http.StatusNotFound { w.WriteHeader(http.StatusNotFound) wc.templates.Get().ExecuteTemplate(w, "list_not_found", templateData) } else { @@ -204,7 +210,7 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, templateData.Title = fmt.Sprintf("%s ~ pixeldrain", list.Title) templateData.OGData = wc.metadataFromList(list) - templateData.Other = viewerData{ + var vd = viewerData{ Type: "list", CaptchaKey: wc.captchaSiteKey, ViewToken: wc.viewTokenOrBust(), @@ -214,6 +220,11 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, APIResponse: list, } + if _, ok := r.URL.Query()["embed"]; ok { + vd.Embedded = true + } + templateData.Other = vd + var templateName = "file_viewer" if browserCompat(r.UserAgent()) { templateName = "file_viewer_compat" @@ -307,7 +318,7 @@ func (wc *WebController) serveSkynetViewer(w http.ResponseWriter, r *http.Reques templateData.Other = viewerData{ Type: "skylink", AdType: adType(), - APIResponse: apitype.FileInfo{ + APIResponse: pixelapi.FileInfo{ Success: true, ID: p.ByName("id"), Name: name, diff --git a/webcontroller/misc.go b/webcontroller/misc.go index 9bf4153..dc35fdc 100644 --- a/webcontroller/misc.go +++ b/webcontroller/misc.go @@ -17,7 +17,7 @@ func (wc *WebController) serveShareXConfig(w http.ResponseWriter, r *http.Reques w.Header().Add("Content-Disposition", "attachment; filename=pixeldrain.com.sxcu") if templateData.Authenticated { - sess, err := templateData.PixelAPI.UserSessionCreate() + sess, err := templateData.PixelAPI.PostUserSession() if err != nil { log.Error("Failed to create user session: %s", err) wc.templates.Get().ExecuteTemplate(w, "500", templateData) diff --git a/webcontroller/opengraph.go b/webcontroller/opengraph.go index 42f0e7f..2d2afe8 100644 --- a/webcontroller/opengraph.go +++ b/webcontroller/opengraph.go @@ -3,7 +3,7 @@ package webcontroller import ( "strings" - "fornaxian.tech/pixeldrain_server/api/restapi/apitype" + "fornaxian.tech/pixeldrain_api_client/pixelapi" ) type ogData struct { @@ -21,7 +21,7 @@ func (og *ogData) addOG(k, v string) { og.OGRules = append(og.OGRules, ogPr func (og *ogData) addTwitter(k, v string) { og.TwitterRules = append(og.TwitterRules, ogProp{k, v}) } func (og *ogData) addLink(k, v string) { og.LinkRules = append(og.LinkRules, ogProp{k, v}) } -func (wc *WebController) metadataFromFile(f apitype.FileInfo) (og ogData) { +func (wc *WebController) metadataFromFile(f pixelapi.FileInfo) (og ogData) { og.addOG("og:title", f.Name) og.addOG("og:site_name", "pixeldrain") og.addOG("og:description", "This file has been shared with you on pixeldrain") @@ -67,7 +67,7 @@ func (wc *WebController) metadataFromFile(f apitype.FileInfo) (og ogData) { } return og } -func (wc *WebController) metadataFromList(l apitype.ListInfo) (og ogData) { +func (wc *WebController) metadataFromList(l pixelapi.ListInfo) (og ogData) { og.addOG("og:type", "website") og.addOG("og:title", l.Title) og.addOG("og:site_name", "pixeldrain") diff --git a/webcontroller/subscription_activate.go b/webcontroller/subscription_activate.go index 99b6779..49801ba 100644 --- a/webcontroller/subscription_activate.go +++ b/webcontroller/subscription_activate.go @@ -18,7 +18,7 @@ func (wc *WebController) patreonLinkForm(td *TemplateData, r *http.Request) (f F return f } - patron, err := td.PixelAPI.PatreonByID(r.FormValue("key")) + patron, err := td.PixelAPI.GetPatreonByID(r.FormValue("key")) if err != nil && err.Error() == "not_found" { f.Submitted = true f.SubmitMessages = []template.HTML{"Patron ID not found"} @@ -76,7 +76,7 @@ func (wc *WebController) patreonLinkForm(td *TemplateData, r *http.Request) (f F }} if f.ReadInput(r) { - if err := td.PixelAPI.PatreonLink(r.FormValue("key")); err != nil { + if err := td.PixelAPI.PostPatreonLink(r.FormValue("key")); err != nil { formAPIError(err, &f) } else { // Request was a success @@ -105,7 +105,7 @@ func (wc *WebController) knoxfsLinkForm(td *TemplateData, r *http.Request) (f Fo return f } - sub, err := td.PixelAPI.SubscriptionByID(r.FormValue("key")) + sub, err := td.PixelAPI.GetSubscriptionID(r.FormValue("key")) if err != nil && err.Error() == "not_found" { f.Submitted = true f.SubmitMessages = []template.HTML{"Subscription ID not found"} @@ -163,7 +163,7 @@ func (wc *WebController) knoxfsLinkForm(td *TemplateData, r *http.Request) (f Fo } if f.ReadInput(r) { - if err := td.PixelAPI.SubscriptionLink(r.FormValue("key")); err != nil { + if err := td.PixelAPI.PostSubscriptionLink(r.FormValue("key")); err != nil { formAPIError(err, &f) } else { // Request was a success diff --git a/webcontroller/templates.go b/webcontroller/templates.go index 5d4796b..ea06744 100644 --- a/webcontroller/templates.go +++ b/webcontroller/templates.go @@ -14,8 +14,7 @@ import ( "strings" "time" - "fornaxian.tech/pixeldrain_server/api/restapi/apiclient" - "fornaxian.tech/pixeldrain_server/api/restapi/apitype" + "fornaxian.tech/pixeldrain_api_client/pixelapi" "fornaxian.tech/pixeldrain_server/util" "github.com/Fornaxian/log" ) @@ -24,12 +23,12 @@ import ( // the field Other you can pass your own template-specific variables. type TemplateData struct { Authenticated bool - User apitype.UserInfo + User pixelapi.UserInfo UserAgent string Style pixeldrainStyleSheet UserStyle template.CSS APIEndpoint template.URL - PixelAPI apiclient.PixelAPI + PixelAPI pixelapi.PixelAPI Hostname template.HTML // Only used on file viewer page @@ -63,8 +62,7 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) // and stuff like that if key, err := wc.getAPIKey(r); err == nil { t.PixelAPI = t.PixelAPI.Login(key) // Use the user's API key for all requests - t.User, err = t.PixelAPI.UserInfo() - if err != nil { + if t.User, err = t.PixelAPI.GetUser(); err != nil { // This session key doesn't work, or the backend is down, user // cannot be authenticated log.Debug("Session check for key '%s' failed: %s", key, err) diff --git a/webcontroller/user_account.go b/webcontroller/user_account.go index 01e1967..0799ee9 100644 --- a/webcontroller/user_account.go +++ b/webcontroller/user_account.go @@ -16,7 +16,7 @@ func (wc *WebController) serveLogout( ) { if key, err := wc.getAPIKey(r); err == nil { var api = wc.api.Login(key) - if err = api.UserSessionDestroy(key); err != nil { + if err = api.DeleteUserSession(key); err != nil { log.Warn("logout failed for session '%s': %s", key, err) } } @@ -28,7 +28,7 @@ func (wc *WebController) registerForm(td *TemplateData, r *http.Request) (f Form var err error // This only runs on the first request if wc.captchaSiteKey == "" { - capt, err := td.PixelAPI.GetRecaptcha() + capt, err := td.PixelAPI.GetMiscRecaptcha() if err != nil { log.Error("Error getting recaptcha key: %s", err) f.SubmitMessages = []template.HTML{ @@ -148,10 +148,11 @@ func (wc *WebController) loginForm(td *TemplateData, r *http.Request) (f Form) { } if f.ReadInput(r) { - if session, err := td.PixelAPI.UserLogin( + if session, err := td.PixelAPI.PostUserLogin( f.FieldVal("username"), f.FieldVal("password"), ); err != nil { + log.Error("Error while logging in: %s", err) formAPIError(err, &f) } else { // Request was a success @@ -172,6 +173,7 @@ func (wc *WebController) loginForm(td *TemplateData, r *http.Request) (f Form) { // content also gets the cookie. We're not trying to track the // user around the web so we use lax SameSite: http.SameSiteLaxMode, + Secure: true, } f.Extra.RedirectTo = "/user" } @@ -206,7 +208,7 @@ func (wc *WebController) passwordResetForm(td *TemplateData, r *http.Request) (f } if f.ReadInput(r) { - if err := td.PixelAPI.UserPasswordReset( + if err := td.PixelAPI.PutUserPasswordReset( f.FieldVal("email"), f.FieldVal("recaptcha_response"), ); err != nil { @@ -258,7 +260,7 @@ func (wc *WebController) passwordResetConfirmForm(td *TemplateData, r *http.Requ return f } - if err := td.PixelAPI.UserPasswordResetConfirm(resetKey, f.FieldVal("new_password")); err != nil { + if err := td.PixelAPI.PutUserPasswordResetConfirm(resetKey, f.FieldVal("new_password")); err != nil { formAPIError(err, &f) } else { f.SubmitSuccess = true diff --git a/webcontroller/user_export.go b/webcontroller/user_export.go index ecb3da7..77dc118 100644 --- a/webcontroller/user_export.go +++ b/webcontroller/user_export.go @@ -46,7 +46,7 @@ func (wc *WebController) serveUserExportFiles( return } - files, err := td.PixelAPI.UserFiles() + files, err := td.PixelAPI.GetUserFiles() if err != nil { log.Error("Failed to get user files: %s", err) return @@ -84,7 +84,7 @@ func (wc *WebController) serveUserExportLists( return } - lists, err := td.PixelAPI.UserLists() + lists, err := td.PixelAPI.GetUserLists() if err != nil { log.Error("Failed to get user lists: %s", err) return diff --git a/webcontroller/user_settings.go b/webcontroller/user_settings.go index be872fc..49b6537 100644 --- a/webcontroller/user_settings.go +++ b/webcontroller/user_settings.go @@ -6,7 +6,7 @@ import ( "html/template" "net/http" - "fornaxian.tech/pixeldrain_server/api/restapi/apiclient" + "fornaxian.tech/pixeldrain_api_client/pixelapi" "github.com/Fornaxian/log" "github.com/julienschmidt/httprouter" ) @@ -24,7 +24,7 @@ func formAPIError(err error, f *Form) { return name } - if err, ok := err.(apiclient.Error); ok { + if err, ok := err.(pixelapi.Error); ok { if err.StatusCode == "multiple_errors" { for _, err := range err.Errors { // Modify the message to make it more user-friendly @@ -116,7 +116,7 @@ func (wc *WebController) passwordForm(td *TemplateData, r *http.Request) (f Form // Passwords match, send the request and fill in the response in the // form - if err := td.PixelAPI.UserPasswordSet( + if err := td.PixelAPI.PutUserPassword( f.FieldVal("old_password"), f.FieldVal("new_password"), ); err != nil { @@ -149,7 +149,7 @@ func (wc *WebController) emailForm(td *TemplateData, r *http.Request) (f Form) { } if f.ReadInput(r) { - if err := td.PixelAPI.UserEmailReset( + if err := td.PixelAPI.PutUserEmailReset( f.FieldVal("new_email"), false, ); err != nil { @@ -171,7 +171,7 @@ func (wc *WebController) serveEmailConfirm( var err error var status string - err = wc.api.UserEmailResetConfirm(r.FormValue("key")) + err = wc.api.PutUserEmailResetConfirm(r.FormValue("key")) if err != nil && err.Error() == "not_found" { status = "not_found" } else if err != nil { @@ -206,7 +206,7 @@ func (wc *WebController) usernameForm(td *TemplateData, r *http.Request) (f Form } if f.ReadInput(r) { - if err := td.PixelAPI.UserSetUsername(f.FieldVal("new_username")); err != nil { + if err := td.PixelAPI.PutUserUsername(f.FieldVal("new_username")); err != nil { formAPIError(err, &f) } else { // Request was a success diff --git a/webcontroller/web_controller.go b/webcontroller/web_controller.go index 89e74fe..7bfaf36 100644 --- a/webcontroller/web_controller.go +++ b/webcontroller/web_controller.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "fornaxian.tech/pixeldrain_server/api/restapi/apiclient" + "fornaxian.tech/pixeldrain_api_client/pixelapi" "github.com/Fornaxian/log" "github.com/google/uuid" "github.com/julienschmidt/httprouter" @@ -42,7 +42,7 @@ type WebController struct { // API client to use for all requests. If the user is authenticated you // should call Login() on this object. Calling Login will create a copy and // not alter the original PixelAPI, but it will use the same HTTP Transport - api apiclient.PixelAPI + api pixelapi.PixelAPI } // New initializes a new WebController by registering all the request handlers @@ -68,7 +68,7 @@ func New( sessionCookieDomain: sessionCookieDomain, proxyAPIRequests: proxyAPIRequests, httpClient: &http.Client{Timeout: time.Minute * 10}, - api: apiclient.New(apiURLInternal), + api: pixelapi.New(apiURLInternal), } wc.templates = NewTemplateManager(resourceDir, apiURLExternal, debugMode) wc.templates.ParseTemplates(false) @@ -379,7 +379,7 @@ func (wc *WebController) getAPIKey(r *http.Request) (key string, err error) { func (wc *WebController) captchaKey() string { // This only runs on the first request if wc.captchaSiteKey == "" { - capt, err := wc.api.GetRecaptcha() + capt, err := wc.api.GetMiscRecaptcha() if err != nil { log.Error("Error getting recaptcha key: %s", err) return ""