package handler import ( "context" "encoding/json" "io" "net/http" "net/url" cmsstorage "go.unistack.org/cms-service/storage" "go.unistack.org/micro/v4" "go.unistack.org/micro/v4/errors" "go.unistack.org/unistack-org/pkgdash/config" pb "go.unistack.org/unistack-org/pkgdash/proto" cligit "go.unistack.org/unistack-org/pkgdash/service/client_git" "go.unistack.org/unistack-org/pkgdash/storage" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" ) type Handler struct { svc micro.Service store storage.Storage writer writer protojson.MarshalOptions protojson.UnmarshalOptions git cligit.Client chanUrl chan *pb.AddPackageReq } func (h *Handler) ListPackage(w http.ResponseWriter, r *http.Request) { ctx := r.Context() logger := h.svc.Logger() logger.Debug(ctx, "Start getListPackage") dbRsp, err := h.store.ListPackage(ctx) if err != nil { logger.Errorf(ctx, "error db response: %v", err) h.writer.Response(ctx, w, err) return } rsp := new(pb.ListPackageRsp) rsp.Packages = dbRsp.Decode() logger.Debug(ctx, "Success finish getListPackage") h.writer.Response(ctx, w, rsp) } func (h *Handler) UpdatePackage(w http.ResponseWriter, r *http.Request) { ctx := r.Context() logger := h.svc.Logger() logger.Debug(ctx, "Start UpdatePackage") defer r.Body.Close() all, err := io.ReadAll(r.Body) if err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewInternalError(err)) return } req := new(pb.UpdatePackageReq) if err = h.Unmarshal(all, req); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewUnmarshalError(err)) return } if err = req.Validate(); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewValidationError(err)) return } if err = h.store.UpdatePackage(ctx, req); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewInternalError(err)) return } logger.Debug(ctx, "Success finish UpdatePackage") } func (h *Handler) AddComment(w http.ResponseWriter, r *http.Request) { ctx := r.Context() logger := h.svc.Logger() logger.Debug(ctx, "Start AddComment") defer r.Body.Close() all, err := io.ReadAll(r.Body) if err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewInternalError(err)) return } req := new(pb.AddCommentReq) if err = h.Unmarshal(all, req); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewUnmarshalError(err)) return } if err = req.Validate(); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewValidationError(err)) return } if err = h.store.AddComment(ctx, req); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewInternalError(err)) return } logger.Debug(ctx, "Success finish addComment") } func (h *Handler) AddPackage(w http.ResponseWriter, r *http.Request) { ctx := r.Context() logger := h.svc.Logger() logger.Debug(ctx, "Start AddPackage") defer r.Body.Close() all, err := io.ReadAll(r.Body) if err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewInternalError(err)) return } req := new(pb.AddPackageReq) if err = h.Unmarshal(all, req); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewUnmarshalError(err)) return } if err = req.Validate(); err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewValidationError(err)) return } if h.git.IsClose() { logger.Error(ctx, "chan is closed") } else { h.chanUrl <- req } logger.Debug(ctx, "Success finish addPackage") } func (h *Handler) GetModule(w http.ResponseWriter, r *http.Request) { ctx := r.Context() logger := h.svc.Logger() logger.Debug(ctx, "Start GetModule") req := new(pb.GetModuleReq) if err := URLValuesToProto(r.URL.Query(), req); err != nil { logger.Errorf(ctx, "Required parameter missing: %v", err) h.writer.Response(ctx, w, err) return } modules, err := h.store.GetModule(ctx, req) if err != nil { logger.Error(ctx, err) h.writer.Response(ctx, w, NewInternalError(err)) return } rsp := &pb.GetModuleRsp{Modules: modules.Decode()} h.writer.Response(ctx, w, rsp) logger.Debug(ctx, "Success finish getModule") } func URLValuesToProto(vals url.Values, msg proto.Message) error { params := make(map[string]interface{}) var err error for k, v := range vals { if len(v) == 0 { continue } switch k { case "id[]": params[k] = v default: params[k] = v[0] } } b, err := json.Marshal(params) if err != nil { return NewUnmarshalError(err) } if err = protojson.Unmarshal(b, msg); err != nil { return NewUnmarshalError(err) } return nil } func NewHandler(svc micro.Service, w writer, client cligit.Client) *Handler { h := &Handler{ svc: svc, writer: w, git: client, } h.EmitUnpopulated = true h.UseProtoNames = false return h } func (h *Handler) Init(ctx context.Context) error { store := cmsstorage.InterfaceFromContext(h.svc.Options().Context) if store == nil { return cmsstorage.ErrMissingStorage } st, ok := store.(storage.Storage) if !ok { return errors.New(config.ServiceName, "error init storage", 1) } h.chanUrl = h.git.Run(ctx, st) h.store = st return nil }