diff --git a/pinned-topic.PNG b/pinned-topic.PNG new file mode 100644 index 00000000..43cdb0a9 Binary files /dev/null and b/pinned-topic.PNG differ diff --git a/ren5.PNG b/ren5.PNG new file mode 100644 index 00000000..b83e12d7 Binary files /dev/null and b/ren5.PNG differ diff --git a/src/data.sql b/src/data.sql index 8ae6d86c..98047405 100644 --- a/src/data.sql +++ b/src/data.sql @@ -10,6 +10,7 @@ CREATE TABLE `users`( `createdAt` datetime not null, `lastActiveAt` datetime not null, `session` varchar(200) DEFAULT '', + `email` varchar(200) DEFAULT '', `avatar` varchar(20) DEFAULT '', primary key(`uid`) ); @@ -19,6 +20,7 @@ CREATE TABLE `users_groups`( `name` varchar(100) not null, `permissions` text not null, `is_admin` tinyint DEFAULT 0 not null, + `is_banned` tinyint DEFAULT 0 not null, primary key(`gid`) ); diff --git a/src/errors.go b/src/errors.go index 227767b7..3ee5ee54 100644 --- a/src/errors.go +++ b/src/errors.go @@ -56,6 +56,15 @@ func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user U } } +func NoPermissions(w http.ResponseWriter, r *http.Request, user User) { + errmsg := "You don't have permission to do that." + pi := Page{"Local Error","error",user,tList,errmsg} + var b bytes.Buffer + templates.ExecuteTemplate(&b,"error.html", pi) + errpage := b.String() + http.Error(w,errpage,403) +} + func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, is_js string) { errmsg := "You don't have permission to do that." if is_js == "0" { diff --git a/src/main.go b/src/main.go index ce0630fc..6cf2fb3a 100644 --- a/src/main.go +++ b/src/main.go @@ -24,6 +24,9 @@ var create_reply_stmt *sql.Stmt var edit_topic_stmt *sql.Stmt var edit_reply_stmt *sql.Stmt var delete_reply_stmt *sql.Stmt +var delete_topic_stmt *sql.Stmt +var stick_topic_stmt *sql.Stmt +var unstick_topic_stmt *sql.Stmt var login_stmt *sql.Stmt var update_session_stmt *sql.Stmt var logout_stmt *sql.Stmt @@ -87,6 +90,24 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing delete_topic statement.") + delete_topic_stmt, err = db.Prepare("DELETE FROM topics WHERE tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing stick_topic statement.") + stick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 1 WHERE tid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing unstick_topic statement.") + unstick_topic_stmt, err = db.Prepare("UPDATE topics SET sticky = 0 WHERE tid = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing login statement.") login_stmt, err = db.Prepare("SELECT `uid`, `name`, `password`, `salt` FROM `users` WHERE `name` = ?") if err != nil { @@ -172,6 +193,9 @@ func main(){ http.HandleFunc("/reply/edit/submit/", route_reply_edit_submit) //POST http.HandleFunc("/reply/delete/submit/", route_reply_delete_submit) //POST http.HandleFunc("/topic/edit/submit/", route_edit_topic) //POST + http.HandleFunc("/topic/delete/submit/", route_delete_topic) + http.HandleFunc("/topic/stick/submit/", route_stick_topic) + http.HandleFunc("/topic/unstick/submit/", route_unstick_topic) // Custom Pages http.HandleFunc("/pages/", route_custom_page) diff --git a/src/public/main.css b/src/public/main.css index 72cd67ef..bfd53d11 100644 --- a/src/public/main.css +++ b/src/public/main.css @@ -93,7 +93,7 @@ li:not(:last-child) .rowitem { - width: 99%; + width: 100%; padding-left: 8px; padding-right: 8px; padding-top: 17px; @@ -242,6 +242,21 @@ button display: none; } +.username +{ + text-transform: none; + margin-left: 0px; + padding-left: 4px; + padding-right: 4px; + padding-top: 2px; + padding-bottom: 2px; + color: #505050; /* 80,80,80 */ + border-style: dotted; + border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */ + border-width: 1px; + font-size: 15px; +} + .show_on_edit { display: none; diff --git a/src/routes.go b/src/routes.go index ddb075d8..faa88420 100644 --- a/src/routes.go +++ b/src/routes.go @@ -68,7 +68,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){ topicList = make(map[int]interface{}) currentID = 0 - rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid") + rows, err := db.Query("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC") if err != nil { InternalError(err,w,r,user) return @@ -340,6 +340,82 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { } } +func route_delete_topic(w http.ResponseWriter, r *http.Request) { + user := SessionCheck(w,r) + if !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + tid, err := strconv.Atoi(r.URL.Path[len("/topic/delete/submit/"):]) + if err != nil { + LocalError("The provided TopicID is not a valid number.",w,r,user) + return + } + + err = db.QueryRow("SELECT tid from topics where tid = ?", tid).Scan(&tid) + if err == sql.ErrNoRows { + LocalError("The topic you tried to delete doesn't exist.",w,r,user) + return + } else if err != nil { + InternalError(err,w,r,user) + return + } + + _, err = delete_topic_stmt.Exec(tid) + if err != nil { + InternalError(err,w,r,user) + return + } + log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") + + http.Redirect(w, r, "/", http.StatusSeeOther) +} + +func route_stick_topic(w http.ResponseWriter, r *http.Request) { + user := SessionCheck(w,r) + if !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + tid, err := strconv.Atoi(r.URL.Path[len("/topic/stick/submit/"):]) + if err != nil { + LocalError("The provided TopicID is not a valid number.",w,r,user) + return + } + + _, err = stick_topic_stmt.Exec(tid) + if err != nil { + InternalError(err,w,r,user) + return + } + + http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) +} + +func route_unstick_topic(w http.ResponseWriter, r *http.Request) { + user := SessionCheck(w,r) + if !user.Is_Admin { + NoPermissions(w,r,user) + return + } + + tid, err := strconv.Atoi(r.URL.Path[len("/topic/unstick/submit/"):]) + if err != nil { + LocalError("The provided TopicID is not a valid number.",w,r,user) + return + } + + _, err = unstick_topic_stmt.Exec(tid) + if err != nil { + InternalError(err,w,r,user) + return + } + + http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) +} + func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { user := SessionCheck(w,r) err := r.ParseForm() diff --git a/src/templates/footer.html b/src/templates/footer.html index 44d85e96..43cfc794 100644 --- a/src/templates/footer.html +++ b/src/templates/footer.html @@ -1,3 +1,4 @@ + \ No newline at end of file diff --git a/src/templates/topic.html b/src/templates/topic.html index e535d1d1..e5f6f4b5 100644 --- a/src/templates/topic.html +++ b/src/templates/topic.html @@ -1,16 +1,17 @@ {{template "header.html" . }}
-
+
{{.Something.Title}} {{.Something.Status}} - Edit - Delete + Edit + Delete + {{ if .Something.Sticky }}Unpin{{else}}Pin{{end}}
@@ -21,7 +22,7 @@ {{.Something.Content}}

- {{.Something.CreatedByName}} + {{.Something.CreatedByName}}

@@ -29,9 +30,9 @@
{{$element.ContentHtml}}

-
{{$element.CreatedByName}} - - + {{$element.CreatedByName}} + +
{{ end }}
diff --git a/src/templates/topics.html b/src/templates/topics.html index 0de8b8d2..d8b09075 100644 --- a/src/templates/topics.html +++ b/src/templates/topics.html @@ -3,7 +3,7 @@
Topic List
- {{range .ItemList}}
+ {{range .ItemList}}
{{.Title}} {{if .Is_Closed}}closed{{else}}open{{end}}
{{end}}
diff --git a/topic-list.PNG b/topic-list.PNG new file mode 100644 index 00000000..da856fbc Binary files /dev/null and b/topic-list.PNG differ