app_avatar_test.go 4.2 KB

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