Add postal support for email verification #3
3 changed files with 93 additions and 50 deletions
2
main.go
2
main.go
|
@ -54,7 +54,7 @@ func main() {
|
|||
func Routes() *chi.Mux {
|
||||
router := chi.NewRouter()
|
||||
cors := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{os.Getenv("UI_PROTO") + os.Getenv("UI_ADDR") + os.Getenv("UI_PORT"), os.Getenv("UI_PROTO") + "www." + os.Getenv("UI_ADDR") + os.Getenv("UI_PORT")},
|
||||
AllowedOrigins: []string{os.Getenv("UI_PROTO") + os.Getenv("UI_ADDR") + os.Getenv("UI_PORT"), os.Getenv("UI_PROTO") + "www." + os.Getenv("UI_ADDR") + os.Getenv("UI_PORT")},
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"},
|
||||
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
|
||||
AllowCredentials: true,
|
||||
|
|
|
@ -48,6 +48,7 @@ func Init() {
|
|||
|
||||
type ReturnMessage struct {
|
||||
Message string `json:"msg"`
|
||||
Error bool `json:"error"`
|
||||
}
|
||||
|
||||
type SignUpCredentials struct {
|
||||
|
@ -98,6 +99,7 @@ func Routes() *chi.Mux {
|
|||
|
||||
func verify(w http.ResponseWriter, r *http.Request) {
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
_, claims, _ := jwtauth.FromContext(r.Context())
|
||||
sqlStatement := `
|
||||
UPDATE users
|
||||
|
@ -107,6 +109,7 @@ func verify(w http.ResponseWriter, r *http.Request) {
|
|||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
returnMessage.Message = "unexpected error verifying account. please contact the administrator"
|
||||
returnMessage.Error = true
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
|
@ -118,29 +121,34 @@ func verify(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func register(w http.ResponseWriter, r *http.Request) {
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
creds := &SignUpCredentials{}
|
||||
err := json.NewDecoder(r.Body).Decode(creds)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
returnMessage.Message = "bad data provided"
|
||||
returnMessage.Error = true
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
if creds.Username == "" {
|
||||
returnMessage.Message = "username is required"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
if creds.Password == "" {
|
||||
returnMessage.Message = "password is required"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
if creds.Email == "" {
|
||||
returnMessage.Message = "email is required"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
|
@ -148,6 +156,7 @@ func register(w http.ResponseWriter, r *http.Request) {
|
|||
err = checkmail.ValidateFormat(creds.Email)
|
||||
if err != nil {
|
||||
returnMessage.Message = "email not valid"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnMessage)
|
||||
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 {
|
||||
fmt.Println(err)
|
||||
returnMessage.Message = "unexpected error. please contact the administrator"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
|
@ -195,11 +205,13 @@ func register(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func signin(w http.ResponseWriter, r *http.Request) {
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
creds := &UserCredentials{}
|
||||
err := json.NewDecoder(r.Body).Decode(creds)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
returnMessage.Message = "bad data provided"
|
||||
returnMessage.Error = true
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
|
@ -207,6 +219,7 @@ func signin(w http.ResponseWriter, r *http.Request) {
|
|||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
returnMessage.Message = verify_pw
|
||||
returnMessage.Error = true
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
|
@ -230,6 +243,7 @@ func signin(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func refresh(w http.ResponseWriter, r *http.Request) {
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
_, claims, _ := jwtauth.FromContext(r.Context())
|
||||
w.WriteHeader(http.StatusOK)
|
||||
expirationTime := time.Now().Add(24 * time.Hour)
|
||||
|
@ -240,6 +254,7 @@ func refresh(w http.ResponseWriter, r *http.Request) {
|
|||
fmt.Println(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
returnMessage.Message = "unexpected error refreshing your token, please try again later"
|
||||
returnMessage.Error = true
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -43,8 +43,9 @@ type NewBlogPost struct {
|
|||
Author string `json:"author",db:"author"`
|
||||
}
|
||||
|
||||
type ReturnError struct {
|
||||
Message string `json:"error"`
|
||||
type ReturnMessage struct {
|
||||
Message string `json:"msg"`
|
||||
Error bool `json:"error"`
|
||||
}
|
||||
|
||||
type ReturnSuccess struct {
|
||||
|
@ -74,36 +75,41 @@ func Routes() *chi.Mux {
|
|||
}
|
||||
|
||||
func createBlogPost(w http.ResponseWriter, r *http.Request) {
|
||||
returnError := ReturnError{}
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
newBlogPost := &NewBlogPost{}
|
||||
// basic checks
|
||||
_, claims, _ := jwtauth.FromContext(r.Context())
|
||||
is_admin := claims["admin"].(bool)
|
||||
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)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
|
||||
username := claims["username"].(string)
|
||||
err := json.NewDecoder(r.Body).Decode(newBlogPost)
|
||||
if err != nil {
|
||||
returnError.Message = "unknown error, try again later"
|
||||
returnMessage.Message = "unknown error, try again later"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
if newBlogPost.Title == "" {
|
||||
returnError.Message = "title is required"
|
||||
returnMessage.Message = "title is required"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
if newBlogPost.Content == "" {
|
||||
returnError.Message = "content is required"
|
||||
returnMessage.Message = "content is required"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
as := slug.Make(newBlogPost.Title)
|
||||
|
@ -113,16 +119,18 @@ func createBlogPost(w http.ResponseWriter, r *http.Request) {
|
|||
scr := 0
|
||||
err = slugCheck.Scan(&scr)
|
||||
if err == nil {
|
||||
returnError.Message = "slug already exists"
|
||||
returnMessage.Message = "slug already exists"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
if err != sql.ErrNoRows {
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
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)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -164,7 +174,8 @@ func createBlogPost(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
|
||||
id := chi.URLParam(r, "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)
|
||||
if err != nil {
|
||||
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)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -189,9 +202,10 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
|
|||
_, claims, _ := jwtauth.FromContext(r.Context())
|
||||
username := claims["username"].(string)
|
||||
if username != post.Author {
|
||||
returnError.Message = "unauthorized..."
|
||||
returnMessage.Message = "unauthorized..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
// update the post struct
|
||||
|
@ -206,9 +220,10 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
|
|||
// write the row update
|
||||
_, err = DB.Exec(s, post.Title, post.Content, true, time.Now().UTC(), post.ID)
|
||||
if err != nil {
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -220,7 +235,8 @@ func updateBlogPostById(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// This will search by the last id seen, descending.
|
||||
func getBlogPosts(w http.ResponseWriter, r *http.Request) {
|
||||
returnError := ReturnError{}
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
referenceID := &ReferenceID{}
|
||||
err := json.NewDecoder(r.Body).Decode(referenceID)
|
||||
// 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)
|
||||
if err != nil {
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -256,9 +273,10 @@ func getBlogPosts(w http.ResponseWriter, r *http.Request) {
|
|||
posts = append(posts, post)
|
||||
}
|
||||
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)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -268,15 +286,17 @@ func getBlogPosts(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")
|
||||
result := DB.QueryRow("SELECT id, title, slug, author, content, time_published, modified, last_modified FROM posts WHERE slug=$1", slug)
|
||||
post := BlogPost{}
|
||||
err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished, &post.Modified, &post.TimeModified)
|
||||
if err != nil {
|
||||
returnError.Message = "post not found"
|
||||
returnMessage.Message = "post not found"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
@ -285,15 +305,17 @@ func getBlogPostBySlug(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")
|
||||
result := DB.QueryRow("SELECT id, title, slug, author, content, time_published, modified, last_modified FROM posts WHERE id=$1", id)
|
||||
post := BlogPost{}
|
||||
err := result.Scan(&post.ID, &post.Title, &post.Slug, &post.Author, &post.Content, &post.TimePublished, &post.Modified, &post.TimeModified)
|
||||
if err != nil {
|
||||
returnError.Message = "post not found"
|
||||
returnMessage.Message = "post not found"
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
|
@ -302,7 +324,8 @@ func getBlogPostById(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
|
||||
returnError := ReturnError{}
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
referenceID := &ReferenceID{}
|
||||
err := json.NewDecoder(r.Body).Decode(referenceID)
|
||||
// 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)
|
||||
if err != nil {
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -341,9 +365,10 @@ func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
|
|||
posts = append(posts, post)
|
||||
}
|
||||
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)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -353,7 +378,8 @@ func getBlogPostsByTag(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func getBlogPostsByAuthor(w http.ResponseWriter, r *http.Request) {
|
||||
returnError := ReturnError{}
|
||||
returnMessage := ReturnMessage{}
|
||||
returnMessage.Error = false
|
||||
referenceID := &ReferenceID{}
|
||||
err := json.NewDecoder(r.Body).Decode(referenceID)
|
||||
// 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)
|
||||
if err != nil {
|
||||
returnError.Message = "something is super broken..."
|
||||
returnMessage.Message = "something is super broken..."
|
||||
returnMessage.Error = true
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
@ -391,9 +418,10 @@ func getBlogPostsByAuthor(w http.ResponseWriter, r *http.Request) {
|
|||
posts = append(posts, post)
|
||||
}
|
||||
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)
|
||||
render.JSON(w, r, returnError)
|
||||
render.JSON(w, r, returnMessage)
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
|
Reference in a new issue