Add postal support for email verification #3

Merged
Asara merged 1 commit from postal_integration into master 2020-01-25 23:10:31 +00:00
3 changed files with 93 additions and 50 deletions

View file

@ -48,6 +48,7 @@ func Init() {
type ReturnMessage struct { type ReturnMessage struct {
Message string `json:"msg"` Message string `json:"msg"`
Error bool `json:"error"`
} }
type SignUpCredentials struct { type SignUpCredentials struct {
@ -98,6 +99,7 @@ func Routes() *chi.Mux {
func verify(w http.ResponseWriter, r *http.Request) { func verify(w http.ResponseWriter, r *http.Request) {
returnMessage := ReturnMessage{} returnMessage := ReturnMessage{}
returnMessage.Error = false
_, claims, _ := jwtauth.FromContext(r.Context()) _, claims, _ := jwtauth.FromContext(r.Context())
sqlStatement := ` sqlStatement := `
UPDATE users UPDATE users
@ -107,6 +109,7 @@ func verify(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
returnMessage.Message = "unexpected error verifying account. please contact the administrator" returnMessage.Message = "unexpected error verifying account. please contact the administrator"
returnMessage.Error = true
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }
@ -118,29 +121,34 @@ func verify(w http.ResponseWriter, r *http.Request) {
func register(w http.ResponseWriter, r *http.Request) { func register(w http.ResponseWriter, r *http.Request) {
returnMessage := ReturnMessage{} returnMessage := ReturnMessage{}
returnMessage.Error = false
creds := &SignUpCredentials{} creds := &SignUpCredentials{}
err := json.NewDecoder(r.Body).Decode(creds) err := json.NewDecoder(r.Body).Decode(creds)
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
returnMessage.Message = "bad data provided" returnMessage.Message = "bad data provided"
returnMessage.Error = true
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }
if creds.Username == "" { if creds.Username == "" {
returnMessage.Message = "username is required" returnMessage.Message = "username is required"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }
if creds.Password == "" { if creds.Password == "" {
returnMessage.Message = "password is required" returnMessage.Message = "password is required"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }
if creds.Email == "" { if creds.Email == "" {
returnMessage.Message = "email is required" returnMessage.Message = "email is required"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
@ -148,6 +156,7 @@ func register(w http.ResponseWriter, r *http.Request) {
err = checkmail.ValidateFormat(creds.Email) err = checkmail.ValidateFormat(creds.Email)
if err != nil { if err != nil {
returnMessage.Message = "email not valid" returnMessage.Message = "email not valid"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
@ -159,6 +168,7 @@ func register(w http.ResponseWriter, r *http.Request) {
if _, err = DB.Exec(s, creds.Username, creds.Email, string(hashedPassword), false, false); err != nil { if _, err = DB.Exec(s, creds.Username, creds.Email, string(hashedPassword), false, false); err != nil {
fmt.Println(err) fmt.Println(err)
returnMessage.Message = "unexpected error. please contact the administrator" returnMessage.Message = "unexpected error. please contact the administrator"
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
@ -195,11 +205,13 @@ func register(w http.ResponseWriter, r *http.Request) {
func signin(w http.ResponseWriter, r *http.Request) { func signin(w http.ResponseWriter, r *http.Request) {
returnMessage := ReturnMessage{} returnMessage := ReturnMessage{}
returnMessage.Error = false
creds := &UserCredentials{} creds := &UserCredentials{}
err := json.NewDecoder(r.Body).Decode(creds) err := json.NewDecoder(r.Body).Decode(creds)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
returnMessage.Message = "bad data provided" returnMessage.Message = "bad data provided"
returnMessage.Error = true
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }
@ -207,6 +219,7 @@ func signin(w http.ResponseWriter, r *http.Request) {
if !ok { if !ok {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
returnMessage.Message = verify_pw returnMessage.Message = verify_pw
returnMessage.Error = true
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }
@ -230,6 +243,7 @@ func signin(w http.ResponseWriter, r *http.Request) {
func refresh(w http.ResponseWriter, r *http.Request) { func refresh(w http.ResponseWriter, r *http.Request) {
returnMessage := ReturnMessage{} returnMessage := ReturnMessage{}
returnMessage.Error = false
_, claims, _ := jwtauth.FromContext(r.Context()) _, claims, _ := jwtauth.FromContext(r.Context())
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
expirationTime := time.Now().Add(24 * time.Hour) expirationTime := time.Now().Add(24 * time.Hour)
@ -240,6 +254,7 @@ func refresh(w http.ResponseWriter, r *http.Request) {
fmt.Println(err) fmt.Println(err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
returnMessage.Message = "unexpected error refreshing your token, please try again later" returnMessage.Message = "unexpected error refreshing your token, please try again later"
returnMessage.Error = true
render.JSON(w, r, returnMessage) render.JSON(w, r, returnMessage)
return return
} }

View file

@ -43,8 +43,9 @@ type NewBlogPost struct {
Author string `json:"author",db:"author"` Author string `json:"author",db:"author"`
} }
type ReturnError struct { type ReturnMessage struct {
Message string `json:"error"` Message string `json:"msg"`
Error bool `json:"error"`
} }
type ReturnSuccess struct { type ReturnSuccess struct {
@ -74,36 +75,41 @@ func Routes() *chi.Mux {
} }
func createBlogPost(w http.ResponseWriter, r *http.Request) { func createBlogPost(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
newBlogPost := &NewBlogPost{} newBlogPost := &NewBlogPost{}
// basic checks // basic checks
_, claims, _ := jwtauth.FromContext(r.Context()) _, claims, _ := jwtauth.FromContext(r.Context())
is_admin := claims["admin"].(bool) is_admin := claims["admin"].(bool)
if !is_admin { if !is_admin {
returnError.Message = "sorry only admins are allowed to create blog posts" returnMessage.Message = "sorry only admins are allowed to create blog posts"
returnMessage.Error = true
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
username := claims["username"].(string) username := claims["username"].(string)
err := json.NewDecoder(r.Body).Decode(newBlogPost) err := json.NewDecoder(r.Body).Decode(newBlogPost)
if err != nil { if err != nil {
returnError.Message = "unknown error, try again later" returnMessage.Message = "unknown error, try again later"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
if newBlogPost.Title == "" { if newBlogPost.Title == "" {
returnError.Message = "title is required" returnMessage.Message = "title is required"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
if newBlogPost.Content == "" { if newBlogPost.Content == "" {
returnError.Message = "content is required" returnMessage.Message = "content is required"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
as := slug.Make(newBlogPost.Title) as := slug.Make(newBlogPost.Title)
@ -113,16 +119,18 @@ func createBlogPost(w http.ResponseWriter, r *http.Request) {
scr := 0 scr := 0
err = slugCheck.Scan(&scr) err = slugCheck.Scan(&scr)
if err == nil { if err == nil {
returnError.Message = "slug already exists" returnMessage.Message = "slug already exists"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
if err != nil { if err != nil {
if err != sql.ErrNoRows { if err != sql.ErrNoRows {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -135,15 +143,17 @@ func createBlogPost(w http.ResponseWriter, r *http.Request) {
err = DB.QueryRow(s, newBlogPost.Title, as, username, newBlogPost.Content, time.Now().UTC(), false, time.Now().UTC()).Scan(&article_id) err = DB.QueryRow(s, newBlogPost.Title, as, username, newBlogPost.Content, time.Now().UTC(), false, time.Now().UTC()).Scan(&article_id)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -164,7 +174,8 @@ func createBlogPost(w http.ResponseWriter, r *http.Request) {
} }
func updateBlogPostById(w http.ResponseWriter, r *http.Request) { func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
// Get the actual post // Get the actual post
id := chi.URLParam(r, "id") id := chi.URLParam(r, "id")
result := DB.QueryRow("SELECT id, title, slug, author, content, time_published FROM posts WHERE id=$1", id) result := DB.QueryRow("SELECT id, title, slug, author, content, time_published FROM posts WHERE id=$1", id)
@ -172,15 +183,17 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished) err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
returnError.Message = "blog post requested for update not found" returnMessage.Message = "blog post requested for update not found"
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -189,9 +202,10 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
_, claims, _ := jwtauth.FromContext(r.Context()) _, claims, _ := jwtauth.FromContext(r.Context())
username := claims["username"].(string) username := claims["username"].(string)
if username != post.Author { if username != post.Author {
returnError.Message = "unauthorized..." returnMessage.Message = "unauthorized..."
returnMessage.Error = true
w.WriteHeader(http.StatusUnauthorized) w.WriteHeader(http.StatusUnauthorized)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
// update the post struct // update the post struct
@ -206,9 +220,10 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
// write the row update // write the row update
_, err = DB.Exec(s, post.Title, post.Content, true, time.Now().UTC(), post.ID) _, err = DB.Exec(s, post.Title, post.Content, true, time.Now().UTC(), post.ID)
if err != nil { if err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -220,7 +235,8 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
// This will search by the last id seen, descending. // This will search by the last id seen, descending.
func getBlogPosts(w http.ResponseWriter, r *http.Request) { func getBlogPosts(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
referenceID := &ReferenceID{} referenceID := &ReferenceID{}
err := json.NewDecoder(r.Body).Decode(referenceID) err := json.NewDecoder(r.Body).Decode(referenceID)
// hardcode 9001 for cool kid points // hardcode 9001 for cool kid points
@ -241,9 +257,10 @@ func getBlogPosts(w http.ResponseWriter, r *http.Request) {
` `
rows, err := DB.Query(search, search_id) rows, err := DB.Query(search, search_id)
if err != nil { if err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -256,9 +273,10 @@ func getBlogPosts(w http.ResponseWriter, r *http.Request) {
posts = append(posts, post) posts = append(posts, post)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -268,15 +286,17 @@ func getBlogPosts(w http.ResponseWriter, r *http.Request) {
} }
func getBlogPostBySlug(w http.ResponseWriter, r *http.Request) { func getBlogPostBySlug(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
slug := chi.URLParam(r, "slug") slug := chi.URLParam(r, "slug")
result := DB.QueryRow("SELECT id, title, slug, author, content, time_published, modified, last_modified FROM posts WHERE slug=$1", slug) result := DB.QueryRow("SELECT id, title, slug, author, content, time_published, modified, last_modified FROM posts WHERE slug=$1", slug)
post := BlogPost{} post := BlogPost{}
err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished, &post.Modified, &post.TimeModified) err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished, &post.Modified, &post.TimeModified)
if err != nil { if err != nil {
returnError.Message = "post not found" returnMessage.Message = "post not found"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
@ -285,15 +305,17 @@ func getBlogPostBySlug(w http.ResponseWriter, r *http.Request) {
} }
func getBlogPostById(w http.ResponseWriter, r *http.Request) { func getBlogPostById(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
id := chi.URLParam(r, "id") id := chi.URLParam(r, "id")
result := DB.QueryRow("SELECT id, title, slug, author, content, time_published, modified, last_modified FROM posts WHERE id=$1", id) result := DB.QueryRow("SELECT id, title, slug, author, content, time_published, modified, last_modified FROM posts WHERE id=$1", id)
post := BlogPost{} post := BlogPost{}
err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished, &post.Modified, &post.TimeModified) err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished, &post.Modified, &post.TimeModified)
if err != nil { if err != nil {
returnError.Message = "post not found" returnMessage.Message = "post not found"
returnMessage.Error = true
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
return return
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
@ -302,7 +324,8 @@ func getBlogPostById(w http.ResponseWriter, r *http.Request) {
} }
func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) { func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
referenceID := &ReferenceID{} referenceID := &ReferenceID{}
err := json.NewDecoder(r.Body).Decode(referenceID) err := json.NewDecoder(r.Body).Decode(referenceID)
// hardcode 9001 for cool kid points // hardcode 9001 for cool kid points
@ -326,9 +349,10 @@ func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
` `
rows, err := DB.Query(search, search_id, tag) rows, err := DB.Query(search, search_id, tag)
if err != nil { if err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -341,9 +365,10 @@ func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
posts = append(posts, post) posts = append(posts, post)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -353,7 +378,8 @@ func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
} }
func getBlogPostsByAuthor(w http.ResponseWriter, r *http.Request) { func getBlogPostsByAuthor(w http.ResponseWriter, r *http.Request) {
returnError := ReturnError{} returnMessage := ReturnMessage{}
returnMessage.Error = false
referenceID := &ReferenceID{} referenceID := &ReferenceID{}
err := json.NewDecoder(r.Body).Decode(referenceID) err := json.NewDecoder(r.Body).Decode(referenceID)
// hardcode 9001 for cool kid points // hardcode 9001 for cool kid points
@ -376,9 +402,10 @@ func getBlogPostsByAuthor(w http.ResponseWriter, r *http.Request) {
` `
rows, err := DB.Query(search, search_id, author) rows, err := DB.Query(search, search_id, author)
if err != nil { if err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }
@ -391,9 +418,10 @@ func getBlogPostsByAuthor(w http.ResponseWriter, r *http.Request) {
posts = append(posts, post) posts = append(posts, post)
} }
if err := rows.Err(); err != nil { if err := rows.Err(); err != nil {
returnError.Message = "something is super broken..." returnMessage.Message = "something is super broken..."
returnMessage.Error = true
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
render.JSON(w, r, returnError) render.JSON(w, r, returnMessage)
fmt.Println(err) fmt.Println(err)
return return
} }