Support embedded viewer

This commit is contained in:
2021-03-10 20:13:32 +01:00
parent e8181eb6d2
commit 0ebc30814b
14 changed files with 81 additions and 45 deletions

7
go.mod
View File

@@ -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

View File

@@ -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

View File

@@ -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 > * {

View File

@@ -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`}}

View File

@@ -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)

View File

@@ -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,

View File

@@ -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)

View File

@@ -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")

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 ""