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"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url"
"strings"
"github.com/Fornaxian/log" "github.com/Fornaxian/log"
) )
@@ -19,6 +21,13 @@ func New(apiEndpoint string) *PixelAPI {
return &PixelAPI{apiEndpoint} 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 { type Error struct {
ReqError bool ReqError bool
Success bool `json:"success"` Success bool `json:"success"`
@@ -28,24 +37,6 @@ type Error struct {
func (e Error) Error() string { return e.Value } 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 { func getJSON(url string, target interface{}) *Error {
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
@@ -58,7 +49,6 @@ func getJSON(url string, target interface{}) *Error {
} }
client := &http.Client{} client := &http.Client{}
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
return &Error{ return &Error{
@@ -70,38 +60,7 @@ func getJSON(url string, target interface{}) *Error {
} }
defer resp.Body.Close() defer resp.Body.Close()
var jdec = json.NewDecoder(resp.Body) return parseJSONResponse(resp, target)
// 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
} }
func getString(url string) (string, error) { func getString(url string) (string, error) {
@@ -139,3 +98,65 @@ 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 {
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> <body>
<div id='body' class="body"> <div id='body' class="body">
{{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"> <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" /> <meta property="og:image:type" content="image/png" />
<script src="https://www.google.com/recaptcha/api.js"></script> <script src="https://www.google.com/recaptcha/api.js"></script>
<script type="text/javascript">var apiEndpoint = '{{.APIEndpoint}}';</script>
</head> </head>
<body> <body>
<div id='body' class="body"> <div id='body' class="body">
{{template "menu"}} {{template "menu" .}}
<h1>Register a new Pixeldrain account</h1> <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;"> <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>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> <tr><td>
Enter your password twice:<br/> 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> </td></tr>
<tr><td><input name="password1" 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 name="password2" type="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>Prove that you're not a robot (Click the white box)</td></tr>
<tr><td style="text-align: center;"> <tr><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>
</tr> <tr><td><hr/></td></tr>
<tr><td colspan=2 style="text-align: right;"><input type="submit" value="Register" class="button_highlight"/></td></tr> <tr><td colspan=2 style="text-align: right;"><input type="submit" value="Register" class="button_highlight"/></td></tr>
</table> </table>
</form> </form>
@@ -58,6 +69,40 @@
{{template "footer"}} {{template "footer"}}
</div> </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"}} {{template "analytics"}}
</body> </body>
</html> </html>

View File

@@ -32,7 +32,7 @@
<body> <body>
<div id='body' class="body"> <div id='body' class="body">
{{template "menu"}} {{template "menu" .}}
<h1>PixelDrain API Documentation</h1> <h1>PixelDrain API Documentation</h1>
<p> <p>
Welcome to the Pixeldrain API documentation. Welcome to the Pixeldrain API documentation.

View File

@@ -28,7 +28,7 @@
<body> <body>
<div id='body' class="body"> <div id='body' class="body">
{{template "menu"}} {{template "menu" .}}
<br/> <br/>
<h1>Some Error occured</h1> <h1>Some Error occured</h1>
Either you made a mistake, or I made a mistake. Either you made a mistake, or I made a mistake.

View File

@@ -3,7 +3,7 @@
<a href="/">Home</a> <a href="/">Home</a>
<a href="/history">My&nbsp;Files</a> <a href="/history">My&nbsp;Files</a>
<a href="/api">API&nbsp;Documentation</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> <a href="javascript:void(0);" class="icon" onclick="expandNavigation()">&#9776;</a>
<script> <script>
function expandNavigation() { function expandNavigation() {

View File

@@ -37,7 +37,7 @@
<body> <body>
<div id='body' class="body"> <div id='body' class="body">
{{template "menu"}} {{template "menu" .}}
<br/> <br/>
Here are all files you have previously uploaded to PixelDrain using this computer. 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. This data is saved locally in your web browser and gets updated every time you upload a file through your current browser.

View File

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

View File

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

View File

@@ -1,15 +1 @@
package webcontroller 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, r *http.Request,
p httprouter.Params, p httprouter.Params,
) { ) {
err := wc.templates.Get().ExecuteTemplate(w, tpl, nil) err := wc.templates.Get().ExecuteTemplate(w, tpl, wc.newTemplateData(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 +80,5 @@ 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", nil) wc.templates.Get().ExecuteTemplate(w, "error", wc.newTemplateData(r))
} }