work on registration form

This commit is contained in:
2018-06-21 23:41:50 +02:00
parent ffa9fb3395
commit 39404caa6e
12 changed files with 193 additions and 100 deletions

View File

@@ -5,6 +5,8 @@ import (
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/Fornaxian/log"
)
@@ -19,6 +21,13 @@ func New(apiEndpoint string) *PixelAPI {
return &PixelAPI{apiEndpoint}
}
// Error is either an error that occurred during the API request
// (ReqError = true), or an error that was returned from the Pixeldrain API
// (ReqError = false). The Success field is also returned by the Pixeldrain API,
// but since this is struct represents an Error it will usually be false.
//
// When ReqError is true the Value field will contain a Go error message. When
// it's false it will contain a Pixeldrain API error code.
type Error struct {
ReqError bool
Success bool `json:"success"`
@@ -28,24 +37,6 @@ type Error struct {
func (e Error) Error() string { return e.Value }
func errorResponseFromJSON(j string) *Error {
var r = &Error{}
var err = json.Unmarshal([]byte(j), r)
if err != nil {
r.Success = false
r.ReqError = true
r.Value = err.Error()
}
return r
}
func errorResponseFromError(e error) *Error {
var r = &Error{}
r.Success = false
r.ReqError = true
r.Value = e.Error()
return r
}
func getJSON(url string, target interface{}) *Error {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
@@ -58,7 +49,6 @@ func getJSON(url string, target interface{}) *Error {
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return &Error{
@@ -70,38 +60,7 @@ func getJSON(url string, target interface{}) *Error {
}
defer resp.Body.Close()
var jdec = json.NewDecoder(resp.Body)
// Test for client side and server side errors
if resp.StatusCode >= 400 {
var errResp = &Error{
ReqError: false,
}
err = jdec.Decode(&errResp)
if err != nil {
log.Error("Can't decode this: %v", err)
return &Error{
ReqError: true,
Success: false,
Value: err.Error(),
Message: err.Error(),
}
}
return errResp
}
err = jdec.Decode(target)
if err != nil {
r, _ := ioutil.ReadAll(resp.Body)
log.Error("Can't decode this: %v. %s", err, r)
return &Error{
ReqError: true,
Success: false,
Value: err.Error(),
Message: err.Error(),
}
}
return nil
return parseJSONResponse(resp, target)
}
func getString(url string) (string, error) {
@@ -139,3 +98,65 @@ func getRaw(url string) (io.ReadCloser, error) {
return resp.Body, err
}
func postForm(url string, vals url.Values, target interface{}) *Error {
req, err := http.NewRequest("POST", url, strings.NewReader(vals.Encode()))
if err != nil {
return &Error{
ReqError: true,
Success: false,
Value: err.Error(),
Message: err.Error(),
}
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return &Error{
ReqError: true,
Success: false,
Value: err.Error(),
Message: err.Error(),
}
}
defer resp.Body.Close()
return parseJSONResponse(resp, target)
}
func parseJSONResponse(resp *http.Response, target interface{}) *Error {
var jdec = json.NewDecoder(resp.Body)
var err error
// Test for client side and server side errors
if resp.StatusCode >= 400 {
var errResp = &Error{
ReqError: false,
}
err = jdec.Decode(&errResp)
if err != nil {
log.Error("Can't decode this: %v", err)
return &Error{
ReqError: true,
Success: false,
Value: err.Error(),
Message: err.Error(),
}
}
return errResp
}
err = jdec.Decode(target)
if err != nil {
r, _ := ioutil.ReadAll(resp.Body)
log.Error("Can't decode this: %v. %s", err, r)
return &Error{
ReqError: true,
Success: false,
Value: err.Error(),
Message: err.Error(),
}
}
return nil
}

35
pixelapi/user.go Normal file
View File

@@ -0,0 +1,35 @@
package pixelapi
import (
"net/url"
)
type Registration struct {
Success bool `json:"success"`
Message string `json:"message,omitempty"`
Errors []RegistrationError `json:"errors,omitempty"`
}
type RegistrationError struct {
Code string `json:"error_code"`
Message string `json:"message"`
}
// UserRegister registers a new user on the Pixeldrain server. username and
// password are always required. email is optional, but without it you will
// never be able to reset your password in case you forget it. captcha depends
// on whether reCaptcha is enabled on the Pixeldrain server, this can be checked
// through the GetRecaptcha function.
func (p *PixelAPI) UserRegister(username, email, password, captcha string) (resp *Registration, err *Error) {
resp = &Registration{}
var form = url.Values{}
form.Add("username", username)
form.Add("email", email)
form.Add("password", password)
form.Add("recaptcha_response", captcha)
err = postForm(p.apiEndpoint+"/user/register", form, resp)
if err != nil {
return nil, err
}
return resp, nil
}

View File

@@ -30,7 +30,7 @@
<body>
<div id='body' class="body">
{{template "menu"}}
{{template "menu" .}}
<h1>Log in to your PixelDrain account</h1>
<form action="/login" method="POST" class="highlight_dark border_top border_bottom">

View File

@@ -28,28 +28,39 @@
<meta property="og:image:type" content="image/png" />
<script src="https://www.google.com/recaptcha/api.js"></script>
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
</head>
<body>
<div id='body' class="body">
{{template "menu"}}
{{template "menu" .}}
<h1>Register a new Pixeldrain account</h1>
<form action="/login" method="POST" 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;">
<tr><td>Username (Used to log in)</td></tr>
<tr><td><input name="username" type="text" class="form_input"/></td></tr>
<tr><td><input id="register_username" type="text" autocomplete="username" class="form_input"/></td></tr>
<tr><td>used for logging into your account</td></tr>
<tr><td><hr/></td></tr>
<tr><td>E-mail address (optional):</td></tr>
<tr><td><input id="register_email" type="text" autocomplete="email" class="form_input"/></td></tr>
<tr><td>
your e-mail address will only be used for password
resets and important account notifications.
</td></tr>
<tr><td><hr/></td></tr>
<tr><td>
Enter your password twice:<br/>
(So we can verify that you have not made any typing errors)
(so we can verify that you have not made any typing errors)
</td></tr>
<tr><td><input name="password1" type="password" class="form_input"/></td></tr>
<tr><td><input name="password2" type="password" class="form_input"/></td></tr>
<tr><td><input id="register_password1" type="password" autocomplete="new-password" class="form_input"/></td></tr>
<tr><td><input id="register_password2" type="password" autocomplete="new-password" class="form_input"/></td></tr>
<tr><td><hr/></td></tr>
<tr><td>Prove that you're not a robot (Click the white box)</td></tr>
<tr><td style="text-align: center;">
<div class="g-recaptcha" data-theme="dark" data-sitekey="6LdEeQ0TAAAAALBmDF_k_2LgbpuJM66PGspByViS"></div>
</td></tr>
</tr>
<tr><td><hr/></td></tr>
<tr><td colspan=2 style="text-align: right;"><input type="submit" value="Register" class="button_highlight"/></td></tr>
</table>
</form>
@@ -58,6 +69,40 @@
{{template "footer"}}
</div>
<script type="text/javascript">
function submitForm(){
var uname = document.getElementById("register_username").value;
var email = document.getElementById("register_email").value;
var passwd1 = document.getElementById("register_password1").value;
var passwd2 = document.getElementById("register_password2").value;
var capt = grecaptcha.getResponse();
if (passwd1 !== passwd2) {
alert("Passwords do not match! Good thing we checked.");
return false;
}
var req = new XMLHttpRequest();
req.onreadystatechange = function(){
if (this.readyState === 4) {
var response = JSON.parse(req.responseText);
console.log(response);
}
}
req.open("POST", apiEndpoint+"/user/register", true);
var data = new FormData();
data.append("username", uname);
data.append("email", email);
data.append("password", passwd1);
data.append("recaptcha_response", capt);
req.send(data);
return false;
}
</script>
{{template "analytics"}}
</body>
</html>

View File

@@ -14,11 +14,11 @@
<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.
<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" />
@@ -32,14 +32,14 @@
<body>
<div id='body' class="body">
{{template "menu"}}
{{template "menu" .}}
<h1>PixelDrain API Documentation</h1>
<p>
Welcome to the Pixeldrain API documentation.
<br/>
The methods for uploading and retrieving files don't require an
API key. The methods for creating and retrieving lists also
don't require an API key. All methods which delete or modify a
The methods for uploading and retrieving files don't require an
API key. The methods for creating and retrieving lists also
don't require an API key. All methods which delete or modify a
resource <strong>do</strong> require an API key.
<br/>
<br/>
@@ -58,7 +58,7 @@
The base URL for the API is "{{apiUrl}}", all paths below are
relative to that URL.
</p>
<h2>File Methods</h2>
{{template "api-file-post"}}
{{template "api-file-id-get"}}
@@ -66,7 +66,7 @@
{{template "api-file-id-info-get"}}
{{template "api-file-id-thumbnail-get"}}
{{template "api-file-id-delete"}}
<h2>List Methods</h2>
{{template "api-list-post"}}
{{template "api-list-get"}}
@@ -76,4 +76,4 @@
{{template "analytics"}}
</body>
</html>
{{end}}
{{end}}

View File

@@ -13,7 +13,7 @@
<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."/>
@@ -28,7 +28,7 @@
<body>
<div id='body' class="body">
{{template "menu"}}
{{template "menu" .}}
<br/>
<h1>Some Error occured</h1>
Either you made a mistake, or I made a mistake.
@@ -42,4 +42,4 @@
{{template "analytics"}}
</body>
</html>
{{end}}
{{end}}

View File

@@ -3,7 +3,7 @@
<a href="/">Home</a>
<a href="/history">My&nbsp;Files</a>
<a href="/api">API&nbsp;Documentation</a>
<a href="/user">Account</a>
<a href="/user">{{if .Authenticated}}{{.Username}}{{else}}Account{{end}}</a>
<a href="javascript:void(0);" class="icon" onclick="expandNavigation()">&#9776;</a>
<script>
function expandNavigation() {

View File

@@ -13,17 +13,17 @@
<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"}}
<script src="res/script/jquery.js"></script>
<script src="res/script/jquery-cookie.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>var APIURL = "{{apiUrl}}";</script>
<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.
<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" />
@@ -37,12 +37,12 @@
<body>
<div id='body' class="body">
{{template "menu"}}
{{template "menu" .}}
<br/>
Here are all files you have previously uploaded to PixelDrain using this computer.
This data is saved locally in your web browser and gets updated every time you upload a file through your current browser.
<br/><br/>
<div id="uploadedFiles" class="files_container"></div>
{{template "footer"}}
</div>
@@ -50,4 +50,4 @@
{{template "analytics"}}
</body>
</html>
{{end}}
{{end}}

View File

@@ -35,7 +35,7 @@
<img id="header_image" src="/res/img/header_neuropol.png" alt="Header image"/>
<br/>
<div id="body" class="body">
{{template "menu"}}
{{template "menu" .}}
<div class="highlight_middle border_bottom">
<input id="file_input_field" type="file" name="file" multiple="multiple"/>
<button id="select_file_button" class="big_button button_highlight">Upload Files</button>

View File

@@ -1,6 +1,7 @@
package webcontroller
import (
"html/template"
"net/http"
)
@@ -9,6 +10,7 @@ import (
type TemplateData struct {
Authenticated bool
Username string
APIEndpoint template.URL
Recaptcha struct {
Enabled bool
@@ -18,8 +20,12 @@ type TemplateData struct {
Other interface{}
}
func (wc *WebController) newTemplateData(r http.Request) *TemplateData {
var t = &TemplateData{}
func (wc *WebController) newTemplateData(r *http.Request) *TemplateData {
var t = &TemplateData{
Authenticated: false,
Username: "Fornax",
APIEndpoint: template.URL(wc.conf.APIURLExternal),
}
return t
}

View File

@@ -1,15 +1 @@
package webcontroller
import (
"net/http"
"github.com/julienschmidt/httprouter"
)
func (wc *WebController) handleLogin(
w http.ResponseWriter,
r *http.Request,
p httprouter.Params,
) {
}

View File

@@ -61,7 +61,7 @@ func (wc *WebController) serveTemplate(tpl string) httprouter.Handle {
r *http.Request,
p httprouter.Params,
) {
err := wc.templates.Get().ExecuteTemplate(w, tpl, nil)
err := wc.templates.Get().ExecuteTemplate(w, tpl, wc.newTemplateData(r))
if err != nil {
log.Error("Error executing template '%s': %s", tpl, err)
}
@@ -80,5 +80,5 @@ func (wc *WebController) serveFile(path string) httprouter.Handle {
func (wc *WebController) serveNotFound(w http.ResponseWriter, r *http.Request) {
log.Debug("Not Found: %s", r.URL)
wc.templates.Get().ExecuteTemplate(w, "error", nil)
wc.templates.Get().ExecuteTemplate(w, "error", wc.newTemplateData(r))
}