diff --git a/main.go b/main.go index c4442bf..aa45131 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,8 @@ func main() { values := config.ReadConfig("config.json") views.PopulateTemplates() http.HandleFunc("/", views.ShowAllTasksFunc) + http.HandleFunc("/login/", views.LoginFunc) + http.HandleFunc("/logout/", views.LogoutFunc) http.HandleFunc("/add-category/", views.AddCategoryFunc) http.HandleFunc("/add-comment/", views.AddCommentFunc) http.HandleFunc("/del-comment/", views.DeleteCommentFunc) diff --git a/sessions/sessions.go b/sessions/sessions.go new file mode 100755 index 0000000..be955c6 --- /dev/null +++ b/sessions/sessions.go @@ -0,0 +1,19 @@ +package sessions + +import ( + "net/http" + + "github.com/gorilla/sessions" +) + +//Store the cookie store which is going to store session data in the cookie +var Store = sessions.NewCookieStore([]byte("secret-password")) + +//IsLoggedIn will check if the user has an active session and return True +func IsLoggedIn(r *http.Request) bool { + session, _ := Store.Get(r, "session") + if session.Values["loggedin"] == "true" { + return true + } + return false +} diff --git a/templates/_head.html b/templates/_head.html index 724d4b9..efa6936 100644 --- a/templates/_head.html +++ b/templates/_head.html @@ -75,6 +75,7 @@ {{end}} + diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..47d3ae1 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,36 @@ +
+
+ Login +
+
+ + +
+ + +
+ +
+ +
+ Sign up +
+
+ + +
+ + +
+
+ +
+{{template "footer.html"}} + + + + \ No newline at end of file diff --git a/views/addViews.go b/views/addViews.go index 98f8123..9ccb8d3 100644 --- a/views/addViews.go +++ b/views/addViews.go @@ -16,12 +16,13 @@ import ( "time" "github.com/thewhitetulip/Tasks/db" + "github.com/thewhitetulip/Tasks/sessions" "github.com/thewhitetulip/Tasks/utils" ) // UploadedFileHandler is used to handle the uploaded file related requests func UploadedFileHandler(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { token := r.URL.Path[len("/files/"):] //file, err := db.GetFileName(token) @@ -34,7 +35,7 @@ func UploadedFileHandler(w http.ResponseWriter, r *http.Request) { //AddTaskFunc is used to handle the addition of new task, "/add" URL func AddTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { // Will work only for POST requests, will redirect to home + if r.Method == "POST" && sessions.IsLoggedIn(r) { // Will work only for POST requests, will redirect to home var filelink string // will store the html when we have files to be uploaded, appened to the note content r.ParseForm() file, handler, err := r.FormFile("uploadfile") @@ -146,7 +147,7 @@ func AddCategoryFunc(w http.ResponseWriter, r *http.Request) { //EditTaskFunc is used to edit tasks, handles "/edit/" URL func EditTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { id, err := strconv.Atoi(r.URL.Path[len("/edit/"):]) if err != nil { log.Println(err) @@ -171,7 +172,7 @@ func EditTaskFunc(w http.ResponseWriter, r *http.Request) { //AddCommentFunc will be used func AddCommentFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { + if r.Method == "POST" && sessions.IsLoggedIn(r) { r.ParseForm() text := r.Form.Get("commentText") id := r.Form.Get("taskID") diff --git a/views/deleteViews.go b/views/deleteViews.go index 5ace61f..5f41c99 100644 --- a/views/deleteViews.go +++ b/views/deleteViews.go @@ -10,6 +10,7 @@ import ( "strconv" "github.com/thewhitetulip/Tasks/db" + "github.com/thewhitetulip/Tasks/sessions" "github.com/thewhitetulip/Tasks/utils" ) @@ -19,7 +20,7 @@ func TrashTaskFunc(w http.ResponseWriter, r *http.Request) { //the delete transaction, we use the r.Referer() function to get the link redirectUrl := utils.GetRedirectUrl(r.Referer()) - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { id, err := strconv.Atoi(r.URL.Path[len("/trash/"):]) if err != nil { log.Println("TrashTaskFunc", err) @@ -42,7 +43,7 @@ func TrashTaskFunc(w http.ResponseWriter, r *http.Request) { //RestoreTaskFunc is used to restore task from trash, handles "/restore/" URL func RestoreTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { id, err := strconv.Atoi(r.URL.Path[len("/restore/"):]) if err != nil { log.Println(err) @@ -64,7 +65,7 @@ func RestoreTaskFunc(w http.ResponseWriter, r *http.Request) { //DeleteTaskFunc is used to delete a task, trash = move to recycle bin, delete = permanent delete func DeleteTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { id := r.URL.Path[len("/delete/"):] if id == "all" { err := db.DeleteAll() @@ -96,7 +97,7 @@ func DeleteTaskFunc(w http.ResponseWriter, r *http.Request) { //RestoreFromCompleteFunc restores the task from complete to pending func RestoreFromCompleteFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { id, err := strconv.Atoi(r.URL.Path[len("/incomplete/"):]) if err != nil { log.Println(err) @@ -118,7 +119,7 @@ func RestoreFromCompleteFunc(w http.ResponseWriter, r *http.Request) { //DeleteCategoryFunc will delete any category func DeleteCategoryFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { categoryName := r.URL.Path[len("/del-category/"):] err := db.DeleteCategoryByName(categoryName) if err != nil { @@ -133,7 +134,7 @@ func DeleteCategoryFunc(w http.ResponseWriter, r *http.Request) { //DeleteCommentFunc will delete any category func DeleteCommentFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { id := r.URL.Path[len("/del-comment/"):] commentID, err := strconv.Atoi(id) if err != nil { diff --git a/views/otherViews.go b/views/otherViews.go index 62db302..a265d91 100644 --- a/views/otherViews.go +++ b/views/otherViews.go @@ -14,6 +14,7 @@ import ( "text/template" "github.com/thewhitetulip/Tasks/db" + "github.com/thewhitetulip/Tasks/sessions" "github.com/thewhitetulip/Tasks/utils" ) @@ -49,12 +50,13 @@ func PopulateTemplates() { editTemplate = templates.Lookup("edit.html") searchTemplate = templates.Lookup("search.html") completedTemplate = templates.Lookup("completed.html") + loginTemplate = templates.Lookup("login.html") } //CompleteTaskFunc is used to show the complete tasks, handles "/completed/" url func CompleteTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { redirectURL := utils.GetRedirectUrl(r.Referer()) id, err := strconv.Atoi(r.URL.Path[len("/complete/"):]) if err != nil { @@ -76,7 +78,7 @@ func CompleteTaskFunc(w http.ResponseWriter, r *http.Request) { //SearchTaskFunc is used to handle the /search/ url, handles the search function func SearchTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { + if r.Method == "POST" && sessions.IsLoggedIn(r) { r.ParseForm() query := r.Form.Get("query") @@ -94,7 +96,7 @@ func SearchTaskFunc(w http.ResponseWriter, r *http.Request) { //UpdateTaskFunc is used to update a task, handes "/update/" URL func UpdateTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { + if r.Method == "POST" && sessions.IsLoggedIn(r) { r.ParseForm() id, err := strconv.Atoi(r.Form.Get("id")) if err != nil { @@ -124,7 +126,7 @@ func UpdateTaskFunc(w http.ResponseWriter, r *http.Request) { //UpdateCategoryFunc is used to update a task, handes "/upd-category/" URL func UpdateCategoryFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "POST" { + if r.Method == "POST" && sessions.IsLoggedIn(r) { var redirectURL string r.ParseForm() oldName := r.URL.Path[len("/upd-category/"):] diff --git a/views/sessionViews.go b/views/sessionViews.go new file mode 100644 index 0000000..719bccf --- /dev/null +++ b/views/sessionViews.go @@ -0,0 +1,38 @@ +package views + +import ( + "net/http" + + "github.com/thewhitetulip/Tasks/sessions" +) + +//LogoutFunc Implements the logout functionality. WIll delete the session information from the cookie store +func LogoutFunc(w http.ResponseWriter, r *http.Request) { + session, _ := sessions.Store.Get(r, "session") + if session.Values["loggedin"] != "false" { + session.Values["loggedin"] = "false" + session.Save(r, w) + http.Redirect(w, r, "/login", 302) + return + } + http.Redirect(w, r, "/login", 302) +} + +//LoginFunc implements the login functionality, will add a cookie to the cookie store for managing authentication +func LoginFunc(w http.ResponseWriter, r *http.Request) { + session, _ := sessions.Store.Get(r, "session") + + if r.Method == "POST" && r.FormValue("password") == "secret" && r.FormValue("username") == "user" { + session.Values["loggedin"] = "true" + session.Save(r, w) + http.Redirect(w, r, "/", 302) + return + } + + if session.Values["loggedin"] == "true" { + http.Redirect(w, r, "/", 302) + } else { + loginTemplate.Execute(w, nil) + } + +} diff --git a/views/views.go b/views/views.go index 236465f..44d7258 100644 --- a/views/views.go +++ b/views/views.go @@ -8,6 +8,7 @@ import ( "time" "github.com/thewhitetulip/Tasks/db" + "github.com/thewhitetulip/Tasks/sessions" ) var homeTemplate *template.Template @@ -16,13 +17,15 @@ var completedTemplate *template.Template var editTemplate *template.Template var searchTemplate *template.Template var templates *template.Template +var loginTemplate *template.Template + var message string //message will store the message to be shown as notification var err error //ShowAllTasksFunc is used to handle the "/" URL which is the default ons //TODO add http404 error func ShowAllTasksFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { context, err := db.GetTasks("pending", "") categories := db.GetCategories() if err != nil { @@ -46,7 +49,7 @@ func ShowAllTasksFunc(w http.ResponseWriter, r *http.Request) { //ShowTrashTaskFunc is used to handle the "/trash" URL which is used to show the deleted tasks func ShowTrashTaskFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { context, err := db.GetTasks("deleted", "") categories := db.GetCategories() context.Categories = categories @@ -66,7 +69,7 @@ func ShowTrashTaskFunc(w http.ResponseWriter, r *http.Request) { //ShowCompleteTasksFunc is used to populate the "/completed/" URL func ShowCompleteTasksFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { context, err := db.GetTasks("completed", "") categories := db.GetCategories() context.Categories = categories @@ -83,7 +86,7 @@ func ShowCompleteTasksFunc(w http.ResponseWriter, r *http.Request) { //ShowCategoryFunc will populate the /category/ URL which shows all the tasks related // to that particular category func ShowCategoryFunc(w http.ResponseWriter, r *http.Request) { - if r.Method == "GET" { + if r.Method == "GET" && sessions.IsLoggedIn(r) { category := r.URL.Path[len("/category/"):] context, err := db.GetTasks("", category) categories := db.GetCategories()