finish user registration / login
This commit is contained in:
@@ -7,7 +7,7 @@ import (
|
|||||||
// GetFile makes a file download request and returns a readcloser. Don't forget
|
// GetFile makes a file download request and returns a readcloser. Don't forget
|
||||||
// to close it!
|
// to close it!
|
||||||
func (p *PixelAPI) GetFile(id string) (io.ReadCloser, error) {
|
func (p *PixelAPI) GetFile(id string) (io.ReadCloser, error) {
|
||||||
return getRaw(p.apiEndpoint + "/file/" + id)
|
return p.getRaw(p.apiEndpoint + "/file/" + id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileInfo File information object from the pixeldrain API
|
// FileInfo File information object from the pixeldrain API
|
||||||
@@ -28,7 +28,7 @@ type FileInfo struct {
|
|||||||
// GetFileInfo gets the FileInfo from the pixeldrain API
|
// GetFileInfo gets the FileInfo from the pixeldrain API
|
||||||
func (p *PixelAPI) GetFileInfo(id string) (resp *FileInfo, err *Error) {
|
func (p *PixelAPI) GetFileInfo(id string) (resp *FileInfo, err *Error) {
|
||||||
resp = &FileInfo{}
|
resp = &FileInfo{}
|
||||||
err = getJSON(p.apiEndpoint+"/file/"+id+"/info", resp)
|
err = p.jsonRequest("GET", p.apiEndpoint+"/file/"+id+"/info", resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ type ListFile struct {
|
|||||||
// List.Error. Standard error checks apply.
|
// List.Error. Standard error checks apply.
|
||||||
func (p *PixelAPI) GetList(id string) (resp *List, err *Error) {
|
func (p *PixelAPI) GetList(id string) (resp *List, err *Error) {
|
||||||
resp = &List{}
|
resp = &List{}
|
||||||
err = getJSON(p.apiEndpoint+"/list/"+id, resp)
|
err = p.jsonRequest("GET", p.apiEndpoint+"/list/"+id, resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ type Recaptcha struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *PixelAPI) GetRecaptcha() (resp *Recaptcha, err *Error) {
|
func (p *PixelAPI) GetRecaptcha() (resp *Recaptcha, err *Error) {
|
||||||
err = getJSON(p.apiEndpoint+"/misc/recpatcha", resp)
|
err = p.jsonRequest("GET", p.apiEndpoint+"/misc/recpatcha", resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -14,11 +14,12 @@ import (
|
|||||||
// PixelAPI is the Pixeldrain API client
|
// PixelAPI is the Pixeldrain API client
|
||||||
type PixelAPI struct {
|
type PixelAPI struct {
|
||||||
apiEndpoint string
|
apiEndpoint string
|
||||||
|
apiKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new Pixeldrain API client to query the Pixeldrain API with
|
// New creates a new Pixeldrain API client to query the Pixeldrain API with
|
||||||
func New(apiEndpoint string) *PixelAPI {
|
func New(apiEndpoint, apiKey string) *PixelAPI {
|
||||||
return &PixelAPI{apiEndpoint}
|
return &PixelAPI{apiEndpoint, apiKey}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error is either an error that occurred during the API request
|
// Error is either an error that occurred during the API request
|
||||||
@@ -33,12 +34,19 @@ type Error struct {
|
|||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
|
Extra interface{} `json:"extra,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Error) Error() string { return e.Value }
|
func (e Error) Error() string { return e.Value }
|
||||||
|
|
||||||
func getJSON(url string, target interface{}) *Error {
|
// SuccessResponse is a generic response the API returns when the action was
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
// successful and there is nothing interesting to report
|
||||||
|
type SuccessResponse struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PixelAPI) jsonRequest(method, url string, target interface{}) *Error {
|
||||||
|
req, err := http.NewRequest(method, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Error{
|
return &Error{
|
||||||
ReqError: true,
|
ReqError: true,
|
||||||
@@ -47,6 +55,9 @@ func getJSON(url string, target interface{}) *Error {
|
|||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if p.apiKey != "" {
|
||||||
|
req.SetBasicAuth("", p.apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
@@ -63,11 +74,14 @@ func getJSON(url string, target interface{}) *Error {
|
|||||||
return parseJSONResponse(resp, target)
|
return parseJSONResponse(resp, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getString(url string) (string, error) {
|
func (p *PixelAPI) getString(url string) (string, error) {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
if p.apiKey != "" {
|
||||||
|
req.SetBasicAuth("", p.apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
@@ -83,11 +97,14 @@ func getString(url string) (string, error) {
|
|||||||
return string(bodyBytes), err
|
return string(bodyBytes), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getRaw(url string) (io.ReadCloser, error) {
|
func (p *PixelAPI) getRaw(url string) (io.ReadCloser, error) {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if p.apiKey != "" {
|
||||||
|
req.SetBasicAuth("", p.apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
|
|
||||||
@@ -99,7 +116,7 @@ func getRaw(url string) (io.ReadCloser, error) {
|
|||||||
return resp.Body, err
|
return resp.Body, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func postForm(url string, vals url.Values, target interface{}) *Error {
|
func (p *PixelAPI) postForm(url string, vals url.Values, target interface{}) *Error {
|
||||||
req, err := http.NewRequest("POST", url, strings.NewReader(vals.Encode()))
|
req, err := http.NewRequest("POST", url, strings.NewReader(vals.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Error{
|
return &Error{
|
||||||
@@ -109,6 +126,9 @@ func postForm(url string, vals url.Values, target interface{}) *Error {
|
|||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if p.apiKey != "" {
|
||||||
|
req.SetBasicAuth("", p.apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
|
@@ -27,7 +27,34 @@ func (p *PixelAPI) UserRegister(username, email, password, captcha string) (resp
|
|||||||
form.Add("email", email)
|
form.Add("email", email)
|
||||||
form.Add("password", password)
|
form.Add("password", password)
|
||||||
form.Add("recaptcha_response", captcha)
|
form.Add("recaptcha_response", captcha)
|
||||||
err = postForm(p.apiEndpoint+"/user/register", form, resp)
|
err = p.postForm(p.apiEndpoint+"/user/register", form, resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserInfo contains information about the logged in user
|
||||||
|
type UserInfo struct {
|
||||||
|
Success bool `json:"success"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserInfo returns information about the logged in user. Required an API key
|
||||||
|
func (p *PixelAPI) UserInfo() (resp *UserInfo, err *Error) {
|
||||||
|
resp = &UserInfo{}
|
||||||
|
err = p.jsonRequest("GET", p.apiEndpoint+"/user", resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserSessionDestroy destroys an API key so it can no longer be used to perform
|
||||||
|
// actions
|
||||||
|
func (p *PixelAPI) UserSessionDestroy(key string) (resp *SuccessResponse, err *Error) {
|
||||||
|
resp = &SuccessResponse{}
|
||||||
|
err = p.jsonRequest("DELETE", p.apiEndpoint+"/user/session", resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -119,12 +119,15 @@ html{
|
|||||||
padding: 4px 0px 4px 0px;
|
padding: 4px 0px 4px 0px;
|
||||||
z-index: 101;
|
z-index: 101;
|
||||||
}
|
}
|
||||||
.highlight_light {background-color: #484848;}
|
.highlight_light {background-color: #484848; border-color: #686868;}
|
||||||
.highlight_middle {background-color: #3a3a3a;}
|
.highlight_middle {background-color: #3a3a3a; border-color: #686868;}
|
||||||
.highlight_dark {background-color: #303030;}
|
.highlight_dark {background-color: #303030; border-color: #686868;}
|
||||||
|
.highlight_green {background-color: rgba(0, 255, 0, 0.05); border-color: #00d000;}
|
||||||
|
.highlight_blue {background-color: rgba(32, 32, 255, 0.2); border-color: rgb(54, 54, 255);}
|
||||||
|
.highlight_red {background-color: rgba(255, 0, 0, 0.05); border-color: #B00000;}
|
||||||
|
|
||||||
.border_top {border-top: #686868 1px solid;}
|
.border_top {border-top-width: 1px; border-top-style: solid;}
|
||||||
.border_bottom {border-bottom: #686868 1px solid;}
|
.border_bottom {border-bottom-width: 1px; border-bottom-style: solid;}
|
||||||
|
|
||||||
/* Common elements */
|
/* Common elements */
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{{define "login"}}
|
{{define "login"}}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html xmlns:th="http://www.thymeleaf.org">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Login ~ PixelDrain</title>
|
<title>Login ~ PixelDrain</title>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
<meta property="og:url" content="http://pixeldra.in/" />
|
<meta property="og:url" content="http://pixeldra.in/" />
|
||||||
<meta property="og:image" content="/res/img/pixeldrain_big.png" />
|
<meta property="og:image" content="/res/img/pixeldrain_big.png" />
|
||||||
<meta property="og:image:type" content="image/png" />
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
|
||||||
|
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -33,26 +35,58 @@
|
|||||||
{{template "menu" .}}
|
{{template "menu" .}}
|
||||||
|
|
||||||
<h1>Log in to your PixelDrain account</h1>
|
<h1>Log in to your PixelDrain account</h1>
|
||||||
<form action="/login" method="POST" class="highlight_dark border_top border_bottom">
|
<div id="submit_result"></div>
|
||||||
|
<form onSubmit="return submitForm();" class="highlight_dark border_top border_bottom">
|
||||||
<table style="margin-left: auto; margin-right: auto;">
|
<table style="margin-left: auto; margin-right: auto;">
|
||||||
<tr>
|
<tr>
|
||||||
<td>Username</td>
|
<td>Username</td>
|
||||||
<td><input name="username" type="text" value=""/></td>
|
<td><input id="username" name="username" type="text" autocomplete="username" value=""/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Password</td>
|
<td>Password</td>
|
||||||
<td><input name="password" type="password"/></td>
|
<td><input id="password" name="password" type="password" autocomplete="current-password"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan=2 style="text-align: right;"><input type="submit" value="Login"/></td>
|
<td colspan=2 style="text-align: right;"><input type="submit" value="Login" class="button_highlight"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
<br/>
|
<br/>
|
||||||
If you don't have a PixelDrain account, you can <a href="/register">register here</a>. No e-mail address required.<br/>
|
If you don't have a PixelDrain account yet, you can <a href="/register">register here</a>. No e-mail address is required.<br/>
|
||||||
{{template "footer"}}
|
{{template "footer"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
function submitForm(){
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
req.onreadystatechange = function(){
|
||||||
|
if (this.readyState === 4) {
|
||||||
|
var response = JSON.parse(req.responseText);
|
||||||
|
var resultDiv = document.getElementById("submit_result");
|
||||||
|
if (response.success) {
|
||||||
|
resultDiv.className = "border_top border_bottom highlight_green";
|
||||||
|
resultDiv.innerHTML = 'Success! Proceeding to user portal...<br/>'
|
||||||
|
+'<a href="/user">Click here if you are not redirected automatically</a>';
|
||||||
|
window.location.href = "/user";
|
||||||
|
} else {
|
||||||
|
resultDiv.className = "border_top border_bottom highlight_red";
|
||||||
|
resultDiv.innerHTML = response.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = new FormData();
|
||||||
|
data.append("username", document.getElementById("username").value);
|
||||||
|
data.append("password", document.getElementById("password").value);
|
||||||
|
|
||||||
|
req.open("POST", apiEndpoint+"/user/login", true);
|
||||||
|
req.send(data);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{{template "analytics"}}
|
{{template "analytics"}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
58
res/template/account/logout.html
Normal file
58
res/template/account/logout.html
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{{define "logout"}}<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Logging out... ~ Pixeldrain</title>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<link rel="stylesheet" href="/global.css"/>
|
||||||
|
<link rel="stylesheet" href="/res/style/layout.css"/>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'/>
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css"/>
|
||||||
|
<link rel="shortcut icon" href="/res/img/tray32.png"/>
|
||||||
|
<meta name="theme-color" content="#9FCF6C"/>
|
||||||
|
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/>
|
||||||
|
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/>
|
||||||
|
{{template "bgpattern"}}
|
||||||
|
|
||||||
|
<meta name="description" content="PixelDrain is a free file sharing service, you
|
||||||
|
can upload any file and you will be given a shareable link right away.
|
||||||
|
PixelDrain also supports previews for images, videos, audio, PDFs and much more.
|
||||||
|
Uncensored, unmonitored and unmoderated."/>
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta property="og:title" content="Logging out... ~ Pixeldrain" />
|
||||||
|
<meta property="og:site_name" content="Pixeldrain" />
|
||||||
|
<meta property="og:description" content="Instant file and screenshot sharing." />
|
||||||
|
<meta property="og:url" content="http://pixeldra.in/" />
|
||||||
|
<meta property="og:image" content="/res/img/pixeldrain_big.png" />
|
||||||
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='body' class="body">
|
||||||
|
{{template "menu" .}}
|
||||||
|
|
||||||
|
<h1>Please confirm that you want to log out of your Pixeldrain account</h1>
|
||||||
|
<form method="POST" target="/logout" class="highlight_dark border_top border_bottom">
|
||||||
|
<input type="submit" value="I want to log out of pixeldrain on this computer" class="button_highlight"/>
|
||||||
|
</form>
|
||||||
|
<br/>
|
||||||
|
<h2>Why do I need to confirm my logout?</h2>
|
||||||
|
<p>
|
||||||
|
We need you to confirm your action here so we can be sure that
|
||||||
|
you really requested a logout. If we didn't do this, anyone (or
|
||||||
|
any website) would be able to send you to the page
|
||||||
|
pixeldrain.com/logout and you would automatically get logged
|
||||||
|
out of Pixeldrain, which would be very annoying.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To prevent this from happening we're verifying that you actually
|
||||||
|
want to log out by making you submit this form. Because this
|
||||||
|
logout button triggers a different request type than normal
|
||||||
|
page vitis we can confirm that you really want to log out.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{{template "footer"}}
|
||||||
|
</div>
|
||||||
|
{{template "analytics"}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{end}}
|
@@ -1,20 +1,11 @@
|
|||||||
{{define "register"}}
|
{{define "register"}}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html xmlns:th="http://www.thymeleaf.org">
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Register ~ PixelDrain</title>
|
<title>Register ~ PixelDrain</title>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
<link rel="stylesheet" href="/global.css"/>
|
<meta name="theme-color" content="#82C13E"/>
|
||||||
<link rel="stylesheet" href="/res/style/layout.css"/>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'/>
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css"/>
|
|
||||||
<link rel="shortcut icon" href="/res/img/tray32.png"/>
|
|
||||||
<meta name="theme-color" content="#9FCF6C"/>
|
|
||||||
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/>
|
|
||||||
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/>
|
|
||||||
{{template "bgpattern"}}
|
|
||||||
|
|
||||||
<meta name="description" content="PixelDrain is a free file sharing service, you
|
<meta name="description" content="PixelDrain is a free file sharing service, you
|
||||||
can upload any file and you will be given a shareable link right away.
|
can upload any file and you will be given a shareable link right away.
|
||||||
PixelDrain also supports previews for images, videos, audio, PDFs and much more.
|
PixelDrain also supports previews for images, videos, audio, PDFs and much more.
|
||||||
@@ -27,7 +18,17 @@
|
|||||||
<meta property="og:image" content="/res/img/pixeldrain_big.png" />
|
<meta property="og:image" content="/res/img/pixeldrain_big.png" />
|
||||||
<meta property="og:image:type" content="image/png" />
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="/global.css"/>
|
||||||
|
<link rel="stylesheet" href="/res/style/layout.css"/>
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'/>
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css"/>
|
||||||
|
<link rel="shortcut icon" href="/res/img/tray32.png"/>
|
||||||
|
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/>
|
||||||
|
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/>
|
||||||
|
|
||||||
<script src="https://www.google.com/recaptcha/api.js"></script>
|
<script src="https://www.google.com/recaptcha/api.js"></script>
|
||||||
|
|
||||||
|
{{template "bgpattern"}}
|
||||||
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
|
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -36,32 +37,55 @@
|
|||||||
{{template "menu" .}}
|
{{template "menu" .}}
|
||||||
|
|
||||||
<h1>Register a new Pixeldrain account</h1>
|
<h1>Register a new Pixeldrain account</h1>
|
||||||
|
<div id="submit_result"></div>
|
||||||
<form onSubmit="return submitForm();" class="highlight_dark border_top border_bottom">
|
<form onSubmit="return submitForm();" class="highlight_dark border_top border_bottom">
|
||||||
<table style="margin-left: auto; margin-right: auto; text-align: left; max-width: 30em;">
|
<table style="margin-left: auto; margin-right: auto; text-align: left; max-width: 30em;">
|
||||||
<tr><td>Username (Used to log in)</td></tr>
|
<tr>
|
||||||
<tr><td><input id="register_username" type="text" autocomplete="username" class="form_input"/></td></tr>
|
<td>Username</td>
|
||||||
<tr><td>used for logging into your account</td></tr>
|
<td><input id="register_username" type="text" autocomplete="username" class="form_input"/></td>
|
||||||
<tr><td><hr/></td></tr>
|
</tr>
|
||||||
<tr><td>E-mail address (optional):</td></tr>
|
<tr><td colspan="2">used for logging into your account<br/><hr/></td></tr>
|
||||||
<tr><td><input id="register_email" type="text" autocomplete="email" class="form_input"/></td></tr>
|
<tr>
|
||||||
<tr><td>
|
<td>E-mail address</td>
|
||||||
your e-mail address will only be used for password
|
<td><input id="register_email" type="text" autocomplete="email" class="form_input"/></td>
|
||||||
resets and important account notifications.
|
</tr>
|
||||||
|
<tr><td colspan="2">
|
||||||
|
not required. your e-mail address will only be used for
|
||||||
|
password resets and important account notifications<br/>
|
||||||
|
<hr/>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr><td><hr/></td></tr>
|
<tr>
|
||||||
<tr><td>
|
<td>Password</td>
|
||||||
Enter your password twice:<br/>
|
<td><input id="register_password1" type="password" autocomplete="new-password" class="form_input"/></td>
|
||||||
(so we can verify that you have not made any typing errors)
|
</tr>
|
||||||
</td></tr>
|
<tr>
|
||||||
<tr><td><input id="register_password1" type="password" autocomplete="new-password" class="form_input"/></td></tr>
|
<td>Password verification</td>
|
||||||
<tr><td><input id="register_password2" type="password" autocomplete="new-password" class="form_input"/></td></tr>
|
<td><input id="register_password2" type="password" autocomplete="new-password" class="form_input"/></td>
|
||||||
<tr><td><hr/></td></tr>
|
</tr>
|
||||||
<tr><td>Prove that you're not a robot (Click the white box)</td></tr>
|
<tr>
|
||||||
<tr><td style="text-align: center;">
|
<td colspan="2">
|
||||||
|
you need to enter your password twice so we can
|
||||||
|
verify that you have not made any typing errors<br/>
|
||||||
|
<hr/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Turing test<br/>
|
||||||
|
(Click the white box)
|
||||||
|
</td>
|
||||||
|
<td style="text-align: center;">
|
||||||
<div class="g-recaptcha" data-theme="dark" data-sitekey="6LdEeQ0TAAAAALBmDF_k_2LgbpuJM66PGspByViS"></div>
|
<div class="g-recaptcha" data-theme="dark" data-sitekey="6LdEeQ0TAAAAALBmDF_k_2LgbpuJM66PGspByViS"></div>
|
||||||
</td></tr>
|
</td>
|
||||||
<tr><td><hr/></td></tr>
|
</tr>
|
||||||
<tr><td colspan=2 style="text-align: right;"><input type="submit" value="Register" class="button_highlight"/></td></tr>
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
the reCaptcha turing test verifies that you are not
|
||||||
|
an evil robot that is trying to flood the website
|
||||||
|
with fake accounts<br/><hr/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr><td colspan="2" style="text-align: right;"><input type="submit" value="Register" class="button_highlight"/></td></tr>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -86,6 +110,21 @@
|
|||||||
req.onreadystatechange = function(){
|
req.onreadystatechange = function(){
|
||||||
if (this.readyState === 4) {
|
if (this.readyState === 4) {
|
||||||
var response = JSON.parse(req.responseText);
|
var response = JSON.parse(req.responseText);
|
||||||
|
var resultDiv = document.getElementById("submit_result");
|
||||||
|
if (response.success) {
|
||||||
|
resultDiv.className = "border_top border_bottom highlight_green";
|
||||||
|
resultDiv.innerHTML = 'Registration completed! You can now <a href="/login">log in to your account</a>.<br/>'
|
||||||
|
+ "We're glad to have you on board, have fun sharing!";
|
||||||
|
} else {
|
||||||
|
resultDiv.className = "border_top border_bottom highlight_red";
|
||||||
|
var resultHtml = "Something went wrong, please correct these problems and try again:<br/><ul>";
|
||||||
|
for (err in response.errors) {
|
||||||
|
resultHtml += "<li>"+ response.errors[err].message +"</li>";
|
||||||
|
}
|
||||||
|
resultHtml += "</ul>";
|
||||||
|
resultDiv.innerHTML = resultHtml;
|
||||||
|
}
|
||||||
|
|
||||||
console.log(response);
|
console.log(response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,11 @@
|
|||||||
<div id="navigation" class="highlight_light border_top border_bottom navigation">
|
<div id="navigation" class="highlight_light border_top border_bottom navigation">
|
||||||
<a href="/">Home</a>
|
<a href="/">Home</a>
|
||||||
<a href="/history">My Files</a>
|
<a href="/history">My Files</a>
|
||||||
<a href="/api">API Documentation</a>
|
<a href="/api">API</a>
|
||||||
<a href="/user">{{if .Authenticated}}{{.Username}}{{else}}Account{{end}}</a>
|
{{if .Authenticated}}<a href="/user">{{.Username}}</a>{{else}}
|
||||||
|
<a href="/login">Login</a>
|
||||||
|
<a href="/register">Register</a>
|
||||||
|
{{end}}
|
||||||
<a href="javascript:void(0);" class="icon" onclick="expandNavigation()">☰</a>
|
<a href="javascript:void(0);" class="icon" onclick="expandNavigation()">☰</a>
|
||||||
<script>
|
<script>
|
||||||
function expandNavigation() {
|
function expandNavigation() {
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
{{define "history-cookies"}}
|
{{define "history-cookies"}}<!DOCTYPE html>
|
||||||
<!DOCTYPE html>
|
<html>
|
||||||
<html xmlns:th="http://www.thymeleaf.org">
|
|
||||||
<head>
|
<head>
|
||||||
<title>Upload History ~ PixelDrain</title>
|
<title>Upload History ~ PixelDrain</title>
|
||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
@@ -49,5 +48,4 @@
|
|||||||
<script src="/res/script/history.js"></script>
|
<script src="/res/script/history.js"></script>
|
||||||
{{template "analytics"}}
|
{{template "analytics"}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>{{end}}
|
||||||
{{end}}
|
|
||||||
|
@@ -3,6 +3,10 @@ package webcontroller
|
|||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"fornaxian.com/pixeldrain-web/pixelapi"
|
||||||
|
"github.com/Fornaxian/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TemplateData is a struct that every template expects when being rendered. In
|
// TemplateData is a struct that every template expects when being rendered. In
|
||||||
@@ -20,12 +24,32 @@ type TemplateData struct {
|
|||||||
Other interface{}
|
Other interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WebController) newTemplateData(r *http.Request) *TemplateData {
|
func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request) *TemplateData {
|
||||||
var t = &TemplateData{
|
var t = &TemplateData{
|
||||||
Authenticated: false,
|
Authenticated: false,
|
||||||
Username: "Fornax",
|
Username: "Fornax",
|
||||||
APIEndpoint: template.URL(wc.conf.APIURLExternal),
|
APIEndpoint: template.URL(wc.conf.APIURLExternal),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if key, err := wc.getAPIKey(r); err == nil {
|
||||||
|
var api = pixelapi.New(wc.conf.APIURLInternal, key)
|
||||||
|
uinf, err := api.UserInfo()
|
||||||
|
if err != nil {
|
||||||
|
// This session key doesn't work, delete it
|
||||||
|
log.Debug("Invalid API key '%s' passed", key)
|
||||||
|
http.SetCookie(w, &http.Cookie{
|
||||||
|
Name: "pd_auth_key",
|
||||||
|
Value: "",
|
||||||
|
Path: "/",
|
||||||
|
Expires: time.Unix(0, 0),
|
||||||
|
})
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authentication succeeded
|
||||||
|
t.Authenticated = true
|
||||||
|
t.Username = uinf.Username
|
||||||
|
}
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
@@ -1 +1,25 @@
|
|||||||
package webcontroller
|
package webcontroller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"fornaxian.com/pixeldrain-web/pixelapi"
|
||||||
|
"github.com/Fornaxian/log"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (wc *WebController) serveLogout(
|
||||||
|
w http.ResponseWriter,
|
||||||
|
r *http.Request,
|
||||||
|
p httprouter.Params,
|
||||||
|
) {
|
||||||
|
if key, err := wc.getAPIKey(r); err == nil {
|
||||||
|
var api = pixelapi.New(wc.conf.APIURLInternal, key)
|
||||||
|
_, err1 := api.UserSessionDestroy(key)
|
||||||
|
if err1 != nil {
|
||||||
|
log.Warn("logout failed for session '%s': %s", key, err1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/", 302)
|
||||||
|
}
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
package webcontroller
|
package webcontroller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"fornaxian.com/pixeldrain-web/init/conf"
|
"fornaxian.com/pixeldrain-web/init/conf"
|
||||||
"fornaxian.com/pixeldrain-web/pixelapi"
|
"fornaxian.com/pixeldrain-web/pixelapi"
|
||||||
"fornaxian.com/pixeldrain-web/webcontroller/templates"
|
"fornaxian.com/pixeldrain-web/webcontroller/templates"
|
||||||
@@ -12,7 +15,7 @@ import (
|
|||||||
|
|
||||||
type WebController struct {
|
type WebController struct {
|
||||||
conf *conf.PixelWebConfig
|
conf *conf.PixelWebConfig
|
||||||
api *pixelapi.PixelAPI
|
api *pixelapi.PixelAPI // Shared instance, only used for unauthenticated requests
|
||||||
templates *templates.TemplateManager
|
templates *templates.TemplateManager
|
||||||
staticResourceDir string
|
staticResourceDir string
|
||||||
}
|
}
|
||||||
@@ -22,7 +25,7 @@ func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebCon
|
|||||||
conf: conf,
|
conf: conf,
|
||||||
staticResourceDir: conf.StaticResourceDir,
|
staticResourceDir: conf.StaticResourceDir,
|
||||||
}
|
}
|
||||||
wc.api = pixelapi.New(conf.APIURLInternal)
|
wc.api = pixelapi.New(conf.APIURLInternal, "")
|
||||||
wc.templates = templates.New(
|
wc.templates = templates.New(
|
||||||
conf.TemplateDir,
|
conf.TemplateDir,
|
||||||
conf.APIURLExternal,
|
conf.APIURLExternal,
|
||||||
@@ -45,6 +48,8 @@ func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebCon
|
|||||||
|
|
||||||
r.GET(prefix+"/register" /* */, wc.serveTemplate("register"))
|
r.GET(prefix+"/register" /* */, wc.serveTemplate("register"))
|
||||||
r.GET(prefix+"/login" /* */, wc.serveTemplate("login"))
|
r.GET(prefix+"/login" /* */, wc.serveTemplate("login"))
|
||||||
|
r.GET(prefix+"/logout" /* */, wc.serveTemplate("logout"))
|
||||||
|
r.POST(prefix+"/logout" /* */, wc.serveLogout)
|
||||||
|
|
||||||
r.NotFound = http.HandlerFunc(wc.serveNotFound)
|
r.NotFound = http.HandlerFunc(wc.serveNotFound)
|
||||||
|
|
||||||
@@ -61,7 +66,7 @@ func (wc *WebController) serveTemplate(tpl string) httprouter.Handle {
|
|||||||
r *http.Request,
|
r *http.Request,
|
||||||
p httprouter.Params,
|
p httprouter.Params,
|
||||||
) {
|
) {
|
||||||
err := wc.templates.Get().ExecuteTemplate(w, tpl, wc.newTemplateData(r))
|
err := wc.templates.Get().ExecuteTemplate(w, tpl, wc.newTemplateData(w, r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error executing template '%s': %s", tpl, err)
|
log.Error("Error executing template '%s': %s", tpl, err)
|
||||||
}
|
}
|
||||||
@@ -80,5 +85,14 @@ func (wc *WebController) serveFile(path string) httprouter.Handle {
|
|||||||
|
|
||||||
func (wc *WebController) serveNotFound(w http.ResponseWriter, r *http.Request) {
|
func (wc *WebController) serveNotFound(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debug("Not Found: %s", r.URL)
|
log.Debug("Not Found: %s", r.URL)
|
||||||
wc.templates.Get().ExecuteTemplate(w, "error", wc.newTemplateData(r))
|
wc.templates.Get().ExecuteTemplate(w, "error", wc.newTemplateData(w, r))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WebController) getAPIKey(r *http.Request) (key string, err error) {
|
||||||
|
if cookie, err := r.Cookie("pd_auth_key"); err == nil {
|
||||||
|
if _, err := uuid.Parse(cookie.Value); err == nil {
|
||||||
|
return cookie.Value, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", errors.New("not a valid pixeldrain authentication cookie")
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user