A clean, Markdown-based publishing platform made for writers. Write together, and build a community. https://writefreely.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

141 lines
4.0 KiB

  1. /*
  2. * Copyright © 2018 A Bunch Tell LLC.
  3. *
  4. * This file is part of WriteFreely.
  5. *
  6. * WriteFreely is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License, included
  8. * in the LICENSE file in this source code package.
  9. */
  10. package writefreely
  11. import (
  12. "database/sql"
  13. "encoding/json"
  14. "github.com/writeas/impart"
  15. "github.com/writeas/web-core/log"
  16. "net/http"
  17. )
  18. func handleWebSignup(app *app, w http.ResponseWriter, r *http.Request) error {
  19. reqJSON := IsJSON(r.Header.Get("Content-Type"))
  20. // Get params
  21. var ur userRegistration
  22. if reqJSON {
  23. decoder := json.NewDecoder(r.Body)
  24. err := decoder.Decode(&ur)
  25. if err != nil {
  26. log.Error("Couldn't parse signup JSON request: %v\n", err)
  27. return ErrBadJSON
  28. }
  29. } else {
  30. err := r.ParseForm()
  31. if err != nil {
  32. log.Error("Couldn't parse signup form request: %v\n", err)
  33. return ErrBadFormData
  34. }
  35. err = app.formDecoder.Decode(&ur, r.PostForm)
  36. if err != nil {
  37. log.Error("Couldn't decode signup form request: %v\n", err)
  38. return ErrBadFormData
  39. }
  40. }
  41. ur.Web = true
  42. ur.Normalize = true
  43. _, err := signupWithRegistration(app, ur, w, r)
  44. if err != nil {
  45. if err, ok := err.(impart.HTTPError); ok {
  46. session, _ := app.sessionStore.Get(r, cookieName)
  47. if session != nil {
  48. session.AddFlash(err.Message)
  49. session.Save(r, w)
  50. return impart.HTTPError{http.StatusFound, "/"}
  51. }
  52. }
  53. return err
  54. }
  55. return impart.HTTPError{http.StatusFound, "/"}
  56. }
  57. // { "username": "asdf" }
  58. // result: { code: 204 }
  59. func handleUsernameCheck(app *app, w http.ResponseWriter, r *http.Request) error {
  60. reqJSON := IsJSON(r.Header.Get("Content-Type"))
  61. // Get params
  62. var d struct {
  63. Username string `json:"username"`
  64. }
  65. if reqJSON {
  66. decoder := json.NewDecoder(r.Body)
  67. err := decoder.Decode(&d)
  68. if err != nil {
  69. log.Error("Couldn't decode username check: %v\n", err)
  70. return ErrBadFormData
  71. }
  72. } else {
  73. return impart.HTTPError{http.StatusNotAcceptable, "Must be JSON request"}
  74. }
  75. // Check if username is okay
  76. finalUsername := getSlug(d.Username, "")
  77. if finalUsername == "" {
  78. errMsg := "Invalid username"
  79. if d.Username != "" {
  80. // Username was provided, but didn't convert into valid latin characters
  81. errMsg += " - must have at least 2 letters or numbers"
  82. }
  83. return impart.HTTPError{http.StatusBadRequest, errMsg + "."}
  84. }
  85. if app.db.PostIDExists(finalUsername) {
  86. return impart.HTTPError{http.StatusConflict, "Username is already taken."}
  87. }
  88. var un string
  89. err := app.db.QueryRow("SELECT username FROM users WHERE username = ?", finalUsername).Scan(&un)
  90. switch {
  91. case err == sql.ErrNoRows:
  92. return impart.WriteSuccess(w, finalUsername, http.StatusOK)
  93. case err != nil:
  94. log.Error("Couldn't SELECT username: %v", err)
  95. return impart.HTTPError{http.StatusInternalServerError, "We messed up."}
  96. }
  97. // Username was found, so it's taken
  98. return impart.HTTPError{http.StatusConflict, "Username is already taken."}
  99. }
  100. func getValidUsername(app *app, reqName, prevName string) (string, *impart.HTTPError) {
  101. // Check if username is okay
  102. finalUsername := getSlug(reqName, "")
  103. if finalUsername == "" {
  104. errMsg := "Invalid username"
  105. if reqName != "" {
  106. // Username was provided, but didn't convert into valid latin characters
  107. errMsg += " - must have at least 2 letters or numbers"
  108. }
  109. return "", &impart.HTTPError{http.StatusBadRequest, errMsg + "."}
  110. }
  111. if finalUsername == prevName {
  112. return "", &impart.HTTPError{http.StatusNotModified, "Username unchanged."}
  113. }
  114. if app.db.PostIDExists(finalUsername) {
  115. return "", &impart.HTTPError{http.StatusConflict, "Username is already taken."}
  116. }
  117. var un string
  118. err := app.db.QueryRow("SELECT username FROM users WHERE username = ?", finalUsername).Scan(&un)
  119. switch {
  120. case err == sql.ErrNoRows:
  121. return finalUsername, nil
  122. case err != nil:
  123. log.Error("Couldn't SELECT username: %v", err)
  124. return "", &impart.HTTPError{http.StatusInternalServerError, "We messed up."}
  125. }
  126. // Username was found, so it's taken
  127. return "", &impart.HTTPError{http.StatusConflict, "Username is already taken."}
  128. }