Added the ability to upload and use avatars.
This commit is contained in:
parent
7a1a468f93
commit
9bafab7a12
|
@ -33,7 +33,7 @@ Set the password column of your user account in the database to what you want yo
|
||||||
|
|
||||||
# Run the program
|
# Run the program
|
||||||
|
|
||||||
go run errors.go main.go pages.go post.go routes.go topic.go user.go utils.go config.go
|
go run errors.go main.go pages.go reply.go routes.go topic.go user.go utils.go config.go
|
||||||
|
|
||||||
Alternatively, you could run the run.bat batch file on Windows.
|
Alternatively, you could run the run.bat batch file on Windows.
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@ More moderation features.
|
||||||
|
|
||||||
Fix the bug where errors are sent off in raw HTML rather than formatted HTML.
|
Fix the bug where errors are sent off in raw HTML rather than formatted HTML.
|
||||||
|
|
||||||
|
Fix the custom pages.
|
||||||
|
|
||||||
|
Add emails as a requirement for registration and add a simple anti-spam measure.
|
||||||
|
|
||||||
Add an alert system.
|
Add an alert system.
|
||||||
|
|
||||||
Add a report feature.
|
Add a report feature.
|
||||||
|
|
|
@ -6,3 +6,6 @@ var dbuser = "root"
|
||||||
var dbpassword = "password"
|
var dbpassword = "password"
|
||||||
var dbname = "grosolo"
|
var dbname = "grosolo"
|
||||||
var dbport = "3306" // You probably won't need to change this
|
var dbport = "3306" // You probably won't need to change this
|
||||||
|
|
||||||
|
// Limiters
|
||||||
|
var max_request_size = 5 * megabyte
|
|
@ -10,6 +10,7 @@ CREATE TABLE `users`(
|
||||||
`createdAt` datetime not null,
|
`createdAt` datetime not null,
|
||||||
`lastActiveAt` datetime not null,
|
`lastActiveAt` datetime not null,
|
||||||
`session` varchar(200) DEFAULT '',
|
`session` varchar(200) DEFAULT '',
|
||||||
|
`avatar` varchar(20) DEFAULT '',
|
||||||
primary key(`uid`)
|
primary key(`uid`)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
21
src/main.go
21
src/main.go
|
@ -13,6 +13,8 @@ const hour int = 60 * 60
|
||||||
const day int = hour * 24
|
const day int = hour * 24
|
||||||
const month int = day * 30
|
const month int = day * 30
|
||||||
const year int = day * 365
|
const year int = day * 365
|
||||||
|
const kilobyte int = 1024
|
||||||
|
const megabyte int = 1024 * 1024
|
||||||
const saltLength int = 32
|
const saltLength int = 32
|
||||||
const sessionLength int = 80
|
const sessionLength int = 80
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
|
@ -27,6 +29,7 @@ var update_session_stmt *sql.Stmt
|
||||||
var logout_stmt *sql.Stmt
|
var logout_stmt *sql.Stmt
|
||||||
var set_password_stmt *sql.Stmt
|
var set_password_stmt *sql.Stmt
|
||||||
var get_password_stmt *sql.Stmt
|
var get_password_stmt *sql.Stmt
|
||||||
|
var set_avatar_stmt *sql.Stmt
|
||||||
var register_stmt *sql.Stmt
|
var register_stmt *sql.Stmt
|
||||||
var username_exists_stmt *sql.Stmt
|
var username_exists_stmt *sql.Stmt
|
||||||
var custom_pages map[string]string = make(map[string]string)
|
var custom_pages map[string]string = make(map[string]string)
|
||||||
|
@ -48,7 +51,7 @@ func init_database(err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Print("Preparing get_session statement.")
|
log.Print("Preparing get_session statement.")
|
||||||
get_session_stmt, err = db.Prepare("SELECT `uid`, `name`, `group`, `is_super_admin`, `session` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''")
|
get_session_stmt, err = db.Prepare("SELECT `uid`, `name`, `group`, `is_super_admin`, `session`, `avatar` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -113,6 +116,12 @@ func init_database(err error) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing set_avatar statement.")
|
||||||
|
set_avatar_stmt, err = db.Prepare("UPDATE users SET avatar = ? WHERE uid = ?")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Add an admin version of register_stmt with more flexibility
|
// Add an admin version of register_stmt with more flexibility
|
||||||
// create_account_stmt, err = db.Prepare("INSERT INTO
|
// create_account_stmt, err = db.Prepare("INSERT INTO
|
||||||
|
|
||||||
|
@ -122,7 +131,7 @@ func init_database(err error) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Print("Preparing get_session statement.")
|
log.Print("Preparing username_exists statement.")
|
||||||
username_exists_stmt, err = db.Prepare("SELECT `name` FROM `users` WHERE `name` = ?")
|
username_exists_stmt, err = db.Prepare("SELECT `name` FROM `users` WHERE `name` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -140,8 +149,10 @@ func main(){
|
||||||
}
|
}
|
||||||
|
|
||||||
// In a directory to stop it clashing with the other paths
|
// In a directory to stop it clashing with the other paths
|
||||||
fs := http.FileServer(http.Dir("./public"))
|
fs_p := http.FileServer(http.Dir("./public"))
|
||||||
http.Handle("/static/", http.StripPrefix("/static/",fs))
|
http.Handle("/static/", http.StripPrefix("/static/",fs_p))
|
||||||
|
fs_u := http.FileServer(http.Dir("./uploads"))
|
||||||
|
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
||||||
|
|
||||||
http.HandleFunc("/overview/", route_overview)
|
http.HandleFunc("/overview/", route_overview)
|
||||||
http.HandleFunc("/topics/create/", route_topic_create)
|
http.HandleFunc("/topics/create/", route_topic_create)
|
||||||
|
@ -170,6 +181,8 @@ func main(){
|
||||||
//http.HandleFunc("/user/edit/", route_logout)
|
//http.HandleFunc("/user/edit/", route_logout)
|
||||||
http.HandleFunc("/user/edit/critical/", route_account_own_edit_critical) // Password & Email
|
http.HandleFunc("/user/edit/critical/", route_account_own_edit_critical) // Password & Email
|
||||||
http.HandleFunc("/user/edit/critical/submit/", route_account_own_edit_critical_submit)
|
http.HandleFunc("/user/edit/critical/submit/", route_account_own_edit_critical_submit)
|
||||||
|
http.HandleFunc("/user/edit/avatar/", route_account_own_edit_avatar) // Password & Email
|
||||||
|
http.HandleFunc("/user/edit/avatar/submit/", route_account_own_edit_avatar_submit)
|
||||||
//http.HandleFunc("/user/:id/edit/", route_logout)
|
//http.HandleFunc("/user/:id/edit/", route_logout)
|
||||||
//http.HandleFunc("/user/:id/ban/", route_logout)
|
//http.HandleFunc("/user/:id/ban/", route_logout)
|
||||||
http.HandleFunc("/", route_topics)
|
http.HandleFunc("/", route_topics)
|
||||||
|
|
|
@ -59,6 +59,31 @@ li:not(:last-child)
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.colblock_left
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.colblock_right
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
width: 65%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.colblock_left:empty
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.colblock_right:empty
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.rowitem
|
.rowitem
|
||||||
{
|
{
|
||||||
width: 99%;
|
width: 99%;
|
||||||
|
@ -69,29 +94,59 @@ li:not(:last-child)
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rowitem.passive
|
.rowitem.passive
|
||||||
{
|
{
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rowitem:not(:last-child)/*:not(:only-child)*/
|
.rowitem:not(:last-child)/*:not(:only-child)*/
|
||||||
{
|
{
|
||||||
border-bottom: 1px dotted #ccc;
|
border-bottom: 1px dotted #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rowitem a
|
.rowitem a
|
||||||
{
|
{
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rowitem a:hover
|
.rowitem a:hover
|
||||||
{
|
{
|
||||||
color: silver;
|
color: silver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.col_left
|
||||||
|
{
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.col_right
|
||||||
|
{
|
||||||
|
width: 69%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.colitem
|
||||||
|
{
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-top: 17px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.colitem.passive
|
||||||
|
{
|
||||||
|
font-weight: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.colitem a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.colitem a:hover
|
||||||
|
{
|
||||||
|
color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
.formrow
|
.formrow
|
||||||
{
|
{
|
||||||
/*height: 40px;*/
|
/*height: 40px;*/
|
||||||
|
|
|
@ -10,5 +10,6 @@ type Reply struct
|
||||||
CreatedAt string
|
CreatedAt string
|
||||||
LastEdit int
|
LastEdit int
|
||||||
LastEditBy int
|
LastEditBy int
|
||||||
|
Avatar string
|
||||||
|
HasAvatar bool
|
||||||
}
|
}
|
||||||
|
|
130
src/routes.go
130
src/routes.go
|
@ -4,7 +4,11 @@ import "log"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
import "regexp"
|
||||||
|
import "strings"
|
||||||
import "time"
|
import "time"
|
||||||
|
import "io"
|
||||||
|
import "os"
|
||||||
import "net/http"
|
import "net/http"
|
||||||
import "html"
|
import "html"
|
||||||
import "database/sql"
|
import "database/sql"
|
||||||
|
@ -110,6 +114,8 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
||||||
replyCreatedAt string
|
replyCreatedAt string
|
||||||
replyLastEdit int
|
replyLastEdit int
|
||||||
replyLastEditBy int
|
replyLastEditBy int
|
||||||
|
replyAvatar string
|
||||||
|
replyHasAvatar bool
|
||||||
is_closed bool
|
is_closed bool
|
||||||
sticky bool
|
sticky bool
|
||||||
|
|
||||||
|
@ -160,7 +166,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
||||||
|
|
||||||
// Get the replies..
|
// Get the replies..
|
||||||
//rows, err := db.Query("select rid, content, createdBy, createdAt from replies where tid = ?", tid)
|
//rows, err := db.Query("select rid, content, createdBy, createdAt from replies where tid = ?", tid)
|
||||||
rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.name from replies left join users ON replies.createdBy = users.uid where tid = ?", tid)
|
rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name from replies left join users ON replies.createdBy = users.uid where tid = ?", tid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalError(err,w,r,user)
|
InternalError(err,w,r,user)
|
||||||
return
|
return
|
||||||
|
@ -168,12 +174,22 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyCreatedByName)
|
err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalError(err,w,r,user)
|
InternalError(err,w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
replyList[currentID] = Reply{rid,tid,replyContent,replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy}
|
|
||||||
|
if replyAvatar != "" {
|
||||||
|
replyHasAvatar = true
|
||||||
|
if replyAvatar[0] == '.' {
|
||||||
|
replyAvatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + replyAvatar
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
replyHasAvatar = false
|
||||||
|
}
|
||||||
|
|
||||||
|
replyList[currentID] = Reply{rid,tid,replyContent,replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyHasAvatar}
|
||||||
currentID++
|
currentID++
|
||||||
}
|
}
|
||||||
err = rows.Err()
|
err = rows.Err()
|
||||||
|
@ -516,6 +532,114 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque
|
||||||
templates.ExecuteTemplate(w,"account-own-edit-success.html", pi)
|
templates.ExecuteTemplate(w,"account-own-edit-success.html", pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request) {
|
||||||
|
user := SessionCheck(w,r)
|
||||||
|
if !user.Loggedin {
|
||||||
|
errmsg := "You need to login to edit your own account."
|
||||||
|
pi := Page{"Error","error",user,tList,errmsg}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
|
errpage := b.String()
|
||||||
|
http.Error(w,errpage,500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pi := Page{"Edit Avatar","account-own-edit-avatar",user,tList,0}
|
||||||
|
templates.ExecuteTemplate(w,"account-own-edit-avatar.html", pi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.ContentLength > int64(max_request_size) {
|
||||||
|
http.Error(w, "request too large", http.StatusExpectationFailed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
r.Body = http.MaxBytesReader(w, r.Body, int64(max_request_size))
|
||||||
|
|
||||||
|
user := SessionCheck(w,r)
|
||||||
|
if !user.Loggedin {
|
||||||
|
errmsg := "You need to login to edit your own account."
|
||||||
|
pi := Page{"Error","error",user,tList,errmsg}
|
||||||
|
|
||||||
|
var b bytes.Buffer
|
||||||
|
templates.ExecuteTemplate(&b,"error.html", pi)
|
||||||
|
errpage := b.String()
|
||||||
|
http.Error(w,errpage,500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.ParseMultipartForm(int64(max_request_size))
|
||||||
|
if err != nil {
|
||||||
|
LocalError("Upload failed", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename string = ""
|
||||||
|
var ext string
|
||||||
|
for _, fheaders := range r.MultipartForm.File {
|
||||||
|
for _, hdr := range fheaders {
|
||||||
|
infile, err := hdr.Open();
|
||||||
|
if err != nil {
|
||||||
|
LocalError("Upload failed", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer infile.Close()
|
||||||
|
|
||||||
|
// We don't want multiple files
|
||||||
|
if filename != "" {
|
||||||
|
if filename != hdr.Filename {
|
||||||
|
os.Remove("./uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext)
|
||||||
|
LocalError("You may only upload one avatar", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
filename = hdr.Filename
|
||||||
|
}
|
||||||
|
|
||||||
|
if ext == "" {
|
||||||
|
extarr := strings.Split(hdr.Filename,".")
|
||||||
|
if len(extarr) < 2 {
|
||||||
|
LocalError("Bad file", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ext = extarr[len(extarr) - 1]
|
||||||
|
|
||||||
|
reg, err := regexp.Compile("[^A-Za-z0-9]+")
|
||||||
|
if err != nil {
|
||||||
|
LocalError("Bad file extension", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ext = reg.ReplaceAllString(ext,"")
|
||||||
|
ext = strings.ToLower(ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
outfile, err := os.Create("./uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext);
|
||||||
|
if err != nil {
|
||||||
|
LocalError("Upload failed [File Creation Failed]", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer outfile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(outfile, infile);
|
||||||
|
if err != nil {
|
||||||
|
LocalError("Upload failed [Copy Failed]", w, r, user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = set_avatar_stmt.Exec("." + ext, strconv.Itoa(user.ID))
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user.HasAvatar = true
|
||||||
|
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + "." + ext
|
||||||
|
|
||||||
|
pi := Page{"Edit Avatar","account-own-edit-avatar-success",user,tList,0}
|
||||||
|
templates.ExecuteTemplate(w,"account-own-edit-avatar-success.html", pi)
|
||||||
|
}
|
||||||
func route_logout(w http.ResponseWriter, r *http.Request) {
|
func route_logout(w http.ResponseWriter, r *http.Request) {
|
||||||
user := SessionCheck(w,r)
|
user := SessionCheck(w,r)
|
||||||
if !user.Loggedin {
|
if !user.Loggedin {
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
go run errors.go main.go pages.go post.go routes.go topic.go user.go utils.go config.go
|
go run errors.go main.go pages.go reply.go routes.go topic.go user.go utils.go config.go
|
||||||
pause
|
pause
|
|
@ -0,0 +1,30 @@
|
||||||
|
{{template "header.html" . }}
|
||||||
|
<div class="alert_success">Your data was successfully updated</div>
|
||||||
|
<div class="colblock_left">
|
||||||
|
<div class="rowitem"><a>My Account</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/critical/">Edit Password</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/avatar/">Edit Avatar</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="colblock_right">
|
||||||
|
<div class="rowitem"><a>Edit Avatar</a></div>
|
||||||
|
</div>
|
||||||
|
{{ if .CurrentUser.HasAvatar }}
|
||||||
|
<div class="colblock_right">
|
||||||
|
<div class="rowitem"><img src="{{.CurrentUser.Avatar}}" height="128px" max-width="128px" /></div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="colblock_right">
|
||||||
|
<form action="/user/edit/avatar/submit/" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><a>Upload Avatar</a></div>
|
||||||
|
<div class="formitem"><input name="account-avatar" type="file" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><button name="account-button" class="formbutton">Update</div></div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{{template "footer.html" . }}
|
|
@ -0,0 +1,29 @@
|
||||||
|
{{template "header.html" . }}
|
||||||
|
<div class="colblock_left">
|
||||||
|
<div class="rowitem"><a>My Account</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/critical/">Edit Password</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/avatar/">Edit Avatar</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="colblock_right">
|
||||||
|
<div class="rowitem"><a>Edit Avatar</a></div>
|
||||||
|
</div>
|
||||||
|
{{ if .CurrentUser.HasAvatar }}
|
||||||
|
<div class="colblock_right">
|
||||||
|
<div class="rowitem"><img src="{{.CurrentUser.Avatar}}" height="128px" max-width="128px" /></div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<div class="colblock_right">
|
||||||
|
<form action="/user/edit/avatar/submit/" method="post" enctype="multipart/form-data">
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><a>Upload Avatar</a></div>
|
||||||
|
<div class="formitem"><input name="account-avatar" type="file" /></div>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<div class="formitem"><button name="account-button" class="formbutton">Update</div></div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{{template "footer.html" . }}
|
|
@ -1,9 +1,17 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<div class="alert_success">Your data was successfully updated</div>
|
<div class="alert_success">Your data was successfully updated</div>
|
||||||
<div class="rowblock">
|
<div class="colblock_left">
|
||||||
|
<div class="rowitem"><a>My Account</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/critical/">Edit Password</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/avatar/">Edit Avatar</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="colblock_right">
|
||||||
<div class="rowitem"><a>Edit Password</a></div>
|
<div class="rowitem"><a>Edit Password</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="colblock_right">
|
||||||
<form action="/user/edit/critical/submit/" method="post">
|
<form action="/user/edit/critical/submit/" method="post">
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem"><a>Current Password</a></div>
|
<div class="formitem"><a>Current Password</a></div>
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<div class="rowblock">
|
<div class="colblock_left">
|
||||||
|
<div class="rowitem"><a>My Account</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/critical/">Edit Password</a></div>
|
||||||
|
<div class="rowitem passive"><a href="/user/edit/avatar/">Edit Avatar</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
<div class="rowitem passive"><a>Coming Soon</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="colblock_right">
|
||||||
<div class="rowitem"><a>Edit Password</a></div>
|
<div class="rowitem"><a>Edit Password</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="colblock_right">
|
||||||
<form action="/user/edit/critical/submit/" method="post">
|
<form action="/user/edit/critical/submit/" method="post">
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
<div class="formitem"><a>Current Password</a></div>
|
<div class="formitem"><a>Current Password</a></div>
|
||||||
|
|
|
@ -17,21 +17,22 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<div class="rowitem passive editable_parent" style="border-bottom: none;">
|
<div class="rowitem passive editable_parent" style="border-bottom: none;{{ if .CurrentUser.HasAvatar }}background-image: url({{ .CurrentUser.Avatar }});background-position: left;background-repeat: no-repeat;background-size: 128px;padding-left: 136px;{{end}}">
|
||||||
<span class="hide_on_edit topic_content">{{index .Something "content"}}</span>
|
<span class="hide_on_edit topic_content">{{index .Something "content"}}</span>
|
||||||
<textarea name="topic_content" class="show_on_edit topic_content_input">{{index .Something "content"}}</textarea>
|
<textarea name="topic_content" class="show_on_edit topic_content_input">{{index .Something "content"}}</textarea>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a class="topic_status" style="padding-left: 0px;margin-left: 0px;">{{index .Something "createdByName"}}<a/>
|
<a class="topic_status" style="padding-left: 0px;margin-left: 0px;">{{index .Something "createdByName"}}<a/>
|
||||||
</div>
|
</div>
|
||||||
</div><br />
|
</div><br />
|
||||||
<div class="rowblock">
|
<div class="rowblock" style="overflow: hidden;">
|
||||||
{{range $index, $element := .ItemList}}<div class="rowitem passive deletable_block editable_parent">
|
{{range $index, $element := .ItemList}}
|
||||||
|
<div class="rowitem passive deletable_block editable_parent" style="{{ if $element.HasAvatar }}background-image: url({{ $element.Avatar }});background-position: left;background-repeat: no-repeat;background-size: 128px;padding-left: 136px;{{end}}">
|
||||||
<span class="editable_block">{{$element.Content}}</span>
|
<span class="editable_block">{{$element.Content}}</span>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
<a class="topic_status" style="padding-left: 0px;margin-left: 0px;">{{$element.CreatedByName}}<a/>
|
<a class="topic_status" style="padding-left: 0px;margin-left: 0px;">{{$element.CreatedByName}}<a/>
|
||||||
<a href="/reply/edit/submit/{{$element.ID}}/"><button class="topic_status edit_item">Edit</button></a>
|
<a href="/reply/edit/submit/{{$element.ID}}/"><button class="topic_status edit_item">Edit</button></a>
|
||||||
<a href="/reply/delete/submit/{{$element.ID}}/"><button class="topic_status delete_item">Delete</button></a>
|
<a href="/reply/delete/submit/{{$element.ID}}/"><button class="topic_status delete_item">Delete</button></a>
|
||||||
</div>{{end}}
|
</div>{{ end }}
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<form action="/reply/create/" method="post">
|
<form action="/reply/create/" method="post">
|
||||||
|
|
12
src/user.go
12
src/user.go
|
@ -15,6 +15,8 @@ type User struct
|
||||||
Is_Super_Admin bool
|
Is_Super_Admin bool
|
||||||
Session string
|
Session string
|
||||||
Loggedin bool
|
Loggedin bool
|
||||||
|
Avatar string
|
||||||
|
HasAvatar bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetPassword(uid int, password string) (error) {
|
func SetPassword(uid int, password string) (error) {
|
||||||
|
@ -37,7 +39,7 @@ func SetPassword(uid int, password string) (error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SessionCheck(w http.ResponseWriter, r *http.Request) (User) {
|
func SessionCheck(w http.ResponseWriter, r *http.Request) (User) {
|
||||||
user := User{0,"",0,false,false,"",false}
|
user := User{0,"",0,false,false,"",false,"",false}
|
||||||
var err error
|
var err error
|
||||||
var cookie *http.Cookie
|
var cookie *http.Cookie
|
||||||
|
|
||||||
|
@ -61,7 +63,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (User) {
|
||||||
log.Print("Session: " + user.Session)
|
log.Print("Session: " + user.Session)
|
||||||
|
|
||||||
// Is this session valid..?
|
// Is this session valid..?
|
||||||
err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session)
|
err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Avatar)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
log.Print("Couldn't find the user session")
|
log.Print("Couldn't find the user session")
|
||||||
return user
|
return user
|
||||||
|
@ -70,6 +72,12 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (User) {
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
user.Is_Admin = user.Is_Super_Admin
|
user.Is_Admin = user.Is_Super_Admin
|
||||||
|
if user.Avatar != "" {
|
||||||
|
user.HasAvatar = true
|
||||||
|
if user.Avatar[0] == '.' {
|
||||||
|
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
|
||||||
|
}
|
||||||
|
}
|
||||||
user.Loggedin = true
|
user.Loggedin = true
|
||||||
log.Print("Logged in")
|
log.Print("Logged in")
|
||||||
log.Print("ID: " + strconv.Itoa(user.ID))
|
log.Print("ID: " + strconv.Itoa(user.ID))
|
||||||
|
|
Loading…
Reference in New Issue