add login/register forms. Restructure pixelapi

This commit is contained in:
2018-06-20 23:47:47 +02:00
parent 75197310bf
commit ffa9fb3395
18 changed files with 292 additions and 228 deletions

View File

@@ -1,10 +1,7 @@
package pixelapi package pixelapi
import ( import (
"encoding/json"
"io" "io"
"github.com/Fornaxian/log"
) )
// 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
@@ -29,18 +26,11 @@ 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) *FileInfo { func (p *PixelAPI) GetFileInfo(id string) (resp *FileInfo, err *Error) {
body, err := getString(p.apiEndpoint + "/file/" + id + "/info") resp = &FileInfo{}
err = getJSON(p.apiEndpoint+"/file/"+id+"/info", resp)
if err != nil { if err != nil {
log.Error("req failed: %v", err) return nil, err
return nil
} }
var fileInfo FileInfo return resp, nil
err = json.Unmarshal([]byte(body), &fileInfo)
if err != nil {
log.Error("unmarshal failed: %v. json: %s", err, body)
return nil
}
return &fileInfo
} }

View File

@@ -1,9 +1,5 @@
package pixelapi package pixelapi
import (
"encoding/json"
)
// API error constants // API error constants
const ( const (
ListNotFoundError = "list_not_found" ListNotFoundError = "list_not_found"
@@ -11,7 +7,6 @@ const (
// List information object from the pixeldrain API // List information object from the pixeldrain API
type List struct { type List struct {
Error *ErrorResponse
Success bool `json:"success"` Success bool `json:"success"`
ID string `json:"id"` ID string `json:"id"`
Title string `json:"title"` Title string `json:"title"`
@@ -32,22 +27,11 @@ type ListFile struct {
// GetList get a List from the pixeldrain API. Errors will be available through // GetList get a List from the pixeldrain API. Errors will be available through
// List.Error. Standard error checks apply. // List.Error. Standard error checks apply.
func (p *PixelAPI) GetList(id string) *List { func (p *PixelAPI) GetList(id string) (resp *List, err *Error) {
var list = &List{} resp = &List{}
body, err := getString(p.apiEndpoint + "/list/" + id) err = getJSON(p.apiEndpoint+"/list/"+id, resp)
if err != nil { if err != nil {
list.Error = errorResponseFromError(err) return nil, err
return list
} }
return resp, nil
err = json.Unmarshal([]byte(body), list)
if err != nil {
list.Error = errorResponseFromError(err)
return list
}
if !list.Success {
list.Error = errorResponseFromJSON(body)
}
return list
} }

13
pixelapi/misc.go Normal file
View File

@@ -0,0 +1,13 @@
package pixelapi
type Recaptcha struct {
SiteKey string `json:"site_key"`
}
func (p *PixelAPI) GetRecaptcha() (resp *Recaptcha, err *Error) {
err = getJSON(p.apiEndpoint+"/misc/recpatcha", resp)
if err != nil {
return nil, err
}
return resp, nil
}

View File

@@ -1,9 +1,141 @@
package pixelapi package pixelapi
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
"github.com/Fornaxian/log"
)
// PixelAPI is the Pixeldrain API client
type PixelAPI struct { type PixelAPI struct {
apiEndpoint string apiEndpoint string
} }
// New creates a new Pixeldrain API client to query the Pixeldrain API with
func New(apiEndpoint string) *PixelAPI { func New(apiEndpoint string) *PixelAPI {
return &PixelAPI{apiEndpoint} return &PixelAPI{apiEndpoint}
} }
type Error struct {
ReqError bool
Success bool `json:"success"`
Value string `json:"value"`
Message string `json:"message"`
}
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 {
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()
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
}
func getString(url string) (string, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
return string(bodyBytes), err
}
func getRaw(url string) (io.ReadCloser, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
return resp.Body, err
}

View File

@@ -1,70 +0,0 @@
package pixelapi
import (
"encoding/json"
"io"
"io/ioutil"
"net/http"
)
type ErrorResponse struct {
ReqError bool
Success bool `json:"success"`
Value string `json:"value"`
Message *string `json:"message"`
ID *string `json:"id"`
}
func errorResponseFromJSON(j string) *ErrorResponse {
var r = &ErrorResponse{}
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) *ErrorResponse {
var r = &ErrorResponse{}
r.Success = false
r.ReqError = true
r.Value = e.Error()
return r
}
func getString(url string) (string, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return "", err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
return string(bodyBytes), err
}
func getRaw(url string) (io.ReadCloser, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
return resp.Body, err
}

View File

@@ -1,4 +1,4 @@
/* /*
Created on : Jun 3, 2015, 9:33:11 AM Created on : Jun 3, 2015, 9:33:11 AM
Author : Fornax Author : Fornax
*/ */
@@ -72,7 +72,7 @@ html{
margin: 0 4px; margin: 0 4px;
text-decoration: none; text-decoration: none;
font-family: "Lato", sans-serif; font-family: "Lato", sans-serif;
font-weight: bold; font-weight: bold;
font-size: 26px; font-size: 26px;
} }
.navigation a:hover { .navigation a:hover {
@@ -123,8 +123,8 @@ html{
.highlight_middle {background-color: #3a3a3a;} .highlight_middle {background-color: #3a3a3a;}
.highlight_dark {background-color: #303030;} .highlight_dark {background-color: #303030;}
.border-top {border-top: #686868 1px solid;} .border_top {border-top: #686868 1px solid;}
.border-bottom {border-bottom: #686868 1px solid;} .border_bottom {border-bottom: #686868 1px solid;}
/* Common elements */ /* Common elements */
@@ -241,9 +241,13 @@ a:hover{
/* Form fields */ /* Form fields */
.form_input {
width: 100%;
}
/* BUTTONS */ /* BUTTONS */
button, button,
input[type="submit"], input[type="submit"],
input[type="button"], input[type="button"],
input[type="color"], input[type="color"],
select{ select{
@@ -260,19 +264,19 @@ select{
cursor: pointer; cursor: pointer;
} }
button:hover, button:hover,
input[type="submit"]:hover, input[type="submit"]:hover,
input[type="button"]:hover, input[type="button"]:hover,
input[type="color"]:hover, input[type="color"]:hover,
select:hover, select:hover,
button:focus, button:focus,
input[type="submit"]:focus, input[type="submit"]:focus,
input[type="button"]:focus, input[type="button"]:focus,
input[type="color"]:focus, input[type="color"]:focus,
select:focus{ select:focus{
box-shadow: var(--highlight_border), 2px 2px 8px #000000; box-shadow: var(--highlight_border), 2px 2px 8px #000000;
} }
button:active, button:active,
input[type="submit"]:active, input[type="submit"]:active,
input[type="button"]:active, input[type="button"]:active,
input[type="color"]:active, input[type="color"]:active,
select:active{ select:active{
@@ -281,10 +285,10 @@ select:active{
padding: 8px 8px 4px 12px; padding: 8px 8px 4px 12px;
} }
.button_full_width {width: calc(100% - 4px);} .button_full_width {width: calc(100% - 4px);}
.button_highlight {background: linear-gradient(var(--highlight_color), var(--highlight_color_dark));} .button_highlight {background: linear-gradient(var(--highlight_color), var(--highlight_color_dark)) !important; color: #000000 !important;}
.button_highlight:active{background: linear-gradient(var(--highlight_color_dark), var(--highlight_color));} .button_highlight:active{background: linear-gradient(var(--highlight_color_dark), var(--highlight_color)) !important; color: #000000 !important;}
.button_red {background: linear-gradient(#821C40, #61152F);} .button_red {background: linear-gradient(#821C40, #61152F) !important;}
.button_red:active {background: linear-gradient(#61152F, #821C40);} .button_red:active {background: linear-gradient(#61152F, #821C40) !important;}
/* Dropdown list of the select tag */ /* Dropdown list of the select tag */
option{ option{

View File

@@ -1,24 +1,22 @@
{{define "login"}}
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<head> <head>
<title>Login ~ PixelDrain</title> <title>Login ~ 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="/res/style/home.css"/> <link rel="stylesheet" href="/global.css"/>
<link rel="stylesheet" href="/res/style/season.css"/> <link rel="stylesheet" href="/res/style/layout.css"/>
<link rel="stylesheet" href="/res/style/form.css"/>
<link rel="stylesheet" href="/res/style/menu.css"/>
<link href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/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 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="shortcut icon" href="/res/img/tray32.png"/>
<meta name="theme-color" content="#9FCF6C"/> <meta name="theme-color" content="#9FCF6C"/>
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/> <link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/>
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/> <link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/>
{{template "bgpattern"}}
<style th:include="fragments :: background-pattern" th:inline="text"></style>
<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.
Uncensored, unmonitored and unmoderated."/> Uncensored, unmonitored and unmoderated."/>
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
@@ -32,49 +30,30 @@
<body> <body>
<div id='body' class="body"> <div id='body' class="body">
<div th:replace="fragments :: menu"></div> {{template "menu"}}
<br/><br/>
<h1>Log in to your PixelDrain account</h1>
<div id="message" th:switch="${messageType}"> <form action="/login" method="POST" class="highlight_dark border_top border_bottom">
<div th:case="'info'" th:utext="${message}" id="text-info" class="text-info"></div> <table style="margin-left: auto; margin-right: auto;">
<div th:case="'warn'" th:utext="${message}" id="text-warning" class="text-warning"></div>
</div>
Log in to your PixelDrain account
<form action="/login" method="POST">
<table>
<tr> <tr>
<td>Username</td> <td>Username</td>
<td><input name="username" type="text" value="" th:value="${form_username}"/></td> <td><input name="username" type="text" value=""/></td>
</tr> </tr>
<tr> <tr>
<td>Password</td> <td>Password</td>
<td><input name="password" type="password"/></td> <td><input name="password" type="password"/></td>
</tr> </tr>
<tr>
<td colspan=2 style="text-align: right;"><input type="submit" value="Login"/></td>
</tr>
</table> </table>
<input type="submit" value="Login"/>
</form> </form>
<br/><br/> <br/>
If you don't have a PixelDrain account, you can <a href="/register">register here</a>. If you don't have a PixelDrain account, you can <a href="/register">register here</a>. No e-mail address required.<br/>
{{template "footer"}}
</div> </div>
<!-- Google Analytics Tracking Code --> {{template "analytics"}}
<script>
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-24463738-4', 'auto');
ga('send', 'pageview');
</script>
</body> </body>
</html> </html>
{{end}}

View File

@@ -1,26 +1,22 @@
{{define "register"}}
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <html xmlns:th="http://www.thymeleaf.org">
<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="/res/style/home.css"/> <link rel="stylesheet" href="/global.css"/>
<link rel="stylesheet" href="/res/style/season.css"/> <link rel="stylesheet" href="/res/style/layout.css"/>
<link rel="stylesheet" href="/res/style/form.css"/>
<link rel="stylesheet" href="/res/style/menu.css"/>
<link href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/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 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="shortcut icon" href="/res/img/tray32.png"/>
<meta name="theme-color" content="#9FCF6C"/> <meta name="theme-color" content="#9FCF6C"/>
<link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/> <link rel="icon" sizes="180x180" href="/res/img/pixeldrain.png"/>
<link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/> <link rel="icon" sizes="256x256" href="/res/img/pixeldrain_big.png"/>
{{template "bgpattern"}}
<style th:include="fragments :: background-pattern" th:inline="text"></style>
<script src='https://www.google.com/recaptcha/api.js'></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. PixelDrain also supports previews for images, videos, audio, PDFs and much more.
Uncensored, unmonitored and unmoderated."/> Uncensored, unmonitored and unmoderated."/>
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
@@ -30,53 +26,39 @@
<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 src="https://www.google.com/recaptcha/api.js"></script>
</head> </head>
<body> <body>
<div id='body' class="body"> <div id='body' class="body">
<div th:replace="fragments :: menu"></div> {{template "menu"}}
<br/>
<h3>Register a new PixelDrain account</h3> <h1>Register a new Pixeldrain account</h1>
<div id="message" th:switch="${messageType}"> <form action="/login" method="POST" class="highlight_dark border_top border_bottom">
<div th:case="'info'" th:utext="${message}" id="text-info" class="text-info"></div> <table style="margin-left: auto; margin-right: auto; text-align: left; max-width: 30em;">
<div th:case="'warn'" th:utext="${message}" id="text-warning" class="text-warning"></div> <tr><td>Username (Used to log in)</td></tr>
</div> <tr><td><input name="username" type="text" class="form_input"/></td></tr>
<form action="/register" method="POST"> <tr><td>
Enter your password twice:<br/>
(So we can verify that you have not made any typing errors)
Username (Used to log in)<br/> </td></tr>
<input name="username" type="text" th:value="${username}"/><br/> <tr><td><input name="password1" type="password" class="form_input"/></td></tr>
<br/> <tr><td><input name="password2" type="password" class="form_input"/></td></tr>
Enter your password twice (Why twice? So we can verify that you have not made any typing errors)<br/> <tr><td>Prove that you're not a robot (Click the white box)</td></tr>
<input name="password1" type="password" th:value="${password1}"/><br/> <tr><td style="text-align: center;">
<input name="password2" type="password" th:value="${password2}"/><br/> <div class="g-recaptcha" data-theme="dark" data-sitekey="6LdEeQ0TAAAAALBmDF_k_2LgbpuJM66PGspByViS"></div>
<br/> </td></tr>
Prove that you're not a robot (Click the white box) </tr>
<div class="g-recaptcha" data-theme="dark" <tr><td colspan=2 style="text-align: right;"><input type="submit" value="Register" class="button_highlight"/></td></tr>
data-sitekey="6LdEeQ0TAAAAALBmDF_k_2LgbpuJM66PGspByViS"> </table>
</div><br/>
<br/>
<input type="submit" value="Register"/>
</form> </form>
<br/>
Welcome to the club!<br/>
{{template "footer"}}
</div> </div>
<!-- Google Analytics Tracking Code --> {{template "analytics"}}
<script>
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', 'UA-24463738-4', 'auto');
ga('send', 'pageview');
</script>
</body> </body>
</html> </html>
{{end}}

View File

@@ -1,6 +1,6 @@
{{define "footer"}} {{define "footer"}}
<br/> <br/>
<div class="highlight_dark border-top border-bottom"> <div class="highlight_dark border_top border_bottom">
Pixeldrain is a product by <a href="//fornaxian.com" target="_blank">Fornaxian Technologies</a>. Pixeldrain is a product by <a href="//fornaxian.com" target="_blank">Fornaxian Technologies</a>.
</div> </div>
{{end}} {{end}}

View File

@@ -1,8 +1,9 @@
{{define "menu"}} {{define "menu"}}
<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&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="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() {
@@ -15,4 +16,4 @@
} }
</script> </script>
</div> </div>
{{end}} {{end}}

View File

@@ -36,14 +36,14 @@
<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>
<button id="text_button" class="big_button button_highlight" onClick="window.location.href = '/t/'">Upload Text</button><br/> <button id="text_button" class="big_button button_highlight" onClick="window.location.href = '/t/'">Upload Text</button><br/>
<div id="uploads_queue" class="uploads_queue"></div> <div id="uploads_queue" class="uploads_queue"></div>
</div> </div>
<div class="highlight_dark border-bottom"> <div class="highlight_dark border_bottom">
<button id="btn_create_list">Create list with uploaded files</button> <button id="btn_create_list">Create list with uploaded files</button>
</div> </div>

View File

@@ -24,8 +24,8 @@ func (wc *WebController) serveFilePreview(w http.ResponseWriter, r *http.Request
return return
} }
inf := wc.api.GetFileInfo(p.ByName("id")) // TODO: Error handling inf, err := wc.api.GetFileInfo(p.ByName("id")) // TODO: Error handling
if inf == nil { if err != nil {
wc.serveNotFound(w, r) wc.serveNotFound(w, r)
return return
} }

View File

@@ -28,8 +28,8 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
var finfo []*pixelapi.FileInfo var finfo []*pixelapi.FileInfo
for _, id := range ids { for _, id := range ids {
inf := wc.api.GetFileInfo(id) inf, err := wc.api.GetFileInfo(id)
if inf == nil { if err != nil {
continue continue
} }
finfo = append(finfo, inf) finfo = append(finfo, inf)

View File

@@ -10,10 +10,10 @@ import (
// ServeListViewer controller for GET /l/:id // ServeListViewer controller for GET /l/:id
func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) { func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
var list = wc.api.GetList(p.ByName("id")) var list, aerr = wc.api.GetList(p.ByName("id"))
if list.Error != nil { if aerr != nil {
if list.Error.ReqError { if aerr.ReqError {
log.Error("API request error occurred: %s", list.Error.Value) log.Error("API request error occurred: %s", aerr.Value)
} }
wc.serveNotFound(w, r) wc.serveNotFound(w, r)
return return

View File

@@ -0,0 +1,25 @@
package webcontroller
import (
"net/http"
)
// TemplateData is a struct that every template expects when being rendered. In
// the field Other you can pass your own template-specific variables.
type TemplateData struct {
Authenticated bool
Username string
Recaptcha struct {
Enabled bool
PubKey string
}
Other interface{}
}
func (wc *WebController) newTemplateData(r http.Request) *TemplateData {
var t = &TemplateData{}
return t
}

View File

@@ -26,8 +26,9 @@ func New(templateDir, externalAPIEndpoint string, debugMode bool) *TemplateManag
} }
// ParseTemplates parses the templates in the template directory which is // ParseTemplates parses the templates in the template directory which is
// defined in the config file // defined in the config file.
func (tm *TemplateManager) ParseTemplates() { // If silent is false it will print an info log message for every template found
func (tm *TemplateManager) ParseTemplates(silent bool) {
var templatePaths []string var templatePaths []string
filepath.Walk(tm.templateDir, func(path string, f os.FileInfo, err error) error { filepath.Walk(tm.templateDir, func(path string, f os.FileInfo, err error) error {
@@ -35,7 +36,9 @@ func (tm *TemplateManager) ParseTemplates() {
return nil return nil
} }
templatePaths = append(templatePaths, path) templatePaths = append(templatePaths, path)
log.Info("Template found: %s", path) if !silent {
log.Info("Template found: %s", path)
}
return nil return nil
}) })
@@ -57,5 +60,8 @@ func (tm *TemplateManager) ParseTemplates() {
// Get returns the templates, so they can be used to render views // Get returns the templates, so they can be used to render views
func (tm *TemplateManager) Get() *template.Template { func (tm *TemplateManager) Get() *template.Template {
if tm.debugModeEnabled {
tm.ParseTemplates(true)
}
return tm.templates return tm.templates
} }

View File

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

View File

@@ -28,7 +28,7 @@ func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebCon
conf.APIURLExternal, conf.APIURLExternal,
conf.DebugMode, conf.DebugMode,
) )
wc.templates.ParseTemplates() wc.templates.ParseTemplates(false)
// Serve static files // Serve static files
r.ServeFiles(prefix+"/res/*filepath", http.Dir(wc.staticResourceDir+"/res")) r.ServeFiles(prefix+"/res/*filepath", http.Dir(wc.staticResourceDir+"/res"))
@@ -43,13 +43,16 @@ func New(r *httprouter.Router, prefix string, conf *conf.PixelWebConfig) *WebCon
r.GET(prefix+"/l/:id" /* */, wc.serveListViewer) r.GET(prefix+"/l/:id" /* */, wc.serveListViewer)
r.GET(prefix+"/t" /* */, wc.serveTemplate("paste")) r.GET(prefix+"/t" /* */, wc.serveTemplate("paste"))
r.GET(prefix+"/register" /* */, wc.serveTemplate("register"))
r.GET(prefix+"/login" /* */, wc.serveTemplate("login"))
r.NotFound = http.HandlerFunc(wc.serveNotFound) r.NotFound = http.HandlerFunc(wc.serveNotFound)
return wc return wc
} }
func (wc *WebController) ReloadTemplates() { func (wc *WebController) ReloadTemplates() {
wc.templates.ParseTemplates() wc.templates.ParseTemplates(false)
} }
func (wc *WebController) serveTemplate(tpl string) httprouter.Handle { func (wc *WebController) serveTemplate(tpl string) httprouter.Handle {