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) }