
- Добавлена проверка токенов при запросе /amo/state - Исправлена работа с amo oauth-токенами - Добавлены примеры шаблонизатора - Добавлена возможность генерации и создания шаблонов из примеров - В ответ генератора добавлены ссылки для скачивания сгенерированных файлов - Вернул очиску temp после загрузки файла в Яндекс.Диск - yadisk.UploadResources - добавлено ожидание окончания отправки файла и таймаут в 5 секунд для отправки файла - Добавлены эндпоинты для загрузки файлов в хранилища - Актуализирован генератор по вебхуку - Обновлены генератор по данным - Обновлен генератор по лиду
516 lines
13 KiB
Go
516 lines
13 KiB
Go
package handlers
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model"
|
||
GDisk "github.com/Pena-Co-Ltd/amocrm_templategen_back/gdisk"
|
||
"github.com/Pena-Co-Ltd/amocrm_templategen_back/templategen"
|
||
"github.com/Pena-Co-Ltd/amocrm_templategen_back/tools"
|
||
"github.com/gorilla/schema"
|
||
"go.uber.org/zap"
|
||
"google.golang.org/api/drive/v3"
|
||
"io"
|
||
"net/http"
|
||
"os"
|
||
)
|
||
|
||
type ReqGDiskSaveToken struct {
|
||
State string `json:"state" schema:"state"`
|
||
Code string `json:"code" schema:"code"`
|
||
Scope string `json:"scope" schema:"scope"`
|
||
}
|
||
|
||
// GDiskSaveToken - сохраняет токен авторизации
|
||
func (h *Handlers) GDiskSaveToken(w http.ResponseWriter, r *http.Request) {
|
||
var req ReqGDiskSaveToken
|
||
|
||
err := r.ParseForm()
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
err = schema.NewDecoder().Decode(&req, r.Form)
|
||
if err != nil {
|
||
h.reportError(w, err, 500)
|
||
return
|
||
}
|
||
|
||
if req.State == "" {
|
||
err = errors.New("GDiskErr: got empty state")
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.Code == "" {
|
||
err = errors.New("GDiskErr: got empty code")
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
// get user
|
||
var state tools.StateToken
|
||
err = tools.DecryptTokenRC4(req.State, &state)
|
||
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
// generate token
|
||
token, err := h.GDisk.GetToken(r.Context(), req.Code)
|
||
if err != nil {
|
||
h.reportError(w, err, 500)
|
||
return
|
||
}
|
||
|
||
gDisk, err := h.GDisk.NewClient(r.Context(), token)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
token = gDisk.Token
|
||
|
||
gUser, err := gDisk.GetUserInfo()
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// Make default directories in Google Drive
|
||
gDiskData, err := h.dal.GDisk.GetByEmail(r.Context(), gUser.EmailAddress)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
var defaultId, defaultName, templateId, templateName, saveId, saveName string
|
||
if gDiskData != nil {
|
||
defaultId = gDiskData.DefaultFolderID
|
||
defaultName = gDiskData.DefaultFolder
|
||
templateId = gDiskData.TemplateFolderID
|
||
templateName = gDiskData.TemplateFolder
|
||
saveId = gDiskData.SaveFolderID
|
||
saveName = gDiskData.SaveFolder
|
||
}
|
||
|
||
defaultFolder, templateFolder, saveFolder, err := gDisk.MakeDefaultDirs(defaultId, defaultName, templateId,
|
||
templateName, saveId, saveName)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// Insert/Update token in DB
|
||
_, err = h.dal.GDisk.InsertOrUpdate(r.Context(), &model.GDisk{
|
||
UserID: state.UserID,
|
||
Name: fmt.Sprintf("Google Disk (%v)", gUser.EmailAddress),
|
||
DisplayName: gUser.DisplayName,
|
||
Email: gUser.EmailAddress,
|
||
PhotoLink: gUser.PhotoLink,
|
||
AccessToken: token.AccessToken,
|
||
RefreshToken: token.RefreshToken,
|
||
ExpiresIn: token.Expiry,
|
||
TokenType: token.TokenType,
|
||
DefaultFolder: defaultFolder.Name,
|
||
DefaultFolderID: defaultFolder.Id,
|
||
TemplateFolder: templateFolder.Name,
|
||
TemplateFolderID: templateFolder.Id,
|
||
SaveFolder: saveFolder.Name,
|
||
SaveFolderID: saveFolder.Id,
|
||
})
|
||
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
http.Redirect(w, r, state.RedirectUrl, http.StatusPermanentRedirect)
|
||
}
|
||
|
||
type ReqGDiskSetSettings struct {
|
||
ID string `json:"id"`
|
||
Name string `json:"name"` // Пользовательское название хранилища
|
||
DefaultFolder string `json:"default_folder"`
|
||
DefaultFolderId string `json:"default_folder_id"`
|
||
TemplateFolder string `json:"template_folder"`
|
||
TemplateFolderID string `json:"template_folder_id"`
|
||
SaveFolder string `json:"save_folder"`
|
||
SaveFolderID string `json:"save_folder_id"`
|
||
}
|
||
|
||
func (h *Handlers) GDiskSetSettings(w http.ResponseWriter, r *http.Request) {
|
||
var req ReqGDiskSetSettings
|
||
|
||
amoData := getAmoByJwt(r)
|
||
if amoData == nil {
|
||
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
err := decodePost(&req, r)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.ID == "" {
|
||
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
err = h.dal.GDisk.Update(r.Context(), &model.GDisk{
|
||
ID: req.ID,
|
||
Name: req.Name,
|
||
DefaultFolder: req.DefaultFolder,
|
||
DefaultFolderID: req.DefaultFolderId,
|
||
TemplateFolder: req.TemplateFolder,
|
||
TemplateFolderID: req.TemplateFolderID,
|
||
SaveFolder: req.SaveFolder,
|
||
SaveFolderID: req.SaveFolderID,
|
||
})
|
||
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
sendResponse(w, 200, nil)
|
||
}
|
||
|
||
func (h *Handlers) GDiskGetFile(w http.ResponseWriter, r *http.Request) {
|
||
|
||
}
|
||
|
||
type ReqGDiskGetResources struct {
|
||
ID string `json:"id"` // ID хранилища
|
||
FolderID string `json:"folder_id"` // Folder id
|
||
Name string `json:"name,omitempty"` // Folder name
|
||
ParentID string `json:"parent_id,omitempty"` // Parent folder id
|
||
}
|
||
|
||
// GDiskGetResources - возвращает поиск по папке, включая список её файлов и папок.
|
||
// Поведение:
|
||
// - Если не указан FolderID и Name возвращает корневой каталог Google Drive
|
||
// - Если указан только Name ищет файл\папку по всему Google Drive
|
||
// - Если указан Name и ParentID ищет файл\папку только в родителе
|
||
// - ParentID игнорируется без Name
|
||
func (h *Handlers) GDiskGetResources(w http.ResponseWriter, r *http.Request) {
|
||
var req ReqGDiskGetResources
|
||
|
||
amoData := getAmoByJwt(r)
|
||
|
||
if amoData == nil {
|
||
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
err := decodePost(&req, r)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.ID == "" {
|
||
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
gdiskInfo, err := h.dal.GDisk.GetByID(r.Context(), req.ID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
if gdiskInfo == nil {
|
||
h.reportError(w, errors.New("gdisk info not found"), http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
client, err := h.GDisk.NewClient(r.Context(), gdiskInfo.Token())
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
var res *drive.FileList
|
||
|
||
if req.Name != "" {
|
||
res, err = client.GetResourcesByName(req.Name, req.ParentID)
|
||
} else {
|
||
res, err = client.GetResources(req.FolderID)
|
||
}
|
||
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
sendResponse(w, 200, res)
|
||
}
|
||
|
||
type ReqGDiskGetDirTemplate struct {
|
||
Email string `json:"email"` // Required. Google Email ?
|
||
}
|
||
|
||
// GDiskGetDirTemplate - возвращает данные по папке template, включая список её файлов и папок
|
||
func (h *Handlers) GDiskGetDirTemplate(w http.ResponseWriter, r *http.Request) {
|
||
var req ReqGDiskGetDirTemplate
|
||
|
||
err := decodePost(&req, r)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.Email == "" {
|
||
h.reportError(w, errors.New("email required"), http.StatusBadRequest)
|
||
}
|
||
|
||
amoData := getAmoByJwt(r)
|
||
|
||
if amoData == nil {
|
||
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
gdiskInfo, err := h.dal.GDisk.GetByEmail(r.Context(), req.Email)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
if gdiskInfo == nil {
|
||
h.reportError(w, errors.New("gdisk info not found"), http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
if gdiskInfo.Token() == nil {
|
||
h.reportError(w, errors.New("google token invalid"), http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
client, err := h.GDisk.NewClient(r.Context(), gdiskInfo.Token())
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
dir, err := client.GetResources(gdiskInfo.TemplateFolderID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
sendResponse(w, 200, dir)
|
||
}
|
||
|
||
// GDiskGetList - возвращает список хранилищ Google закрепленных за пользователем по его UserID из JWT
|
||
func (h *Handlers) GDiskGetList(w http.ResponseWriter, r *http.Request) {
|
||
amoData := getAmoByJwt(r)
|
||
|
||
if amoData == nil {
|
||
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
gdiskInfo, err := h.dal.GDisk.GetListByUserID(r.Context(), amoData.UserID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
sendResponse(w, http.StatusOK, gdiskInfo)
|
||
}
|
||
|
||
type ReqGDiskPutResources struct {
|
||
ID string `json:"ID"`
|
||
Name string `json:"name"`
|
||
ParentID string `json:"parent_id"`
|
||
}
|
||
|
||
// GDiskPutResources - создать папку в хранилище
|
||
func (h *Handlers) GDiskPutResources(w http.ResponseWriter, r *http.Request) {
|
||
var req ReqGDiskPutResources
|
||
|
||
amoData := getAmoByJwt(r)
|
||
|
||
if amoData == nil {
|
||
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
err := decodePost(&req, r)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.ID == "" {
|
||
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.Name == "" {
|
||
h.reportError(w, errors.New("name required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
gdiskInfo, err := h.dal.GDisk.GetByID(r.Context(), req.ID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
if gdiskInfo == nil {
|
||
h.reportError(w, errors.New("gdisk info not found"), http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
client, err := h.GDisk.NewClient(r.Context(), gdiskInfo.Token())
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
file, err := client.PutResources(req.Name, req.ParentID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
sendResponse(w, 200, file)
|
||
}
|
||
|
||
type ReqGDiskUploadResources struct {
|
||
ID string `json:"id" schema:"id"` // Storage ID
|
||
ParentID string `json:"parent_id" schema:"parent_id"`
|
||
}
|
||
|
||
// GDiskUploadResources - загрузить файл в хранилище
|
||
func (h *Handlers) GDiskUploadResources(w http.ResponseWriter, r *http.Request) {
|
||
// Check form
|
||
fileData, fileHeader, err := r.FormFile("file")
|
||
defer fileData.Close()
|
||
|
||
var req ReqGDiskUploadResources
|
||
err = schema.NewDecoder().Decode(&req, r.Form)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.ID == "" {
|
||
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
var maxSize int64 = 10 << 20 // mb
|
||
if fileHeader.Size > maxSize {
|
||
h.reportError(w, errors.New("max size 10 mb"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
// Download file to the temp
|
||
|
||
downloadPath := fmt.Sprintf("%v/%v", templategen.TempDownloaded, fileHeader.Filename)
|
||
|
||
out, err := os.Create(downloadPath)
|
||
defer out.Close()
|
||
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
_, err = io.Copy(out, fileData)
|
||
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// Upload file to the storage
|
||
storage, err := h.dal.GDisk.GetByID(r.Context(), req.ID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
client, err := h.GDisk.NewClient(r.Context(), storage.Token())
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
h.logger.Info("INFO", zap.String("downloadPath", downloadPath))
|
||
|
||
_, err = client.UploadFile(downloadPath, GDisk.MimeTypeDocx, req.ParentID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
w.WriteHeader(http.StatusOK)
|
||
}
|
||
|
||
type ReqGDiskDeleteResources struct {
|
||
ID string `json:"id"`
|
||
FolderID string `json:"folder_id"`
|
||
}
|
||
|
||
// GDiskDeleteResources - удалить папку\файл
|
||
func (h *Handlers) GDiskDeleteResources(w http.ResponseWriter, r *http.Request) {
|
||
var req ReqGDiskDeleteResources
|
||
|
||
amoData := getAmoByJwt(r)
|
||
|
||
if amoData == nil {
|
||
h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized)
|
||
return
|
||
}
|
||
|
||
err := decodePost(&req, r)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.ID == "" {
|
||
h.reportError(w, errors.New("id required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
if req.FolderID == "" {
|
||
h.reportError(w, errors.New("folder_id required"), http.StatusBadRequest)
|
||
return
|
||
}
|
||
|
||
gdiskInfo, err := h.dal.GDisk.GetByID(r.Context(), req.ID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
if gdiskInfo == nil {
|
||
h.reportError(w, errors.New("gdisk info not found"), http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
client, err := h.GDisk.NewClient(r.Context(), gdiskInfo.Token())
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusForbidden)
|
||
return
|
||
}
|
||
|
||
err = client.DeleteResources(req.FolderID)
|
||
if err != nil {
|
||
h.reportError(w, err, http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
w.WriteHeader(http.StatusOK)
|
||
}
|