package handlers import ( "errors" "github.com/Pena-Co-Ltd/amocrm_templategen_back/dal/model" "github.com/Pena-Co-Ltd/amocrm_templategen_back/tools" "github.com/gorilla/schema" "golang.org/x/oauth2" "net/http" "strconv" "time" ) type ReqAmoSaveToken struct { AccessToken string `json:"access_token" schema:"access_token"` Code string `json:"code" schema:"code"` ClientID string `json:"client_id" schema:"client_id"` ExpiresIn int64 `json:"expires_in" schema:"expires_in"` TokenType string `json:"token_type" schema:"token_type"` RefreshToken string `json:"refresh_token" schema:"refresh_token"` State string `json:"state" schema:"state"` FromWidget string `json:"from_widget" schema:"from_widget"` Referer string `json:"referer" schema:"referer"` Platform string `json:"platform" schema:"platform"` // Вообще без понятия что это } func (h *Handlers) AmoSaveToken(w http.ResponseWriter, r *http.Request) { var req ReqAmoSaveToken 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, http.StatusBadRequest) return } if req.AccessToken == "" && req.Code == "" { err = errors.New("token required") h.reportError(w, err, http.StatusBadRequest) return } if req.State == "" { err = errors.New("state required") h.reportError(w, err, http.StatusBadRequest) return } var state tools.StateToken err = tools.DecryptTokenRC4(req.State, &state) if err != nil { h.reportError(w, err, http.StatusUnauthorized) return } token := &oauth2.Token{ AccessToken: req.AccessToken, RefreshToken: req.RefreshToken, TokenType: req.TokenType, Expiry: time.Now().Add(time.Duration(req.ExpiresIn) * time.Second), } amoClient, err := h.Amo.NewClient(r.Context(), req.Referer, token, req.Code) if err != nil { h.reportError(w, err, http.StatusForbidden) return } token = amoClient.Token amoAcc, err := amoClient.GetAccount() if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } // Insert/Update token in DB _, err = h.dal.Amo.InsertOrUpdate(r.Context(), &model.Amo{ UserID: state.UserID, AccountID: strconv.FormatInt(amoAcc.Id, 10), AccessToken: token.AccessToken, RefreshToken: token.RefreshToken, FromWidget: req.FromWidget, Referer: req.Referer, Subdomain: amoAcc.Subdomain, ExpiresIn: token.Expiry, TokenType: token.TokenType, }) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } http.Redirect(w, r, state.RedirectUrl, http.StatusPermanentRedirect) } type RespAmoState struct { GenCount int `json:"gen_count"` AuthYandexUrl string `json:"auth_yandex_url"` AuthGoogleUrl string `json:"auth_google_url"` AuthAmoUrl string `json:"auth_amo_url"` Storages map[string]interface{} `json:"storages"` Visibility []int64 `json:"visibility"` Creation []int64 `json:"creation"` Delete []int64 `json:"delete"` } // AmoState - получить актуальное состояние аккаунта пользователя в Amo func (h *Handlers) AmoState(w http.ResponseWriter, r *http.Request, redirectUrn string) { // TODO: get pena jwt amoData := getAmoByJwt(r) if amoData == nil { h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized) return } yaStorages, err := h.dal.YaDisk.GetListByUserID(r.Context(), amoData.UserID) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } gStorages, err := h.dal.GDisk.GetListByUserID(r.Context(), amoData.UserID) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } storages := map[string]interface{}{ "yadisk": yaStorages, "gdisk": gStorages, } redirectUri := "https://" + amoData.Referer + redirectUrn authYandexUrl, err := h.YaDisk.GenerateOAuthUrl(amoData.UserID, redirectUri) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } authGoogleUrl, err := h.GDisk.GenerateOAuthUrl(amoData.UserID, redirectUri) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } authAmoUrl, err := h.Amo.GenerateOAuthUrl(amoData.UserID, redirectUri) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } resp := RespAmoState{ GenCount: 97, AuthYandexUrl: authYandexUrl, AuthGoogleUrl: authGoogleUrl, AuthAmoUrl: authAmoUrl, Storages: storages, Visibility: amoData.AccessRules.Visibility, Creation: amoData.AccessRules.Creation, Delete: amoData.AccessRules.Delete, } sendResponse(w, 200, resp) } type ReqAmoAccessRules struct { Visibility []int64 `json:"visibility"` Creation []int64 `json:"creation"` Delete []int64 `json:"delete"` } // AmoAccessRules - задать правила для пользователя func (h *Handlers) AmoAccessRules(w http.ResponseWriter, r *http.Request) { var req ReqAmoAccessRules amoData := getAmoByJwt(r) if amoData == nil { h.reportError(w, ErrorUnauthorized, http.StatusUnauthorized) return } isAdmin := r.Context().Value("amoIsAdmin").(bool) if !isAdmin { h.reportError(w, errors.New("need admin access"), http.StatusUnauthorized) return } err := decodePost(&req, r) if err != nil { h.reportError(w, err, http.StatusBadRequest) return } if (req.Visibility == nil || len(req.Visibility) == 0) && (req.Creation == nil || len(req.Creation) == 0) && (req.Delete == nil || len(req.Delete) == 0) { h.reportError(w, errors.New("empty request"), http.StatusBadRequest) return } err = h.dal.Amo.UpdateAccessRules(r.Context(), amoData.ID, &model.AmoAccessRules{ Visibility: req.Visibility, Creation: req.Creation, Delete: req.Delete, }) if err != nil { h.reportError(w, err, http.StatusInternalServerError) return } w.WriteHeader(200) }