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.
 
 
 
 
 

145 lines
4.1 KiB

  1. /*
  2. * Copyright © 2018-2019 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. to := "/"
  44. if ur.InviteCode != "" {
  45. to = "/invite/" + ur.InviteCode
  46. }
  47. _, err := signupWithRegistration(app, ur, w, r)
  48. if err != nil {
  49. if err, ok := err.(impart.HTTPError); ok {
  50. session, _ := app.sessionStore.Get(r, cookieName)
  51. if session != nil {
  52. session.AddFlash(err.Message)
  53. session.Save(r, w)
  54. return impart.HTTPError{http.StatusFound, to}
  55. }
  56. }
  57. return err
  58. }
  59. return impart.HTTPError{http.StatusFound, to}
  60. }
  61. // { "username": "asdf" }
  62. // result: { code: 204 }
  63. func handleUsernameCheck(app *App, w http.ResponseWriter, r *http.Request) error {
  64. reqJSON := IsJSON(r.Header.Get("Content-Type"))
  65. // Get params
  66. var d struct {
  67. Username string `json:"username"`
  68. }
  69. if reqJSON {
  70. decoder := json.NewDecoder(r.Body)
  71. err := decoder.Decode(&d)
  72. if err != nil {
  73. log.Error("Couldn't decode username check: %v\n", err)
  74. return ErrBadFormData
  75. }
  76. } else {
  77. return impart.HTTPError{http.StatusNotAcceptable, "Must be JSON request"}
  78. }
  79. // Check if username is okay
  80. finalUsername := getSlug(d.Username, "")
  81. if finalUsername == "" {
  82. errMsg := "Invalid username"
  83. if d.Username != "" {
  84. // Username was provided, but didn't convert into valid latin characters
  85. errMsg += " - must have at least 2 letters or numbers"
  86. }
  87. return impart.HTTPError{http.StatusBadRequest, errMsg + "."}
  88. }
  89. if app.db.PostIDExists(finalUsername) {
  90. return impart.HTTPError{http.StatusConflict, "Username is already taken."}
  91. }
  92. var un string
  93. err := app.db.QueryRow("SELECT username FROM users WHERE username = ?", finalUsername).Scan(&un)
  94. switch {
  95. case err == sql.ErrNoRows:
  96. return impart.WriteSuccess(w, finalUsername, http.StatusOK)
  97. case err != nil:
  98. log.Error("Couldn't SELECT username: %v", err)
  99. return impart.HTTPError{http.StatusInternalServerError, "We messed up."}
  100. }
  101. // Username was found, so it's taken
  102. return impart.HTTPError{http.StatusConflict, "Username is already taken."}
  103. }
  104. func getValidUsername(app *App, reqName, prevName string) (string, *impart.HTTPError) {
  105. // Check if username is okay
  106. finalUsername := getSlug(reqName, "")
  107. if finalUsername == "" {
  108. errMsg := "Invalid username"
  109. if reqName != "" {
  110. // Username was provided, but didn't convert into valid latin characters
  111. errMsg += " - must have at least 2 letters or numbers"
  112. }
  113. return "", &impart.HTTPError{http.StatusBadRequest, errMsg + "."}
  114. }
  115. if finalUsername == prevName {
  116. return "", &impart.HTTPError{http.StatusNotModified, "Username unchanged."}
  117. }
  118. if app.db.PostIDExists(finalUsername) {
  119. return "", &impart.HTTPError{http.StatusConflict, "Username is already taken."}
  120. }
  121. var un string
  122. err := app.db.QueryRow("SELECT username FROM users WHERE username = ?", finalUsername).Scan(&un)
  123. switch {
  124. case err == sql.ErrNoRows:
  125. return finalUsername, nil
  126. case err != nil:
  127. log.Error("Couldn't SELECT username: %v", err)
  128. return "", &impart.HTTPError{http.StatusInternalServerError, "We messed up."}
  129. }
  130. // Username was found, so it's taken
  131. return "", &impart.HTTPError{http.StatusConflict, "Username is already taken."}
  132. }