Add content policy and add abuse categories
This commit is contained in:
25
main.go
25
main.go
@@ -2,8 +2,10 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"fornaxian.tech/pixeldrain_server/util"
|
||||||
web "fornaxian.tech/pixeldrain_web/init"
|
web "fornaxian.tech/pixeldrain_web/init"
|
||||||
|
|
||||||
"github.com/Fornaxian/log"
|
"github.com/Fornaxian/log"
|
||||||
@@ -14,17 +16,32 @@ import (
|
|||||||
// be directly embedded by another Go project. And when deployed it will run
|
// be directly embedded by another Go project. And when deployed it will run
|
||||||
// independently.
|
// independently.
|
||||||
func main() {
|
func main() {
|
||||||
|
var err error
|
||||||
|
var sock = flag.Bool("systemd-socket", false, "Enable/disable systemd socket activation")
|
||||||
var listen = flag.String("listen", ":8081", "The address which the API server will listen on")
|
var listen = flag.String("listen", ":8081", "The address which the API server will listen on")
|
||||||
var prefix = flag.String("prefix", "", "Prefix that comes before the API URL")
|
var prefix = flag.String("prefix", "", "Prefix that comes before the API URL")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
r := httprouter.New()
|
var listener net.Listener
|
||||||
|
|
||||||
web.Init(r, *prefix, true)
|
// Serve the API on a socket. If systemd-socket is enabled we'll reuse
|
||||||
|
// systemd's socket, else we'll create our own to serve on
|
||||||
|
if *sock {
|
||||||
|
// Socket activation enabled. Get the provided sockets and serve on them
|
||||||
|
if listener, err = util.SystemdSocketByName("pd-web.socket"); err != nil {
|
||||||
|
panic("Socket pd-web.socket not found")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Socket activation disabled, so we create our own listener to serve on
|
||||||
|
if listener, err = net.Listen("tcp", *listen); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := http.ListenAndServe(*listen, r)
|
var router = httprouter.New()
|
||||||
|
web.Init(router, *prefix, true)
|
||||||
|
|
||||||
if err != nil {
|
if err = http.Serve(listener, router); err != nil {
|
||||||
log.Error("Can't listen and serve Pixeldrain Web: %v", err)
|
log.Error("Can't listen and serve Pixeldrain Web: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,33 @@ spare some coins. Possible methods for donating are:
|
|||||||
* <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU49A5NHPAZ9G&source=url">
|
* <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU49A5NHPAZ9G&source=url">
|
||||||
Donate with PayPal</a>
|
Donate with PayPal</a>
|
||||||
|
|
||||||
|
## Content policy
|
||||||
|
|
||||||
|
The following types of content are not allowed to be shared on pixeldrain. They
|
||||||
|
will be removed when reported.
|
||||||
|
|
||||||
|
* **Copyright violation**: Works which are shared without permission from the
|
||||||
|
copyright holder.
|
||||||
|
* **Abuse of minors**: Videos, images or audio fragments depicting abuse or
|
||||||
|
inappropriate touching of minors will be removed and reported to the National
|
||||||
|
Center for Missing and Exploited Children when found.
|
||||||
|
* **Terrorism**: Videos, images or audio fragments which promote and
|
||||||
|
glorify acts of terrorism.
|
||||||
|
* **Gore**: Graphic and shocking videos or images depicting severe harm to
|
||||||
|
humans.
|
||||||
|
* **Malware and computer viruses**: Software designed to cause harm to computer
|
||||||
|
systems.
|
||||||
|
|
||||||
|
If you have found content which falls in any of these categories on pixeldrain
|
||||||
|
please report the download link to me at
|
||||||
|
[abuse@pixeldrain.com](mailto:abuse@pixeldrain.com) and I will review it. If the
|
||||||
|
content does not fit into one of the categories your e-mail will be ignored.
|
||||||
|
|
||||||
|
Fornaxian Technologies cannot be held liable for any illegal or copyrighted
|
||||||
|
material that's uploaded by the users of this application under the Online
|
||||||
|
Copyright Infringement Liability Limitation Act § 512\(c) in the USA and the
|
||||||
|
Electronic Commerce Directive 2000 Article 14 in the EU.
|
||||||
|
|
||||||
## How does pixeldrain store files?
|
## How does pixeldrain store files?
|
||||||
|
|
||||||
Pixeldrain uses a few different techniques to store files cheaply, efficiently
|
Pixeldrain uses a few different techniques to store files cheaply, efficiently
|
||||||
@@ -87,16 +114,8 @@ When uploading a file pixeldrain will save a list of file links on your
|
|||||||
browser's local storage. This data is **only** used for viewing your upload
|
browser's local storage. This data is **only** used for viewing your upload
|
||||||
history on the [history page](/history).
|
history on the [history page](/history).
|
||||||
|
|
||||||
## Legality
|
## Support
|
||||||
|
|
||||||
I cannot be held liable for any illegal and / or copyrighted material that's
|
|
||||||
uploaded by the users of this application. Files uploaded to this website are
|
|
||||||
subjected to local laws. If laws are being broken, and I've been notified of the
|
|
||||||
fact I'll have to delete the offending content. If you find any files on this
|
|
||||||
domain that break the law, please contact me at
|
|
||||||
[abuse@pixeldrain.com](mailto:abuse@pixeldrain.com), and I'll take care of it.
|
|
||||||
|
|
||||||
Please share responsibly.
|
|
||||||
|
|
||||||
For other questions you can reach me at
|
For other questions you can reach me at
|
||||||
[support@pixeldrain.com](mailto:support@pixeldrain.com)
|
[support@pixeldrain.com](mailto:support@pixeldrain.com). Abuse reports sent to
|
||||||
|
this address will not be reviewed, use the abuse address.
|
||||||
|
@@ -15,12 +15,12 @@
|
|||||||
* [BurntSushi/toml](https://github.com/BurntSushi/toml)
|
* [BurntSushi/toml](https://github.com/BurntSushi/toml)
|
||||||
* [julienschmidt/httprouter](https://github.com/julienschmidt/httprouter)
|
* [julienschmidt/httprouter](https://github.com/julienschmidt/httprouter)
|
||||||
* [gabriel-vasile/mimetype](https://github.com/gabriel-vasile/mimetype)
|
* [gabriel-vasile/mimetype](https://github.com/gabriel-vasile/mimetype)
|
||||||
* [disintegration/imaging](github.com/disintegration/imaging)
|
* [disintegration/imaging](https://github.com/disintegration/imaging)
|
||||||
* [gorilla/websocket](github.com/gorilla/websocket)
|
* [gorilla/websocket](https://github.com/gorilla/websocket)
|
||||||
* [shopspring/decimal](github.com/shopspring/decimal)
|
* [shopspring/decimal](https://github.com/shopspring/decimal)
|
||||||
* [jhillyerd/enmime](github.com/jhillyerd/enmime)
|
* [jhillyerd/enmime](https://github.com/jhillyerd/enmime)
|
||||||
* [russross/blackfriday](https://github.com/russross/blackfriday)
|
* [russross/blackfriday](https://github.com/russross/blackfriday)
|
||||||
* [microcosm-cc/bluemonday](github.com/microcosm-cc/bluemonday)
|
* [microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday)
|
||||||
|
|
||||||
### Web framework
|
### Web framework
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
border-top: 1px solid var(--layer_2_color_border);
|
border-top: 1px solid var(--layer_2_color_border);
|
||||||
border-bottom: 1px solid var(--layer_2_color_border);
|
border-bottom: 1px solid var(--layer_2_color_border);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin: 10px 0;
|
margin: 1.5em 0;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.big_number {
|
.big_number {
|
||||||
@@ -122,9 +122,8 @@
|
|||||||
Upload <u>T</u>ext</button>
|
Upload <u>T</u>ext</button>
|
||||||
<br/>
|
<br/>
|
||||||
<p>
|
<p>
|
||||||
By uploading files to pixeldrain you accept that a cookie will
|
By uploading files to pixeldrain you acknowledge and accept our
|
||||||
be placed in your web browser. More information on the
|
<a href="/about#content-policy">content policy</a>.
|
||||||
<a href="/about">about</a> page
|
|
||||||
<p>
|
<p>
|
||||||
<div id="instruction_2" class="instruction_highlight">
|
<div id="instruction_2" class="instruction_highlight">
|
||||||
<div class="limit_width">
|
<div class="limit_width">
|
||||||
|
@@ -182,7 +182,9 @@ const toggle_select = () => {
|
|||||||
{child.name}
|
{child.name}
|
||||||
</td>
|
</td>
|
||||||
<td class="node_size">
|
<td class="node_size">
|
||||||
{formatDataVolume(child.file_size, 3)}
|
{#if child.type === "file"}
|
||||||
|
{formatDataVolume(child.file_size, 3)}
|
||||||
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
{/each}
|
||||||
|
88
svelte/src/user_buckets/Bucket.svelte
Normal file
88
svelte/src/user_buckets/Bucket.svelte
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
<script>
|
||||||
|
|
||||||
|
export let bucket
|
||||||
|
let details_hidden = true
|
||||||
|
const expand_bucket = () => {
|
||||||
|
details_hidden = !details_hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="bucket">
|
||||||
|
<div class="bucket_header">
|
||||||
|
<a href={'/d/' + bucket.id} class="bucket_title">
|
||||||
|
<img class="bucket_icon" src="/res/img/mime/folder-remote.png" alt="Bucket icon"/>
|
||||||
|
{bucket.name}
|
||||||
|
</a>
|
||||||
|
<button class="bucket_expand" on:click={expand_bucket}>
|
||||||
|
{#if details_hidden}
|
||||||
|
<i class="icon">expand_more</i>
|
||||||
|
{:else}
|
||||||
|
<i class="icon">expand_less</i>
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="bucket_details" class:hidden={details_hidden}>
|
||||||
|
<form>
|
||||||
|
<table class="form">
|
||||||
|
<tr class="form">
|
||||||
|
<td>Name</td>
|
||||||
|
<td><input type="text" value={bucket.name} /></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="form">
|
||||||
|
<td colspan="2">
|
||||||
|
<button class="button_red">
|
||||||
|
<i class="icon">delete</i> Delete
|
||||||
|
</button>
|
||||||
|
<button class="button_highlight" style="float: right;">
|
||||||
|
<i class="icon">save</i> Save
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bucket {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: var(--layer_3_color);
|
||||||
|
transition: box-shadow 0.5s;
|
||||||
|
box-shadow: 1px 1px var(--layer_3_shadow) 0 var(--shadow_color);
|
||||||
|
}
|
||||||
|
.bucket_header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
color: var(--text_color);
|
||||||
|
}
|
||||||
|
.bucket_header:hover {
|
||||||
|
background-color: var(--input_color_dark)
|
||||||
|
}
|
||||||
|
.bucket_title {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
align-self: center;
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.bucket_icon {
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
margin: 4px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.bucket_expand {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
.bucket_details {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.4em;
|
||||||
|
flex-direction: column;
|
||||||
|
text-decoration: none;
|
||||||
|
border-top: 1px solid var(--layer_3_color_border);
|
||||||
|
color: var(--text_color);
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -1,5 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
import Bucket from "./Bucket.svelte";
|
||||||
import Spinner from "../util/Spinner.svelte";
|
import Spinner from "../util/Spinner.svelte";
|
||||||
import { fs_get_buckets } from "../filesystem/FilesystemAPI.svelte";
|
import { fs_get_buckets } from "../filesystem/FilesystemAPI.svelte";
|
||||||
|
|
||||||
@@ -17,10 +18,6 @@ const get_buckets = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const expand_bucket = () => {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(get_buckets);
|
onMount(get_buckets);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -32,15 +29,23 @@ onMount(get_buckets);
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="limit_width">
|
<div class="limit_width">
|
||||||
|
<button style="float: right;">
|
||||||
|
<i class="icon">create_new_folder</i> New bucket
|
||||||
|
</button>
|
||||||
|
<br/>
|
||||||
|
<h2>Persistent buckets</h2>
|
||||||
|
<p>
|
||||||
|
These buckets don't expire, but have limited storage space and
|
||||||
|
bandwidth. Their limits can be raised by buying a subscription.
|
||||||
|
</p>
|
||||||
{#each buckets as bucket}
|
{#each buckets as bucket}
|
||||||
<a class="bucket_header" href={'/d/' + bucket.id}>
|
<Bucket bucket={bucket}></Bucket>
|
||||||
<div class="bucket_title">{bucket.name}</div>
|
|
||||||
<button class="bucket_expand" on:click|preventDefault={expand_bucket}><i class="icon">expand_more</i></button>
|
|
||||||
</a>
|
|
||||||
<div class="bucket_details">
|
|
||||||
Hello!
|
|
||||||
</div>
|
|
||||||
{/each}
|
{/each}
|
||||||
|
<br/>
|
||||||
|
<h2>Temporary buckets</h2>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -50,34 +55,4 @@ onMount(get_buckets);
|
|||||||
height: 100px;
|
height: 100px;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
.bucket_header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--text_color);
|
|
||||||
background-color: var(--layer_3_color);
|
|
||||||
transition: box-shadow 0.5s;
|
|
||||||
box-shadow: 1px 1px var(--layer_2_shadow) 0 var(--shadow_color);
|
|
||||||
}
|
|
||||||
.bucket_header:hover {
|
|
||||||
box-shadow: 0 0 2px 2px var(--highlight_color), inset 0 0 1px 1px var(--highlight_color);
|
|
||||||
color: var(--highlight_color);
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.bucket_title {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
align-self: center;
|
|
||||||
padding: 0.4em;
|
|
||||||
}
|
|
||||||
.bucket_expand {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
.bucket_details {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--text_color);
|
|
||||||
background-color: var(--layer_3_color);
|
|
||||||
transition: box-shadow 0.5s;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -4,7 +4,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"fornaxian.tech/pixeldrain_server/api/restapi/apiclient"
|
|
||||||
"fornaxian.tech/pixeldrain_server/util"
|
"fornaxian.tech/pixeldrain_server/util"
|
||||||
"github.com/Fornaxian/log"
|
"github.com/Fornaxian/log"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
@@ -15,11 +14,9 @@ func (wc *WebController) serveAdClick(w http.ResponseWriter, r *http.Request, p
|
|||||||
w.Header().Set("Referrer-Policy", "origin")
|
w.Header().Set("Referrer-Policy", "origin")
|
||||||
http.Redirect(w, r, r.URL.Query().Get("target"), http.StatusTemporaryRedirect)
|
http.Redirect(w, r, r.URL.Query().Get("target"), http.StatusTemporaryRedirect)
|
||||||
|
|
||||||
api := apiclient.New(wc.apiURLInternal)
|
|
||||||
|
|
||||||
// The Real IP is used in the API server to determine that the view is not
|
// The Real IP is used in the API server to determine that the view is not
|
||||||
// fake
|
// fake
|
||||||
api.RealIP = util.RemoteAddress(r)
|
var api = wc.api.RealIP(util.RemoteAddress(r))
|
||||||
|
|
||||||
// Log a view on the file
|
// Log a view on the file
|
||||||
if err := api.PostFileView(p.ByName("id"), wc.viewTokenOrBust()); err != nil {
|
if err := api.PostFileView(p.ByName("id"), wc.viewTokenOrBust()); err != nil {
|
||||||
|
@@ -110,7 +110,14 @@ func (wc *WebController) adminAbuseForm(td *TemplateData, r *http.Request) (f Fo
|
|||||||
Label: "Type",
|
Label: "Type",
|
||||||
DefaultValue: "unknown",
|
DefaultValue: "unknown",
|
||||||
Type: FieldTypeRadio,
|
Type: FieldTypeRadio,
|
||||||
RadioValues: []string{"unknown", "copyright", "terrorism", "child_abuse"},
|
RadioValues: []string{
|
||||||
|
"unknown",
|
||||||
|
"copyright",
|
||||||
|
"child_abuse",
|
||||||
|
"terrorism",
|
||||||
|
"gore",
|
||||||
|
"malware",
|
||||||
|
},
|
||||||
}, {
|
}, {
|
||||||
Name: "reporter",
|
Name: "reporter",
|
||||||
Label: "Reporter",
|
Label: "Reporter",
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"fornaxian.tech/pixeldrain_server/api/restapi/apiclient"
|
|
||||||
"fornaxian.tech/pixeldrain_server/util"
|
"fornaxian.tech/pixeldrain_server/util"
|
||||||
"github.com/Fornaxian/log"
|
"github.com/Fornaxian/log"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
@@ -21,9 +20,8 @@ func (wc *WebController) serveFilePreview(w http.ResponseWriter, r *http.Request
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
api := apiclient.New(wc.apiURLInternal)
|
apiKey, _ := wc.getAPIKey(r)
|
||||||
api.APIKey, _ = wc.getAPIKey(r)
|
api := wc.api.Login(apiKey).RealIP(util.RemoteAddress(r))
|
||||||
api.RealIP = util.RemoteAddress(r)
|
|
||||||
|
|
||||||
file, err := api.GetFileInfo(p.ByName("id")) // TODO: Error handling
|
file, err := api.GetFileInfo(p.ByName("id")) // TODO: Error handling
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
func (wc *WebController) viewTokenOrBust() (t string) {
|
func (wc *WebController) viewTokenOrBust() (t string) {
|
||||||
var err error
|
var err error
|
||||||
if t, err = wc.systemPixelAPI.GetMiscViewToken(); err != nil {
|
if t, err = wc.api.GetMiscViewToken(); err != nil {
|
||||||
log.Error("Could not get viewtoken: %s", err)
|
log.Error("Could not get viewtoken: %s", err)
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
@@ -47,9 +47,7 @@ func adType() int {
|
|||||||
switch i := rand.Intn(5); i {
|
switch i := rand.Intn(5); i {
|
||||||
case 0:
|
case 0:
|
||||||
return amarulaSolutions
|
return amarulaSolutions
|
||||||
case 1:
|
case 1, 2, 3, 4:
|
||||||
return adMaven
|
|
||||||
case 2, 3, 4:
|
|
||||||
return propellerAds
|
return propellerAds
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf(
|
panic(fmt.Errorf(
|
||||||
|
@@ -29,7 +29,7 @@ type TemplateData struct {
|
|||||||
Style pixeldrainStyleSheet
|
Style pixeldrainStyleSheet
|
||||||
UserStyle template.CSS
|
UserStyle template.CSS
|
||||||
APIEndpoint template.URL
|
APIEndpoint template.URL
|
||||||
PixelAPI *apiclient.PixelAPI
|
PixelAPI apiclient.PixelAPI
|
||||||
Hostname template.HTML
|
Hostname template.HTML
|
||||||
|
|
||||||
// Only used on file viewer page
|
// Only used on file viewer page
|
||||||
@@ -50,19 +50,19 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
|
|||||||
Style: userStyle(r),
|
Style: userStyle(r),
|
||||||
UserStyle: template.CSS(userStyle(r).String()),
|
UserStyle: template.CSS(userStyle(r).String()),
|
||||||
APIEndpoint: template.URL(wc.apiURLExternal),
|
APIEndpoint: template.URL(wc.apiURLExternal),
|
||||||
PixelAPI: apiclient.New(wc.apiURLInternal),
|
|
||||||
Hostname: template.HTML(wc.hostname),
|
|
||||||
URLQuery: r.URL.Query(),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the user's IP address for making requests
|
// Use the user's IP address for making requests
|
||||||
t.PixelAPI.RealIP = util.RemoteAddress(r)
|
PixelAPI: wc.api.RealIP(util.RemoteAddress(r)),
|
||||||
|
|
||||||
|
Hostname: template.HTML(wc.hostname),
|
||||||
|
URLQuery: r.URL.Query(),
|
||||||
|
}
|
||||||
|
|
||||||
// If the user is authenticated we'll indentify him and put the user info
|
// If the user is authenticated we'll indentify him and put the user info
|
||||||
// into the templatedata. This is used for putting the username in the menu
|
// into the templatedata. This is used for putting the username in the menu
|
||||||
// and stuff like that
|
// and stuff like that
|
||||||
if key, err := wc.getAPIKey(r); err == nil {
|
if key, err := wc.getAPIKey(r); err == nil {
|
||||||
t.PixelAPI.APIKey = key // Use the user's API key for all requests
|
t.PixelAPI = t.PixelAPI.Login(key) // Use the user's API key for all requests
|
||||||
t.User, err = t.PixelAPI.UserInfo()
|
t.User, err = t.PixelAPI.UserInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// This session key doesn't work, or the backend is down, user
|
// This session key doesn't work, or the backend is down, user
|
||||||
@@ -71,7 +71,7 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
if err.Error() == "authentication_required" || err.Error() == "authentication_failed" {
|
if err.Error() == "authentication_required" || err.Error() == "authentication_failed" {
|
||||||
// Disable API authentication
|
// Disable API authentication
|
||||||
t.PixelAPI.APIKey = ""
|
t.PixelAPI = wc.api
|
||||||
|
|
||||||
// Remove the authentication cookie
|
// Remove the authentication cookie
|
||||||
log.Debug("Deleting invalid API key")
|
log.Debug("Deleting invalid API key")
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"fornaxian.tech/pixeldrain_server/api/restapi/apiclient"
|
|
||||||
"github.com/Fornaxian/log"
|
"github.com/Fornaxian/log"
|
||||||
"github.com/julienschmidt/httprouter"
|
"github.com/julienschmidt/httprouter"
|
||||||
)
|
)
|
||||||
@@ -16,8 +15,7 @@ func (wc *WebController) serveLogout(
|
|||||||
p httprouter.Params,
|
p httprouter.Params,
|
||||||
) {
|
) {
|
||||||
if key, err := wc.getAPIKey(r); err == nil {
|
if key, err := wc.getAPIKey(r); err == nil {
|
||||||
var api = apiclient.New(wc.apiURLInternal)
|
var api = wc.api.Login(key)
|
||||||
api.APIKey = key
|
|
||||||
if err = api.UserSessionDestroy(key); err != nil {
|
if err = api.UserSessionDestroy(key); err != nil {
|
||||||
log.Warn("logout failed for session '%s': %s", key, err)
|
log.Warn("logout failed for session '%s': %s", key, err)
|
||||||
}
|
}
|
||||||
@@ -150,7 +148,7 @@ func (wc *WebController) loginForm(td *TemplateData, r *http.Request) (f Form) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if f.ReadInput(r) {
|
if f.ReadInput(r) {
|
||||||
loginResp, err := td.PixelAPI.UserLogin(f.FieldVal("username"), f.FieldVal("password"), false)
|
loginResp, err := td.PixelAPI.UserLogin(f.FieldVal("username"), f.FieldVal("password"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
formAPIError(err, &f)
|
formAPIError(err, &f)
|
||||||
} else {
|
} else {
|
||||||
|
@@ -170,8 +170,7 @@ func (wc *WebController) serveEmailConfirm(
|
|||||||
var err error
|
var err error
|
||||||
var status string
|
var status string
|
||||||
|
|
||||||
api := apiclient.New(wc.apiURLInternal)
|
err = wc.api.UserEmailResetConfirm(r.FormValue("key"))
|
||||||
err = api.UserEmailResetConfirm(r.FormValue("key"))
|
|
||||||
if err != nil && err.Error() == "not_found" {
|
if err != nil && err.Error() == "not_found" {
|
||||||
status = "not_found"
|
status = "not_found"
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
|
@@ -36,9 +36,10 @@ type WebController struct {
|
|||||||
|
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
|
|
||||||
// This API client should only be used for system functions like getting
|
// API client to use for all requests. If the user is authenticated you
|
||||||
// view tokens. It has no authentication and no IP forwarding
|
// should call Login() on this object. Calling Login will create a copy and
|
||||||
systemPixelAPI *apiclient.PixelAPI
|
// not alter the original PixelAPI, but it will use the same HTTP Transport
|
||||||
|
api apiclient.PixelAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// New initializes a new WebController by registering all the request handlers
|
// New initializes a new WebController by registering all the request handlers
|
||||||
@@ -60,7 +61,7 @@ func New(
|
|||||||
apiURLExternal: apiURLExternal,
|
apiURLExternal: apiURLExternal,
|
||||||
sessionCookieDomain: sessionCookieDomain,
|
sessionCookieDomain: sessionCookieDomain,
|
||||||
httpClient: &http.Client{Timeout: time.Minute * 10},
|
httpClient: &http.Client{Timeout: time.Minute * 10},
|
||||||
systemPixelAPI: apiclient.New(apiURLInternal),
|
api: apiclient.New(apiURLInternal),
|
||||||
}
|
}
|
||||||
wc.templates = NewTemplateManager(resourceDir, apiURLExternal, debugMode)
|
wc.templates = NewTemplateManager(resourceDir, apiURLExternal, debugMode)
|
||||||
wc.templates.ParseTemplates(false)
|
wc.templates.ParseTemplates(false)
|
||||||
@@ -218,7 +219,7 @@ func (wc *WebController) serveMarkdown(tpl string, requireAuth bool) httprouter.
|
|||||||
var inHeader = false
|
var inHeader = false
|
||||||
blackfriday.New(
|
blackfriday.New(
|
||||||
blackfriday.WithRenderer(renderer),
|
blackfriday.WithRenderer(renderer),
|
||||||
blackfriday.WithExtensions(blackfriday.CommonExtensions),
|
blackfriday.WithExtensions(blackfriday.CommonExtensions|blackfriday.AutoHeadingIDs),
|
||||||
).Parse(
|
).Parse(
|
||||||
tplBuf.Bytes(),
|
tplBuf.Bytes(),
|
||||||
).Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
|
).Walk(func(node *blackfriday.Node, entering bool) blackfriday.WalkStatus {
|
||||||
@@ -337,8 +338,7 @@ func (wc *WebController) getAPIKey(r *http.Request) (key string, err error) {
|
|||||||
func (wc *WebController) captchaKey() string {
|
func (wc *WebController) captchaKey() string {
|
||||||
// This only runs on the first request
|
// This only runs on the first request
|
||||||
if wc.captchaSiteKey == "" {
|
if wc.captchaSiteKey == "" {
|
||||||
var api = apiclient.New(wc.apiURLInternal)
|
capt, err := wc.api.GetRecaptcha()
|
||||||
capt, err := api.GetRecaptcha()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error getting recaptcha key: %s", err)
|
log.Error("Error getting recaptcha key: %s", err)
|
||||||
return ""
|
return ""
|
||||||
|
Reference in New Issue
Block a user