app_avatar_test.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package test_test
  2. import (
  3. "crypto/rand"
  4. "crypto/sha256"
  5. "encoding/hex"
  6. "fmt"
  7. "io"
  8. "log"
  9. "os"
  10. "time"
  11. "git.ali33.ru/fcg-xvii/go-tools/json"
  12. "git.ali33.ru/fcg-xvii/rest"
  13. )
  14. // AvatarApp по запросу веб сервера создает объекты команд и возвращает их серверу
  15. type AvatarApp struct {
  16. imagePath string
  17. }
  18. // ImagePath формирует путь к файлу аватара пользователя по его хэшу
  19. func (s *AvatarApp) ImagePath(hash string) string {
  20. return fmt.Sprintf("%s/%s.jpg", s.imagePath, hash)
  21. }
  22. // Executer создает команду по запросу веб сервера
  23. func (s *AvatarApp) Executer(r *rest.Request) (rest.IExecuter, bool) {
  24. // проверяем входной URL
  25. switch r.RPath() {
  26. case "/register": // Регистрация нового порльзователя
  27. return &RequestReg{}, true
  28. }
  29. return nil, false
  30. }
  31. ///////////////////////////////////////
  32. // RequestReg реализует команду регистрации нового пользователя.
  33. type RequestReg struct {
  34. // имя пользователя
  35. Name string `rest:"required" json:"name"`
  36. }
  37. // HashString генерирует хэш для строки.
  38. // Возвращает хэш-строку и возможную ошибку.
  39. func (s *RequestReg) HashString() (string, error) {
  40. data := make([]byte, 16)
  41. if _, err := rand.Read(data); err != nil {
  42. return "", err
  43. }
  44. hash := sha256.Sum256(data)
  45. hashString := hex.EncodeToString(hash[:])
  46. return hashString, nil
  47. }
  48. // Validate проверяет запрос на корректность входных данных (не обязательный метод).
  49. func (s *RequestReg) Validate(r *rest.Request) *rest.Response {
  50. if r.IsAuth() {
  51. return rest.ResponseError("AlreadyAuth", nil, 500)
  52. }
  53. return nil
  54. }
  55. // Execute реализует логику команды. Выполняется после валидации
  56. func (s *RequestReg) Execute(r *rest.Request) *rest.Response {
  57. // генерируем хэш нового пользователя
  58. hash, err := s.HashString()
  59. if err != nil {
  60. return rest.ResponseErrorMessage("HashGenerate", err.Error(), 500)
  61. }
  62. // создаем токен авторизации (бессрочный)
  63. token, err := r.GenerateToken(
  64. json.Map{
  65. "name": s.Name,
  66. "hash": hash,
  67. },
  68. 0,
  69. )
  70. if err != nil {
  71. return rest.ResponseErrorMessage("AuthTokenGenerate", err.Error(), 500)
  72. }
  73. // создаем ответ
  74. resp := rest.NewResponse()
  75. resp.KeySet("token", token)
  76. return resp
  77. }
  78. // swagger:response registrationResponse
  79. type RegistrationResponseWrapper struct {
  80. // Встроенный объект ответа
  81. //
  82. // in: body
  83. Body struct {
  84. // Токен авторизации для пользователя
  85. Token string `json:"token"`
  86. }
  87. }
  88. ////////////////////////////////////////////////////////////////
  89. type RequestUpload struct {
  90. app *AvatarApp
  91. AvatarJpg io.Reader `rest:"required;file"`
  92. }
  93. func (s *RequestUpload) Validate(r *rest.Request) *rest.Response {
  94. if !r.IsAuth() {
  95. return rest.ResponseError("NotAuth", nil, 500)
  96. }
  97. return nil
  98. }
  99. func (s *RequestUpload) Execute(r *rest.Request) *rest.Response {
  100. mAuth := r.Auth()
  101. // открываем файл для обновления
  102. f, err := os.OpenFile(s.app.ImagePath(mAuth.String("hash", "")), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
  103. if err != nil {
  104. return rest.ResponseErrorMessage("AvatarFileOpen", err.Error(), 500)
  105. }
  106. defer f.Close()
  107. // обновляем файл
  108. if _, err = io.Copy(f, s.AvatarJpg); err != nil {
  109. return rest.ResponseErrorMessage("AvatarFileWrite", err.Error(), 500)
  110. }
  111. // файл обновлён
  112. resp := rest.NewResponse()
  113. resp.KeySet("ok", true)
  114. return resp
  115. }
  116. /////////////////////////////////////////////////////////////////
  117. func RestNew() {
  118. // адрес и порт веб сервера
  119. addr := ":7000"
  120. // ключ шифрования токена авторизации
  121. secret := []byte("top-secret")
  122. // люъект приложения (rest.IApp)
  123. app := &AvatarApp{}
  124. // создание сервера
  125. rest := rest.New(addr, secret, app)
  126. // запуск
  127. if err := rest.Listen(time.Second); err != nil {
  128. log.Fatal(err)
  129. }
  130. }
  131. func ExampleRestNew() {
  132. RestNew()
  133. ch := make(chan struct{})
  134. <-ch
  135. }