From cfa11daa57bb6b2b898beb8472a5d08cce0703fb Mon Sep 17 00:00:00 2001 From: zengchen1024 Date: Wed, 26 Jul 2023 10:49:21 +0800 Subject: [PATCH 1/4] support dco --- controllers/dco.go | 127 +++++++++++ controllers/dco_link.go | 134 +++++++++++ controllers/link.go | 4 +- controllers/token.go | 6 - models/adapter.go | 44 ++++ models/dco.go | 16 ++ models/error.go | 7 +- models/init.go | 28 +++ routers/commentsRouter.go | 74 +++++- routers/router.go | 11 + signing.go | 17 ++ signing/adapter/cla.go | 14 +- signing/adapter/dco.go | 96 ++++++++ signing/adapter/dco_link.go | 173 ++++++++++++++ signing/adapter/error.go | 17 ++ signing/adapter/link.go | 6 +- signing/app/dco.go | 107 +++++++++ signing/app/dco_dto.go | 23 ++ signing/app/dco_link.go | 141 ++++++++++++ signing/app/dco_link_dto.go | 33 +++ signing/domain/claservice/service.go | 15 +- signing/domain/error.go | 8 + signing/domain/link.go | 6 + swagger/swagger.json | 328 ++++++++++++++++++++++++++- swagger/swagger.yml | 234 ++++++++++++++++++- 25 files changed, 1635 insertions(+), 34 deletions(-) create mode 100644 controllers/dco.go create mode 100644 controllers/dco_link.go create mode 100644 models/dco.go create mode 100644 signing/adapter/dco.go create mode 100644 signing/adapter/dco_link.go create mode 100644 signing/app/dco.go create mode 100644 signing/app/dco_dto.go create mode 100644 signing/app/dco_link.go create mode 100644 signing/app/dco_link_dto.go diff --git a/controllers/dco.go b/controllers/dco.go new file mode 100644 index 0000000..76bf664 --- /dev/null +++ b/controllers/dco.go @@ -0,0 +1,127 @@ +package controllers + +import ( + "strings" + + "github.com/opensourceways/app-cla-server/models" +) + +type DCOController struct { + baseController +} + +func (ctl *DCOController) Prepare() { + if ctl.isGetRequest() && strings.HasSuffix(ctl.routerPattern(), "/:link_id/:id") { + ctl.apiPrepare("") + } else { + ctl.apiPrepare(PermissionOwnerOfOrg) + } +} + +// @Title Add +// @Description add dco +// @Tags DCO +// @Accept json +// @Param body body models.DCOCreateOpt true "body for adding dco" +// @Success 201 {object} controllers.respData +// @router /:link_id [post] +func (ctl *DCOController) Add() { + action := "add dco" + linkID := ctl.GetString(":link_id") + + pl, fr := ctl.tokenPayloadBasedOnCodePlatform() + if fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + if fr := pl.isOwnerOfLink(linkID); fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + + input := &models.DCOCreateOpt{} + if fr := ctl.fetchInputPayloadFromFormData(input); fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + + if err := models.AddDCOInstance(linkID, input); err != nil { + ctl.sendModelErrorAsResp(err, action) + } else { + ctl.sendSuccessResp(action, "successfully") + } +} + +// @Title Delete +// @Description delete dco +// @Tags DCO +// @Accept json +// @Param link_id path string true "link id" +// @Param id path string true "dco id" +// @Success 204 {object} controllers.respData +// @router /:link_id/:id [delete] +func (ctl *DCOController) Delete() { + action := "delete dco" + linkID := ctl.GetString(":link_id") + dcoId := ctl.GetString(":id") + + pl, fr := ctl.tokenPayloadBasedOnCodePlatform() + if fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + if fr := pl.isOwnerOfLink(linkID); fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + + if err := models.RemoveDCOInstance(linkID, dcoId); err != nil { + ctl.sendModelErrorAsResp(err, action) + + return + } + + ctl.sendSuccessResp(action, "successfully") +} + +// @Title DownloadPDF +// @Description get dco pdf +// @Tags DCO +// @Accept json +// @Param link_id path string true "link id" +// @Param id path string true "dco id" +// @Success 200 +// @router /:link_id/:id [get] +func (ctl *DCOController) DownloadPDF() { + ctl.downloadFile(models.DCOFile( + ctl.GetString(":link_id"), ctl.GetString(":id"), + )) +} + +// @Title List +// @Description list dcos of link +// @Tags DCO +// @Accept json +// @Param link_id path string true "link id" +// @Success 200 {object} models.CLADetail +// @router /:link_id [get] +func (ctl *DCOController) List() { + action := "list dco" + linkID := ctl.GetString(":link_id") + + pl, fr := ctl.tokenPayloadBasedOnCodePlatform() + if fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + if fr := pl.isOwnerOfLink(linkID); fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + + if dcos, merr := models.ListDCOInstances(linkID); merr != nil { + ctl.sendModelErrorAsResp(merr, action) + } else { + ctl.sendSuccessResp(action, dcos) + } +} diff --git a/controllers/dco_link.go b/controllers/dco_link.go new file mode 100644 index 0000000..316df87 --- /dev/null +++ b/controllers/dco_link.go @@ -0,0 +1,134 @@ +package controllers + +import ( + "strings" + + "github.com/opensourceways/app-cla-server/models" +) + +type DCOLinkController struct { + baseController +} + +func (ctl *DCOLinkController) Prepare() { + if strings.HasSuffix(ctl.routerPattern(), "dcos") { + ctl.apiPrepare("") + } else { + ctl.apiPrepare(PermissionOwnerOfOrg) + } +} + +// @Title Create +// @Description create a link(dco application) +// @Tags DCOLink +// @Accept json +// @Param body body models.DCOLinkCreateOption true "body for creating link" +// @Success 201 {object} controllers.respData +// @router / [post] +func (ctl *DCOLinkController) Create() { + action := "community manager creates link(dco application)" + sendResp := ctl.newFuncForSendingFailedResp(action) + + pl, fr := ctl.tokenPayloadBasedOnCodePlatform() + if fr != nil { + sendResp(fr) + return + } + + input := &models.DCOLinkCreateOption{} + if fr := ctl.fetchInputPayloadFromFormData(input); fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + + if fr := pl.isOwnerOfOrg(input.Platform, input.OrgID); fr != nil { + sendResp(fr) + return + } + + if merr := models.AddDCOLink(pl.User, input); merr != nil { + ctl.sendModelErrorAsResp(merr, action) + return + } + + ctl.sendSuccessResp(action, "successfully") +} + +// @Title Delete +// @Description delete link +// @Tags DCOLink +// @Accept json +// @Param link_id path string true "link id" +// @Success 204 {object} controllers.respData +// @router /:link_id [delete] +func (ctl *DCOLinkController) Delete() { + linkId := ctl.GetString(":link_id") + action := "community manager delete dco link: " + linkId + sendResp := ctl.newFuncForSendingFailedResp(action) + + pl, fr := ctl.tokenPayloadBasedOnCodePlatform() + if fr != nil { + sendResp(fr) + return + } + + if fr := pl.isOwnerOfLink(linkId); fr != nil { + sendResp(fr) + return + } + + if err := models.RemoveDCOLink(linkId); err != nil { + ctl.sendModelErrorAsResp(err, action) + return + } + + ctl.sendSuccessResp(action, "successfully") +} + +// @Title List +// @Description list all links +// @Tags DCOLink +// @Accept json +// @Success 200 {object} models.LinkInfo +// @Failure 401 missing_token: token is missing +// @Failure 402 unknown_token: token is unknown +// @Failure 403 expired_token: token is expired +// @Failure 404 unauthorized_token: the permission of token is unmatched +// @Failure 500 system_error: system error +// @router / [get] +func (ctl *DCOLinkController) List() { + action := "community manager list dco links" + + pl, fr := ctl.tokenPayloadBasedOnCodePlatform() + if fr != nil { + ctl.sendFailedResultAsResp(fr, action) + return + } + + if r, merr := models.ListDCOLink(pl.Platform, pl.Orgs); merr != nil { + ctl.sendModelErrorAsResp(merr, action) + } else { + ctl.sendSuccessResp(action, r) + } +} + +// @Title GetDCOForSigning +// @Description get signing page info +// @Tags DCOLink +// @Accept json +// @Param link_id path string true "link id" +// @Param apply_to path string true "apply to" +// @Success 200 {object} models.CLADetail +// @Failure util.ErrNoCLABindingDoc "org has not been bound any clas" +// @Failure util.ErrNotReadyToSign "the corp signing is not ready" +// @router /:link_id/dcos [get] +func (ctl *DCOLinkController) GetDCOForSigning() { + action := "fetch dco signing page info" + + result, err := models.ListDCOs(ctl.GetString(":link_id")) + if err != nil { + ctl.sendModelErrorAsResp(err, action) + } else { + ctl.sendSuccessResp(action, result) + } +} diff --git a/controllers/link.go b/controllers/link.go index f48fdef..a4a0dc1 100644 --- a/controllers/link.go +++ b/controllers/link.go @@ -18,14 +18,14 @@ func (ctl *LinkController) Prepare() { } } -// @Title Link +// @Title Create // @Description create a link(cla application) // @Tags Link // @Accept json // @Param body body models.LinkCreateOption true "body for creating link" // @Success 201 {object} controllers.respData // @router / [post] -func (ctl *LinkController) Link() { +func (ctl *LinkController) Create() { action := "community manager creates link(cla application)" sendResp := ctl.newFuncForSendingFailedResp(action) diff --git a/controllers/token.go b/controllers/token.go index 1d9e11d..4243207 100644 --- a/controllers/token.go +++ b/controllers/token.go @@ -6,7 +6,6 @@ import ( "net" "strings" - "github.com/beego/beego/v2/core/logs" "github.com/opensourceways/app-cla-server/models" ) @@ -92,17 +91,12 @@ func (ctl *baseController) setToken(t models.AccessToken) { func (ctl *baseController) getRemoteAddr() (string, *failedApiResult) { ips := ctl.Ctx.Request.Header.Get("x-forwarded-for") - logs.Info("x-forwarded-for value is: %s", ips) for _, item := range strings.Split(ips, ", ") { if net.ParseIP(item) != nil { - logs.Info("x-forwarded-for value is: %s, remote addr: %s", ips, item) - return item, nil } } - logs.Info("x-forwarded-for value is: %s, no remote addr", ips) - return "", newFailedApiResult(400, errCanNotFetchClientIP, fmt.Errorf("can not fetch client ip")) } diff --git a/models/adapter.go b/models/adapter.go index 9ce2cd4..af1b1c1 100644 --- a/models/adapter.go +++ b/models/adapter.go @@ -60,6 +60,50 @@ func GetLink(linkId string) (OrgInfo, IModelError) { return linkAdapterInstance.GetLink(linkId) } +// dco + +func AddDCOInstance(linkId string, opt *DCOCreateOpt) IModelError { + return dcoAdapterInstance.Add(linkId, opt) +} + +func DCOFile(linkId, dcoId string) string { + return dcoAdapterInstance.DCOLocalFilePath(linkId, dcoId) +} + +func ListDCOInstances(linkId string) ([]CLADetail, IModelError) { + return dcoAdapterInstance.List(linkId) +} + +func RemoveDCOInstance(linkId, dcoId string) IModelError { + return dcoAdapterInstance.Remove(linkId, dcoId) +} + +// link + +func AddDCOLink(submitter string, opt *DCOLinkCreateOption) IModelError { + return dcoLinkAdapterInstance.Add(submitter, opt) +} + +func RemoveDCOLink(linkId string) IModelError { + return dcoLinkAdapterInstance.Remove(linkId) +} + +func ListDCOLink(platform string, orgs []string) ([]LinkInfo, IModelError) { + return dcoLinkAdapterInstance.List(platform, orgs) +} + +func GetLinkDCO(linkId, dcoId string) (OrgInfo, CLAInfo, IModelError) { + return dcoLinkAdapterInstance.GetDCO(linkId, dcoId) +} + +func ListDCOs(linkId string) ([]CLADetail, IModelError) { + return dcoLinkAdapterInstance.ListDCOs(linkId) +} + +func GetDCOLink(linkId string) (OrgInfo, IModelError) { + return dcoLinkAdapterInstance.GetLink(linkId) +} + // corp signing func VCOfCorpSigning(linkId, email string) (string, IModelError) { diff --git a/models/dco.go b/models/dco.go new file mode 100644 index 0000000..5dbf53e --- /dev/null +++ b/models/dco.go @@ -0,0 +1,16 @@ +package models + +type DCOLinkCreateOption struct { + Platform string `json:"platform"` + OrgID string `json:"org_id"` + RepoID string `json:"repo_id"` + OrgAlias string `json:"org_alias"` + OrgEmail string `json:"org_email"` + DCO *DCOCreateOpt `json:"dco"` +} + +type DCOCreateOpt = struct { + URL string `json:"url"` + Fields []CLAField `json:"fields"` + Language string `json:"language"` +} diff --git a/models/error.go b/models/error.go index 6117efc..886d7ca 100644 --- a/models/error.go +++ b/models/error.go @@ -49,10 +49,15 @@ const ( ErrNoRefreshToken ModelErrCode = "no_refresh_token" ErrInvalidToken ModelErrCode = "invalid_token" ErrCLAExists ModelErrCode = "cla_exists" + ErrCLAIsUsed ModelErrCode = "cla_is_used" + ErrDCOExists ModelErrCode = "dco_exists" + ErrDCOIsUsed ModelErrCode = "dco_is_used" ErrTooManyRequest ModelErrCode = "too_many_request" ErrUserLoginFrozen ModelErrCode = "user_login_frozen" - ErrCLAIsUsed ModelErrCode = "cla_is_used" ErrLinkIsUsed ModelErrCode = "link_is_used" + ErrNoDCOLink ModelErrCode = "no_dco_link" + ErrDCOLinkExists ModelErrCode = "dco_link_exists" + ErrDCOLinkIsUsed ModelErrCode = "dco_link_is_used" ) type IModelError interface { diff --git a/models/init.go b/models/init.go index 54a9c01..53bf9ab 100644 --- a/models/init.go +++ b/models/init.go @@ -2,9 +2,11 @@ package models var ( claAdapterInstance claAdapter + dcoAdapterInstance dcoAdapter linkAdapterInstance linkAdapter userAdapterInstance userAdapter smtpAdapterInstance smtpAdapter + dcoLinkAdapterInstance dcoLinkAdapter corpPDFAdapterInstance corpPDFAdapter corpAdminAdatperInstance corpAdminAdatper accessTokenAdapterInstance accessTokenAdapter @@ -151,3 +153,29 @@ type linkAdapter interface { func RegisterLinkAdapter(a linkAdapter) { linkAdapterInstance = a } + +// dcoAdapter +type dcoAdapter interface { + Add(linkId string, opt *DCOCreateOpt) IModelError + Remove(linkId, dcoId string) IModelError + DCOLocalFilePath(linkId, dcoId string) string + List(linkId string) ([]CLADetail, IModelError) +} + +func RegisterDCOAdapter(a dcoAdapter) { + dcoAdapterInstance = a +} + +// dcoLinkAdapter +type dcoLinkAdapter interface { + Add(submitter string, opt *DCOLinkCreateOption) IModelError + Remove(linkId string) IModelError + List(platform string, orgs []string) ([]LinkInfo, IModelError) + GetLink(linkId string) (org OrgInfo, merr IModelError) + GetDCO(linkId, dcoId string) (OrgInfo, CLAInfo, IModelError) + ListDCOs(linkId string) ([]CLADetail, IModelError) +} + +func RegisterDCOLinkAdapter(a dcoLinkAdapter) { + dcoLinkAdapterInstance = a +} diff --git a/routers/commentsRouter.go b/routers/commentsRouter.go index 0ff6a4f..05e2a7d 100644 --- a/routers/commentsRouter.go +++ b/routers/commentsRouter.go @@ -223,6 +223,78 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"], + beego.ControllerComments{ + Method: "Add", + Router: `/:link_id`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"], + beego.ControllerComments{ + Method: "List", + Router: `/:link_id`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"], + beego.ControllerComments{ + Method: "Delete", + Router: `/:link_id/:id`, + AllowHTTPMethods: []string{"delete"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOController"], + beego.ControllerComments{ + Method: "DownloadPDF", + Router: `/:link_id/:id`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"], + beego.ControllerComments{ + Method: "Create", + Router: `/`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"], + beego.ControllerComments{ + Method: "List", + Router: `/`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"], + beego.ControllerComments{ + Method: "Delete", + Router: `/:link_id`, + AllowHTTPMethods: []string{"delete"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:DCOLinkController"], + beego.ControllerComments{ + Method: "GetDCOForSigning", + Router: `/:link_id/dcos`, + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:EmployeeManagerController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:EmployeeManagerController"], beego.ControllerComments{ Method: "Post", @@ -333,7 +405,7 @@ func init() { beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:LinkController"] = append(beego.GlobalControllerRouter["github.com/opensourceways/app-cla-server/controllers:LinkController"], beego.ControllerComments{ - Method: "Link", + Method: "Create", Router: `/`, AllowHTTPMethods: []string{"post"}, MethodParams: param.Make(), diff --git a/routers/router.go b/routers/router.go index 9ad3b8a..ebafeb8 100644 --- a/routers/router.go +++ b/routers/router.go @@ -25,6 +25,17 @@ func init() { &controllers.LinkController{}, ), ), + + beego.NSNamespace("/dco", + beego.NSInclude( + &controllers.DCOController{}, + ), + ), + beego.NSNamespace("/dco-link", + beego.NSInclude( + &controllers.DCOLinkController{}, + ), + ), beego.NSNamespace("/individual-signing", beego.NSInclude( &controllers.IndividualSigningController{}, diff --git a/signing.go b/signing.go index 3294fbd..9235e01 100644 --- a/signing.go +++ b/signing.go @@ -158,5 +158,22 @@ func initSigning(cfg *config.Config) error { ), ) + // + + dcoAapter := adapter.NewDCOAdapter( + app.NewDCOService(linkRepo, cla, individual), + cfg.Domain.MaxSizeOfCLAContent, + cfg.Domain.FileTypeOfCLAContent, + ) + + models.RegisterDCOAdapter(dcoAapter) + + models.RegisterDCOLinkAdapter( + adapter.NewDCOLinkAdapter( + app.NewDCOLinkService(linkRepo, cla, individual, echelper), + dcoAapter, + ), + ) + return nil } diff --git a/signing/adapter/cla.go b/signing/adapter/cla.go index 0536d77..9fa849e 100644 --- a/signing/adapter/cla.go +++ b/signing/adapter/cla.go @@ -51,12 +51,12 @@ func (adapter *claAdatper) List(linkId string) (models.CLAOfLink, models.IModelE } return models.CLAOfLink{ - IndividualCLAs: adapter.toCLADetail(individuals), - CorpCLAs: adapter.toCLADetail(corps), + IndividualCLAs: toCLADetail(individuals), + CorpCLAs: toCLADetail(corps), }, nil } -func (adapter *claAdatper) toCLADetail(v []app.CLADTO) []models.CLADetail { +func toCLADetail(v []app.CLADTO) []models.CLADetail { r := make([]models.CLADetail, len(v)) for i := range v { @@ -114,12 +114,12 @@ func (adapter *claAdatper) cmdToAddCLA(opt *models.CLACreateOpt) ( return } - cmd.Fields, err = adapter.toFields(cmd.Type, opt.Fields) + cmd.Fields, err = toCLAFields(cmd.Type, opt.Fields) return } -func (adapter *claAdatper) toFields(claType dp.CLAType, fields []models.CLAField) (r []domain.Field, err error) { +func toCLAFields(claType dp.CLAType, fields []models.CLAField) (r []domain.Field, err error) { if len(fields) == 0 { err = errors.New("no fields") @@ -139,7 +139,7 @@ func (adapter *claAdatper) toFields(claType dp.CLAType, fields []models.CLAField m[item.Type] = true - if r[i], err = adapter.toField(item, f); err != nil { + if r[i], err = toCLAField(item, f); err != nil { return } } @@ -151,7 +151,7 @@ func (adapter *claAdatper) toFields(claType dp.CLAType, fields []models.CLAField return } -func (adapter *claAdatper) toField( +func toCLAField( opt *models.CLAField, f func(string) (dp.CLAFieldType, error), ) (domain.Field, error) { diff --git a/signing/adapter/dco.go b/signing/adapter/dco.go new file mode 100644 index 0000000..d1f5fa1 --- /dev/null +++ b/signing/adapter/dco.go @@ -0,0 +1,96 @@ +package adapter + +import ( + "github.com/opensourceways/app-cla-server/models" + "github.com/opensourceways/app-cla-server/signing/app" + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/dp" + "github.com/opensourceways/app-cla-server/util" +) + +func NewDCOAdapter( + s app.DCOService, + maxSizeOfDCOContent int, + fileTypeOfDCOContent string, +) *dcoAdapter { + return &dcoAdapter{ + s: s, + maxSizeOfDCOContent: maxSizeOfDCOContent, + fileTypeOfDCOContent: fileTypeOfDCOContent, + } +} + +type dcoAdapter struct { + s app.DCOService + maxSizeOfDCOContent int + fileTypeOfDCOContent string +} + +// Remove +func (adapter *dcoAdapter) Remove(linkId, claId string) models.IModelError { + err := adapter.s.Remove(domain.CLAIndex{ + LinkId: linkId, + CLAId: claId, + }) + + if err != nil { + return toModelError(err) + } + + return nil +} + +// List +func (adapter *dcoAdapter) List(linkId string) ([]models.CLADetail, models.IModelError) { + v, err := adapter.s.List(linkId) + if err != nil { + return nil, toModelError(err) + } + + return toCLADetail(v), nil +} + +// DCOLocalFilePath +func (adapter *dcoAdapter) DCOLocalFilePath(linkId, claId string) string { + return adapter.s.DCOLocalFilePath(domain.CLAIndex{ + LinkId: linkId, + CLAId: claId, + }) +} + +// Add +func (adapter *dcoAdapter) Add(linkId string, opt *models.DCOCreateOpt) models.IModelError { + cmd, err := adapter.cmdToAddDCO(opt) + if err != nil { + return errBadRequestParameter(err) + } + + if err := adapter.s.Add(linkId, &cmd); err != nil { + return toModelError(err) + } + + return nil +} + +func (adapter *dcoAdapter) cmdToAddDCO(opt *models.DCOCreateOpt) ( + cmd app.CmdToAddDCO, err error, +) { + cmd.Text, err = util.DownloadFile( + opt.URL, adapter.fileTypeOfDCOContent, adapter.maxSizeOfDCOContent, + ) + if err != nil { + return + } + + if cmd.URL, err = dp.NewURL(opt.URL); err != nil { + return + } + + if cmd.Language, err = dp.NewLanguage(opt.Language); err != nil { + return + } + + cmd.Fields, err = toCLAFields(dp.CLATypeIndividual, opt.Fields) + + return +} diff --git a/signing/adapter/dco_link.go b/signing/adapter/dco_link.go new file mode 100644 index 0000000..8925751 --- /dev/null +++ b/signing/adapter/dco_link.go @@ -0,0 +1,173 @@ +package adapter + +import ( + "errors" + + "github.com/opensourceways/app-cla-server/models" + "github.com/opensourceways/app-cla-server/signing/app" + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/dp" +) + +func NewDCOLinkAdapter( + s app.DCOLinkService, + dco *dcoAdapter, +) *dcoLinkAdapter { + return &dcoLinkAdapter{ + dco: dco, + s: s, + } +} + +type dcoLinkAdapter struct { + dco *dcoAdapter + + s app.DCOLinkService +} + +func (adapter *dcoLinkAdapter) GetLink(linkId string) ( + org models.OrgInfo, merr models.IModelError, +) { + v, err := adapter.s.Find(linkId) + if err != nil { + merr = toModelError(err) + + return + } + + org.OrgID = v.Org.Org + org.Platform = v.Org.Platform + org.OrgAlias = v.Org.Alias + org.OrgEmail = v.Email.Addr.EmailAddr() + org.OrgEmailPlatform = v.Email.Platform + + return +} + +// GetDCOLinkDCO +func (adapter *dcoLinkAdapter) GetDCO(linkId, claId string) ( + org models.OrgInfo, cla models.CLAInfo, merr models.IModelError, +) { + v, err := adapter.s.FindDCO(&domain.CLAIndex{ + LinkId: linkId, + CLAId: claId, + }) + if err != nil { + merr = toModelError(err) + + return + } + + org.OrgID = v.Org.Org + org.Platform = v.Org.Platform + org.OrgAlias = v.Org.Alias + org.OrgEmail = v.Email.Addr.EmailAddr() + org.OrgEmailPlatform = v.Email.Platform + + cla.CLAId = v.CLA.Id + cla.CLAFile = v.CLA.LocalFile + cla.CLALang = v.CLA.Language + cla.Fields = toFields(v.CLA.Fileds) + + return +} + +// ListDCOs +func (adapter *dcoLinkAdapter) ListDCOs(linkId string) ([]models.CLADetail, models.IModelError) { + v, err := adapter.s.FindDCOs(linkId) + if err != nil { + return nil, toModelError(err) + } + + r := make([]models.CLADetail, len(v)) + for i := range v { + item := &v[i] + + detail := &r[i] + detail.CLAId = item.Id + detail.Language = item.Language + detail.Fields = toFields(item.Fileds) + } + + return r, nil +} + +// List +func (adapter *dcoLinkAdapter) List(platform string, orgs []string) ([]models.LinkInfo, models.IModelError) { + v, err := adapter.s.List(&app.CmdToListDCOLink{ + Platform: platform, + Orgs: orgs, + }) + if err != nil { + return nil, toModelError(err) + } + + r := make([]models.LinkInfo, len(v)) + for i := range v { + item := &v[i] + + li := &r[i] + + li.LinkID = item.Id + li.Submitter = item.Submitter + + li.OrgID = item.Org.Org + li.Platform = item.Org.Platform + + li.OrgAlias = item.Org.Alias + li.OrgEmail = item.Email.Addr.EmailAddr() + li.OrgEmailPlatform = item.Email.Platform + } + + return r, nil +} + +// Remove +func (adapter *dcoLinkAdapter) Remove(linkId string) models.IModelError { + if err := adapter.s.Remove(linkId); err != nil { + return toModelError(err) + } + + return nil +} + +// Add +func (adapter *dcoLinkAdapter) Add(submitter string, opt *models.DCOLinkCreateOption) models.IModelError { + cmd, err := adapter.cmdToAddLink(submitter, opt) + if err != nil { + return errBadRequestParameter(err) + } + + if err := adapter.s.Add(&cmd); err != nil { + return toModelError(err) + } + + return nil +} + +func (adapter *dcoLinkAdapter) cmdToAddLink(submitter string, opt *models.DCOLinkCreateOption) ( + cmd app.CmdToAddDCOLink, err error, +) { + if opt.DCO == nil { + err = errors.New("no dco instance") + + return + } + + v, err := adapter.dco.cmdToAddDCO(opt.DCO) + if err != nil { + return + } + cmd.DCOs = append(cmd.DCOs, v) + + if cmd.Email, err = dp.NewEmailAddr(opt.OrgEmail); err != nil { + return + } + + cmd.Org.Org = opt.OrgID + cmd.Org.Alias = opt.OrgAlias + cmd.Org.Platform = opt.Platform + cmd.Submitter = submitter + + return +} diff --git a/signing/adapter/error.go b/signing/adapter/error.go index d515693..d738df0 100644 --- a/signing/adapter/error.go +++ b/signing/adapter/error.go @@ -115,6 +115,23 @@ func codeMap(code string) models.ModelErrCode { case domain.ErrorCodeLinkCanNotRemove: return models.ErrLinkIsUsed + // cla + case domain.ErrorCodeDCOExists: + return models.ErrDCOExists + + case domain.ErrorCodeDCOCanNotRemove: + return models.ErrDCOIsUsed + + // link + case domain.ErrorCodeDCOLinkNotExists: + return models.ErrNoDCOLink + + case domain.ErrorCodeDCOLinkExists: + return models.ErrDCOLinkExists + + case domain.ErrorCodeDCOLinkCanNotRemove: + return models.ErrDCOLinkIsUsed + // gmail case domain.ErrorCodeGmailNoRefreshToken: return models.ErrNoRefreshToken diff --git a/signing/adapter/link.go b/signing/adapter/link.go index ff449fd..256f66b 100644 --- a/signing/adapter/link.go +++ b/signing/adapter/link.go @@ -67,7 +67,7 @@ func (adapter *linkAdatper) GetLinkCLA(linkId, claId string) ( cla.CLAId = v.CLA.Id cla.CLAFile = v.CLA.LocalFile cla.CLALang = v.CLA.Language - cla.Fields = adapter.toFields(v.CLA.Fileds) + cla.Fields = toFields(v.CLA.Fileds) return } @@ -94,13 +94,13 @@ func (adapter *linkAdatper) ListCLAs(linkId, applyTo string) ([]models.CLADetail detail := &r[i] detail.CLAId = item.Id detail.Language = item.Language - detail.Fields = adapter.toFields(item.Fileds) + detail.Fields = toFields(item.Fileds) } return r, nil } -func (adapter *linkAdatper) toFields(fields []domain.Field) []models.CLAField { +func toFields(fields []domain.Field) []models.CLAField { r := make([]models.CLAField, len(fields)) for i := range fields { diff --git a/signing/app/dco.go b/signing/app/dco.go new file mode 100644 index 0000000..1dc1057 --- /dev/null +++ b/signing/app/dco.go @@ -0,0 +1,107 @@ +package app + +import ( + commonRepo "github.com/opensourceways/app-cla-server/common/domain/repository" + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/claservice" + "github.com/opensourceways/app-cla-server/signing/domain/repository" +) + +func NewDCOService( + repo repository.Link, + dco claservice.CLAService, + individual repository.IndividualSigning, +) *dcoService { + return &dcoService{ + repo: repo, + dco: dco, + individual: individual, + } +} + +type DCOService interface { + Add(linkId string, cmd *CmdToAddDCO) error + Remove(cmd domain.CLAIndex) error + DCOLocalFilePath(domain.CLAIndex) string + List(linkId string) ([]CLADTO, error) +} + +type dcoService struct { + repo repository.Link + dco claservice.CLAService + individual repository.IndividualSigning +} + +func (s *dcoService) Add(linkId string, cmd *CmdToAddDCO) error { + link, err := s.repo.Find(linkId) + if err != nil { + if commonRepo.IsErrorResourceNotFound(err) { + err = domain.NewDomainError(domain.ErrorCodeDCOLinkNotExists) + } + + return err + } + + v := cmd.toDCO() + + return s.dco.Add(&link, &v) +} + +func (s *dcoService) Remove(cmd domain.CLAIndex) error { + link, err := s.repo.Find(cmd.LinkId) + if err != nil { + if commonRepo.IsErrorResourceNotFound(err) { + err = domain.NewDomainError(domain.ErrorCodeDCOLinkNotExists) + } + + return err + } + + cla := link.FindCLA(cmd.CLAId) + if cla == nil { + return domain.NewDomainError(domain.ErrorCodeDCONotExists) + } + + if err := s.checkIfCanRemove(&cmd); err != nil { + return err + } + + return s.repo.RemoveCLA(&link, cla) +} + +func (s *dcoService) checkIfCanRemove(cmd *domain.CLAIndex) error { + v, err := s.individual.HasSignedCLA(cmd) + if err != nil { + return err + } + if v { + return domain.NewDomainError(domain.ErrorCodeDCOCanNotRemove) + } + + return nil +} + +func (s *dcoService) List(linkId string) (dcos []CLADTO, err error) { + v, err := s.repo.Find(linkId) + if err != nil { + return + } + + dcos = make([]CLADTO, 0, len(v.CLAs)) + + for i := range v.CLAs { + item := &v.CLAs[i] + + dcos = append(dcos, CLADTO{ + Id: item.Id, + URL: item.URL.URL(), + Language: item.Language.Language(), + }) + } + + return +} + +func (s *dcoService) DCOLocalFilePath(index domain.CLAIndex) string { + return s.dco.CLALocalFilePath(&index) +} diff --git a/signing/app/dco_dto.go b/signing/app/dco_dto.go new file mode 100644 index 0000000..b48d702 --- /dev/null +++ b/signing/app/dco_dto.go @@ -0,0 +1,23 @@ +package app + +import ( + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/dp" +) + +type CmdToAddDCO struct { + URL dp.URL + Text []byte + Fields []domain.Field + Language dp.Language +} + +func (cmd *CmdToAddDCO) toDCO() domain.CLA { + return domain.CLA{ + URL: cmd.URL, + Text: cmd.Text, + Type: dp.CLATypeIndividual, + Fields: cmd.Fields, + Language: cmd.Language, + } +} diff --git a/signing/app/dco_link.go b/signing/app/dco_link.go new file mode 100644 index 0000000..0474421 --- /dev/null +++ b/signing/app/dco_link.go @@ -0,0 +1,141 @@ +package app + +import ( + commonRepo "github.com/opensourceways/app-cla-server/common/domain/repository" + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/claservice" + "github.com/opensourceways/app-cla-server/signing/domain/repository" +) + +func NewDCOLinkService( + repo repository.Link, + dco claservice.CLAService, + individual repository.IndividualSigning, + emailCredential repository.EmailCredential, +) *dcoLinkService { + return &dcoLinkService{ + repo: repo, + dco: dco, + individual: individual, + emailCredential: emailCredential, + } +} + +type DCOLinkService interface { + Add(cmd *CmdToAddDCOLink) error + Remove(linkId string) error + List(cmd *CmdToListDCOLink) ([]repository.LinkSummary, error) + Find(linkId string) (dto LinkDTO, err error) + FindDCOs(string) ([]CLADetailDTO, error) + FindDCO(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) +} + +type dcoLinkService struct { + repo repository.Link + dco claservice.CLAService + individual repository.IndividualSigning + emailCredential repository.EmailCredential +} + +func (s *dcoLinkService) Add(cmd *CmdToAddDCOLink) error { + v, err := s.emailCredential.Find(cmd.Email) + if err != nil { + return err + } + + link := cmd.toDCOLink() + link.Email = domain.EmailInfo{ + Addr: cmd.Email, + Platform: v.Platform, + } + + return s.dco.AddLink(&link) +} + +func (s *dcoLinkService) Remove(linkId string) error { + b, err := s.checkIfCanRemove(linkId) + if err != nil { + return err + } + if !b { + return domain.NewDomainError(domain.ErrorCodeDCOLinkCanNotRemove) + } + + v, err := s.repo.Find(linkId) + if err != nil { + if commonRepo.IsErrorResourceNotFound(err) { + return nil + } + + return err + } + + return s.repo.Remove(&v) +} + +func (s *dcoLinkService) checkIfCanRemove(linkId string) (bool, error) { + v, err := s.individual.HasSignedLink(linkId) + + return !v, err +} + +func (s *dcoLinkService) List(cmd *CmdToListDCOLink) ([]repository.LinkSummary, error) { + return s.repo.FindAll(cmd) +} + +func (s *dcoLinkService) FindDCOs(linkId string) ([]CLADetailDTO, error) { + v, err := s.repo.Find(linkId) + if err != nil { + return nil, err + } + + r := make([]CLADetailDTO, 0, len(v.CLAs)) + for i := range v.CLAs { + item := &v.CLAs[i] + + r = append(r, CLADetailDTO{ + Id: item.Id, + Fileds: item.Fields, + Language: item.Language.Language(), + }) + } + + return r, nil +} + +func (s *dcoLinkService) FindDCO(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) { + v, err := s.repo.Find(cmd.LinkId) + if err != nil { + return + } + + cla := v.FindCLA(cmd.CLAId) + if cla == nil { + err = domain.NewDomainError(domain.ErrorCodeDCONotExists) + + return + } + + dto.Org = v.Org + dto.Email = v.Email + dto.CLA = CLADetailDTO{ + Id: cla.Id, + Fileds: cla.Fields, + Language: cla.Language.Language(), + LocalFile: s.dco.CLALocalFilePath(cmd), + } + + return +} + +func (s *dcoLinkService) Find(linkId string) (dto LinkDTO, err error) { + v, err := s.repo.Find(linkId) + if err != nil { + return + } + + dto.Org = v.Org + dto.Email = v.Email + + return +} diff --git a/signing/app/dco_link_dto.go b/signing/app/dco_link_dto.go new file mode 100644 index 0000000..cdc055e --- /dev/null +++ b/signing/app/dco_link_dto.go @@ -0,0 +1,33 @@ +package app + +import ( + "strconv" + + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/dp" + "github.com/opensourceways/app-cla-server/signing/domain/repository" +) + +type CmdToAddDCOLink struct { + Org domain.OrgInfo + Email dp.EmailAddr + DCOs []CmdToAddDCO + Submitter string +} + +func (cmd *CmdToAddDCOLink) toDCOLink() domain.Link { + v := make([]domain.CLA, len(cmd.DCOs)) + for i := range cmd.DCOs { + v[i] = cmd.DCOs[i].toDCO() + v[i].Id = strconv.Itoa(i) + } + + return domain.Link{ + Org: cmd.Org, + CLAs: v, + CLANum: len(cmd.DCOs), + Submitter: cmd.Submitter, + } +} + +type CmdToListDCOLink = repository.FindLinksOpt diff --git a/signing/domain/claservice/service.go b/signing/domain/claservice/service.go index d2c2da4..8a9c108 100644 --- a/signing/domain/claservice/service.go +++ b/signing/domain/claservice/service.go @@ -1,9 +1,7 @@ package claservice import ( - "fmt" "github.com/beego/beego/v2/core/logs" - "time" commonRepo "github.com/opensourceways/app-cla-server/common/domain/repository" "github.com/opensourceways/app-cla-server/signing/domain" @@ -56,9 +54,6 @@ func (s *claService) CLALocalFilePath(index *domain.CLAIndex) string { } func (s *claService) AddLink(link *domain.Link) error { - linkId := genLinkID(link) - link.Id = linkId - tempFiles := []string{} clean := func() { for _, p := range tempFiles { @@ -68,10 +63,12 @@ func (s *claService) AddLink(link *domain.Link) error { } } + link.Id = link.Org.LinkId() + for i := range link.CLAs { item := &link.CLAs[i] - p, err := s.local.AddCLA(linkId, item) + p, err := s.local.AddCLA(link.Id, item) if err != nil { clean() @@ -93,9 +90,3 @@ func (s *claService) AddLink(link *domain.Link) error { return nil } - -func genLinkID(v *domain.Link) string { - org := &v.Org - - return fmt.Sprintf("%s_%s-%d", org.Platform, org.Org, time.Now().UnixNano()) -} diff --git a/signing/domain/error.go b/signing/domain/error.go index 547909f..13036b4 100644 --- a/signing/domain/error.go +++ b/signing/domain/error.go @@ -54,6 +54,14 @@ const ( ErrorCodeLinkExists = "link_exists" ErrorCodeLinkNotExists = "link_not_exists" ErrorCodeLinkCanNotRemove = "link_can_not_remove" + + ErrorCodeDCOExists = "dco_exists" + ErrorCodeDCONotExists = "dco_not_exists" + ErrorCodeDCOCanNotRemove = "dco_can_not_remove" + + ErrorCodeDCOLinkExists = "dco_link_exists" + ErrorCodeDCOLinkNotExists = "dco_link_not_exists" + ErrorCodeDCOLinkCanNotRemove = "dco_link_can_not_remove" ) // domainError diff --git a/signing/domain/link.go b/signing/domain/link.go index b95db7c..9018cdd 100644 --- a/signing/domain/link.go +++ b/signing/domain/link.go @@ -1,7 +1,9 @@ package domain import ( + "fmt" "strconv" + "time" "github.com/opensourceways/app-cla-server/signing/domain/dp" ) @@ -17,6 +19,10 @@ type OrgInfo struct { Alias string } +func (v *OrgInfo) LinkId() string { + return fmt.Sprintf("%s_%s-%d", v.Platform, v.Org, time.Now().UnixNano()) +} + type Link struct { Id string Org OrgInfo diff --git a/swagger/swagger.json b/swagger/swagger.json index 6dd8b0b..4b5265b 100644 --- a/swagger/swagger.json +++ b/swagger/swagger.json @@ -1020,6 +1020,290 @@ } } }, + "/dco-link/": { + "get": { + "tags": [ + "dco-link" + ], + "description": "list all links\n\u003cbr\u003e", + "operationId": "DCOLinkController.List", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/models.LinkInfo" + } + }, + "401": { + "description": "missing_token: token is missing" + }, + "402": { + "description": "unknown_token: token is unknown" + }, + "403": { + "description": "expired_token: token is expired" + }, + "404": { + "description": "unauthorized_token: the permission of token is unmatched" + }, + "500": { + "description": "system_error: system error" + } + } + }, + "post": { + "tags": [ + "dco-link" + ], + "description": "create a link(dco application)\n\u003cbr\u003e", + "operationId": "DCOLinkController.Create", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "body for creating link", + "required": true, + "schema": { + "$ref": "#/definitions/models.DCOLinkCreateOption" + } + } + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/controllers.respData" + } + } + } + } + }, + "/dco-link/{link_id}": { + "delete": { + "tags": [ + "dco-link" + ], + "description": "delete link\n\u003cbr\u003e", + "operationId": "DCOLinkController.Delete", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "link id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "", + "schema": { + "$ref": "#/definitions/controllers.respData" + } + } + } + } + }, + "/dco-link/{link_id}/dcos": { + "get": { + "tags": [ + "dco-link" + ], + "description": "get signing page info\n\u003cbr\u003e", + "operationId": "DCOLinkController.GetDCOForSigning", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "link id", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "apply_to", + "description": "apply to", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/models.CLADetail" + } + }, + "util.ErrNoCLABindingDoc": { + "description": "\"org has not been bound any clas\"" + }, + "util.ErrNotReadyToSign": { + "description": "\"the corp signing is not ready\"" + } + } + } + }, + "/dco/{link_id}": { + "get": { + "tags": [ + "dco" + ], + "description": "list dcos of link\n\u003cbr\u003e", + "operationId": "DCOController.List", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "link id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/models.CLADetail" + } + } + } + }, + "post": { + "tags": [ + "dco" + ], + "description": "add dco\n\u003cbr\u003e", + "operationId": "DCOController.Add", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "body", + "name": "body", + "description": "body for adding dco", + "required": true, + "schema": { + "$ref": "#/definitions/models.DCOCreateOpt" + } + } + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/controllers.respData" + } + } + } + } + }, + "/dco/{link_id}/{id}": { + "get": { + "tags": [ + "dco" + ], + "description": "get dco pdf\n\u003cbr\u003e", + "operationId": "DCOController.DownloadPDF", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "link id", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "id", + "description": "dco id", + "required": true, + "type": "string" + } + ], + "responses": { + "200": { + "description": "" + } + } + }, + "delete": { + "tags": [ + "dco" + ], + "description": "delete dco\n\u003cbr\u003e", + "operationId": "DCOController.Delete", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "parameters": [ + { + "in": "path", + "name": "link_id", + "description": "link id", + "required": true, + "type": "string" + }, + { + "in": "path", + "name": "id", + "description": "dco id", + "required": true, + "type": "string" + } + ], + "responses": { + "204": { + "description": "", + "schema": { + "$ref": "#/definitions/controllers.respData" + } + } + } + } + }, "/employee-manager/": { "get": { "tags": [ @@ -1581,7 +1865,7 @@ "link" ], "description": "create a link(cla application)\n\u003cbr\u003e", - "operationId": "LinkController.Link", + "operationId": "LinkController.Create", "consumes": [ "application/json" ], @@ -2214,6 +2498,48 @@ } } }, + "models.DCOCreateOpt": { + "title": "DCOCreateOpt", + "type": "object", + "properties": { + "fields": { + "type": "array", + "items": { + "$ref": "#/definitions/models.CLAField" + } + }, + "language": { + "type": "string" + }, + "url": { + "type": "string" + } + } + }, + "models.DCOLinkCreateOption": { + "title": "DCOLinkCreateOption", + "type": "object", + "properties": { + "dco": { + "$ref": "#/definitions/models.DCOCreateOpt" + }, + "org_alias": { + "type": "string" + }, + "org_email": { + "type": "string" + }, + "org_id": { + "type": "string" + }, + "platform": { + "type": "string" + }, + "repo_id": { + "type": "string" + } + } + }, "models.EmailAuthorization": { "title": "EmailAuthorization", "type": "object", diff --git a/swagger/swagger.yml b/swagger/swagger.yml index 42fb315..712024f 100644 --- a/swagger/swagger.yml +++ b/swagger/swagger.yml @@ -733,6 +733,210 @@ paths: community' "500": description: 'system_error: system error' + /dco-link/: + get: + tags: + - dco-link + description: |- + list all links +
+ operationId: DCOLinkController.List + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: "" + schema: + $ref: '#/definitions/models.LinkInfo' + "401": + description: 'missing_token: token is missing' + "402": + description: 'unknown_token: token is unknown' + "403": + description: 'expired_token: token is expired' + "404": + description: 'unauthorized_token: the permission of token is unmatched' + "500": + description: 'system_error: system error' + post: + tags: + - dco-link + description: |- + create a link(dco application) +
+ operationId: DCOLinkController.Create + consumes: + - application/json + produces: + - application/json + parameters: + - in: body + name: body + description: body for creating link + required: true + schema: + $ref: '#/definitions/models.DCOLinkCreateOption' + responses: + "201": + description: "" + schema: + $ref: '#/definitions/controllers.respData' + /dco-link/{link_id}: + delete: + tags: + - dco-link + description: |- + delete link +
+ operationId: DCOLinkController.Delete + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: link_id + description: link id + required: true + type: string + responses: + "204": + description: "" + schema: + $ref: '#/definitions/controllers.respData' + /dco-link/{link_id}/dcos: + get: + tags: + - dco-link + description: |- + get signing page info +
+ operationId: DCOLinkController.GetDCOForSigning + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: link_id + description: link id + required: true + type: string + - in: path + name: apply_to + description: apply to + required: true + type: string + responses: + "200": + description: "" + schema: + $ref: '#/definitions/models.CLADetail' + util.ErrNoCLABindingDoc: + description: '"org has not been bound any clas"' + util.ErrNotReadyToSign: + description: '"the corp signing is not ready"' + /dco/{link_id}: + get: + tags: + - dco + description: |- + list dcos of link +
+ operationId: DCOController.List + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: link_id + description: link id + required: true + type: string + responses: + "200": + description: "" + schema: + $ref: '#/definitions/models.CLADetail' + post: + tags: + - dco + description: |- + add dco +
+ operationId: DCOController.Add + consumes: + - application/json + produces: + - application/json + parameters: + - in: body + name: body + description: body for adding dco + required: true + schema: + $ref: '#/definitions/models.DCOCreateOpt' + responses: + "201": + description: "" + schema: + $ref: '#/definitions/controllers.respData' + /dco/{link_id}/{id}: + get: + tags: + - dco + description: |- + get dco pdf +
+ operationId: DCOController.DownloadPDF + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: link_id + description: link id + required: true + type: string + - in: path + name: id + description: dco id + required: true + type: string + responses: + "200": + description: "" + delete: + tags: + - dco + description: |- + delete dco +
+ operationId: DCOController.Delete + consumes: + - application/json + produces: + - application/json + parameters: + - in: path + name: link_id + description: link id + required: true + type: string + - in: path + name: id + description: dco id + required: true + type: string + responses: + "204": + description: "" + schema: + $ref: '#/definitions/controllers.respData' /employee-manager/: get: tags: @@ -1140,7 +1344,7 @@ paths: description: |- create a link(cla application)
- operationId: LinkController.Link + operationId: LinkController.Create consumes: - application/json produces: @@ -1573,6 +1777,34 @@ definitions: type: string pdf_uploaded: type: boolean + models.DCOCreateOpt: + title: DCOCreateOpt + type: object + properties: + fields: + type: array + items: + $ref: '#/definitions/models.CLAField' + language: + type: string + url: + type: string + models.DCOLinkCreateOption: + title: DCOLinkCreateOption + type: object + properties: + dco: + $ref: '#/definitions/models.DCOCreateOpt' + org_alias: + type: string + org_email: + type: string + org_id: + type: string + platform: + type: string + repo_id: + type: string models.EmailAuthorization: title: EmailAuthorization type: object From d21439043c81de96eeae7f3d5312c602538bd1eb Mon Sep 17 00:00:00 2001 From: zengchen1024 Date: Wed, 26 Jul 2023 11:29:10 +0800 Subject: [PATCH 2/4] minor update --- models/adapter.go | 6 +++--- signing/adapter/link.go | 2 +- signing/app/link.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/models/adapter.go b/models/adapter.go index af1b1c1..38b1f44 100644 --- a/models/adapter.go +++ b/models/adapter.go @@ -78,7 +78,7 @@ func RemoveDCOInstance(linkId, dcoId string) IModelError { return dcoAdapterInstance.Remove(linkId, dcoId) } -// link +// dco link func AddDCOLink(submitter string, opt *DCOLinkCreateOption) IModelError { return dcoLinkAdapterInstance.Add(submitter, opt) @@ -92,7 +92,7 @@ func ListDCOLink(platform string, orgs []string) ([]LinkInfo, IModelError) { return dcoLinkAdapterInstance.List(platform, orgs) } -func GetLinkDCO(linkId, dcoId string) (OrgInfo, CLAInfo, IModelError) { +func GetLinkDCO1(linkId, dcoId string) (OrgInfo, CLAInfo, IModelError) { return dcoLinkAdapterInstance.GetDCO(linkId, dcoId) } @@ -100,7 +100,7 @@ func ListDCOs(linkId string) ([]CLADetail, IModelError) { return dcoLinkAdapterInstance.ListDCOs(linkId) } -func GetDCOLink(linkId string) (OrgInfo, IModelError) { +func GetDCOLink1(linkId string) (OrgInfo, IModelError) { return dcoLinkAdapterInstance.GetLink(linkId) } diff --git a/signing/adapter/link.go b/signing/adapter/link.go index 256f66b..329b4e3 100644 --- a/signing/adapter/link.go +++ b/signing/adapter/link.go @@ -48,7 +48,7 @@ func (adapter *linkAdatper) GetLink(linkId string) ( func (adapter *linkAdatper) GetLinkCLA(linkId, claId string) ( org models.OrgInfo, cla models.CLAInfo, merr models.IModelError, ) { - v, err := adapter.s.FindLinkCLA(&domain.CLAIndex{ + v, err := adapter.s.FindCLA(&domain.CLAIndex{ LinkId: linkId, CLAId: claId, }) diff --git a/signing/app/link.go b/signing/app/link.go index 4f110d6..ab8e2ae 100644 --- a/signing/app/link.go +++ b/signing/app/link.go @@ -29,7 +29,7 @@ type LinkService interface { List(cmd *CmdToListLink) ([]repository.LinkSummary, error) Find(linkId string) (dto LinkDTO, err error) FindCLAs(cmd *CmdToFindCLAs) ([]CLADetailDTO, error) - FindLinkCLA(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) + FindCLA(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) } type linkService struct { @@ -118,7 +118,7 @@ func (s *linkService) FindCLAs(cmd *CmdToFindCLAs) ([]CLADetailDTO, error) { return r, nil } -func (s *linkService) FindLinkCLA(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) { +func (s *linkService) FindCLA(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) { v, err := s.repo.Find(cmd.LinkId) if err != nil { return From 0f83ea4e51ca25b8511d9ef5b2cb030214ae6756 Mon Sep 17 00:00:00 2001 From: zengchen1024 Date: Wed, 26 Jul 2023 14:23:45 +0800 Subject: [PATCH 3/4] repository --- signing/adapter/dco_link.go | 2 +- signing/app/dco_link.go | 9 +++-- signing/app/dco_link_dto.go | 4 +-- signing/app/link.go | 5 ++- signing/app/link_dto.go | 16 +++++++-- signing/domain/dp/link_type.go | 34 +++++++++++++++++++ signing/domain/link.go | 1 + signing/domain/repository/link.go | 8 +++-- signing/infrastructure/repositoryimpl/link.go | 1 + .../infrastructure/repositoryimpl/link_do.go | 9 +++++ 10 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 signing/domain/dp/link_type.go diff --git a/signing/adapter/dco_link.go b/signing/adapter/dco_link.go index 8925751..55c0308 100644 --- a/signing/adapter/dco_link.go +++ b/signing/adapter/dco_link.go @@ -94,7 +94,7 @@ func (adapter *dcoLinkAdapter) ListDCOs(linkId string) ([]models.CLADetail, mode // List func (adapter *dcoLinkAdapter) List(platform string, orgs []string) ([]models.LinkInfo, models.IModelError) { - v, err := adapter.s.List(&app.CmdToListDCOLink{ + v, err := adapter.s.List(&app.CmdToListLink{ Platform: platform, Orgs: orgs, }) diff --git a/signing/app/dco_link.go b/signing/app/dco_link.go index 0474421..097c956 100644 --- a/signing/app/dco_link.go +++ b/signing/app/dco_link.go @@ -4,6 +4,7 @@ import ( commonRepo "github.com/opensourceways/app-cla-server/common/domain/repository" "github.com/opensourceways/app-cla-server/signing/domain" "github.com/opensourceways/app-cla-server/signing/domain/claservice" + "github.com/opensourceways/app-cla-server/signing/domain/dp" "github.com/opensourceways/app-cla-server/signing/domain/repository" ) @@ -24,7 +25,7 @@ func NewDCOLinkService( type DCOLinkService interface { Add(cmd *CmdToAddDCOLink) error Remove(linkId string) error - List(cmd *CmdToListDCOLink) ([]repository.LinkSummary, error) + List(cmd *CmdToListLink) ([]repository.LinkSummary, error) Find(linkId string) (dto LinkDTO, err error) FindDCOs(string) ([]CLADetailDTO, error) FindDCO(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) @@ -79,8 +80,10 @@ func (s *dcoLinkService) checkIfCanRemove(linkId string) (bool, error) { return !v, err } -func (s *dcoLinkService) List(cmd *CmdToListDCOLink) ([]repository.LinkSummary, error) { - return s.repo.FindAll(cmd) +func (s *dcoLinkService) List(cmd *CmdToListLink) ([]repository.LinkSummary, error) { + opt := cmd.toOpt(dp.LinkTypeDCO) + + return s.repo.FindAll(&opt) } func (s *dcoLinkService) FindDCOs(linkId string) ([]CLADetailDTO, error) { diff --git a/signing/app/dco_link_dto.go b/signing/app/dco_link_dto.go index cdc055e..e51262e 100644 --- a/signing/app/dco_link_dto.go +++ b/signing/app/dco_link_dto.go @@ -5,7 +5,6 @@ import ( "github.com/opensourceways/app-cla-server/signing/domain" "github.com/opensourceways/app-cla-server/signing/domain/dp" - "github.com/opensourceways/app-cla-server/signing/domain/repository" ) type CmdToAddDCOLink struct { @@ -23,11 +22,10 @@ func (cmd *CmdToAddDCOLink) toDCOLink() domain.Link { } return domain.Link{ + Type: dp.LinkTypeDCO, Org: cmd.Org, CLAs: v, CLANum: len(cmd.DCOs), Submitter: cmd.Submitter, } } - -type CmdToListDCOLink = repository.FindLinksOpt diff --git a/signing/app/link.go b/signing/app/link.go index ab8e2ae..637076b 100644 --- a/signing/app/link.go +++ b/signing/app/link.go @@ -4,6 +4,7 @@ import ( commonRepo "github.com/opensourceways/app-cla-server/common/domain/repository" "github.com/opensourceways/app-cla-server/signing/domain" "github.com/opensourceways/app-cla-server/signing/domain/claservice" + "github.com/opensourceways/app-cla-server/signing/domain/dp" "github.com/opensourceways/app-cla-server/signing/domain/repository" ) @@ -91,7 +92,9 @@ func (s *linkService) checkIfCanRemove(linkId string) (bool, error) { } func (s *linkService) List(cmd *CmdToListLink) ([]repository.LinkSummary, error) { - return s.repo.FindAll(cmd) + opt := cmd.toOpt(dp.LinkTypeCLA) + + return s.repo.FindAll(&opt) } func (s *linkService) FindCLAs(cmd *CmdToFindCLAs) ([]CLADetailDTO, error) { diff --git a/signing/app/link_dto.go b/signing/app/link_dto.go index b86df11..acd79a5 100644 --- a/signing/app/link_dto.go +++ b/signing/app/link_dto.go @@ -23,6 +23,7 @@ func (cmd *CmdToAddLink) toLink() domain.Link { } return domain.Link{ + Type: dp.LinkTypeCLA, Org: cmd.Org, CLAs: v, CLANum: len(cmd.CLAs), @@ -30,8 +31,6 @@ func (cmd *CmdToAddLink) toLink() domain.Link { } } -type CmdToListLink = repository.FindLinksOpt - type CmdToFindCLAs struct { LinkId string Type dp.CLAType @@ -47,3 +46,16 @@ type LinkDTO struct { Org domain.OrgInfo Email domain.EmailInfo } + +type CmdToListLink struct { + Orgs []string + Platform string +} + +func (cmd *CmdToListLink) toOpt(t dp.LinkType) repository.FindLinksOpt { + return repository.FindLinksOpt{ + Type: t, + Orgs: cmd.Orgs, + Platform: cmd.Platform, + } +} diff --git a/signing/domain/dp/link_type.go b/signing/domain/dp/link_type.go new file mode 100644 index 0000000..8bf6fdd --- /dev/null +++ b/signing/domain/dp/link_type.go @@ -0,0 +1,34 @@ +package dp + +import "errors" + +var ( + LinkTypeCLA = linkType("cla") + LinkTypeDCO = linkType("dco") +) + +type LinkType interface { + LinkType() string +} + +type linkType string + +func (v linkType) LinkType() string { + return string(v) +} + +func NewLinkType(v string) (LinkType, error) { + if v == LinkTypeCLA.LinkType() { + return LinkTypeCLA, nil + } + + if v == LinkTypeDCO.LinkType() { + return LinkTypeDCO, nil + } + + return nil, errors.New("invalid link type") +} + +func IsLinkTypeCLA(v LinkType) bool { + return v != nil && v.LinkType() == LinkTypeCLA.LinkType() +} diff --git a/signing/domain/link.go b/signing/domain/link.go index 9018cdd..029e2ac 100644 --- a/signing/domain/link.go +++ b/signing/domain/link.go @@ -27,6 +27,7 @@ type Link struct { Id string Org OrgInfo Email EmailInfo + Type dp.LinkType CLAs []CLA Submitter string CLANum int diff --git a/signing/domain/repository/link.go b/signing/domain/repository/link.go index f26f58d..067e46b 100644 --- a/signing/domain/repository/link.go +++ b/signing/domain/repository/link.go @@ -1,10 +1,14 @@ package repository -import "github.com/opensourceways/app-cla-server/signing/domain" +import ( + "github.com/opensourceways/app-cla-server/signing/domain" + "github.com/opensourceways/app-cla-server/signing/domain/dp" +) type FindLinksOpt struct { - Platform string + Type dp.LinkType Orgs []string + Platform string } type LinkSummary struct { diff --git a/signing/infrastructure/repositoryimpl/link.go b/signing/infrastructure/repositoryimpl/link.go index f860600..084096a 100644 --- a/signing/infrastructure/repositoryimpl/link.go +++ b/signing/infrastructure/repositoryimpl/link.go @@ -89,6 +89,7 @@ func (impl *link) Find(linkId string) (r domain.Link, err error) { func (impl *link) FindAll(opt *repository.FindLinksOpt) ([]repository.LinkSummary, error) { filter := bson.M{ fieldDeleted: false, + fieldType: opt.Type.LinkType(), childField(fieldOrg, fieldOrg): bson.M{mongodbCmdIn: opt.Orgs}, childField(fieldOrg, fieldPlatform): opt.Platform, } diff --git a/signing/infrastructure/repositoryimpl/link_do.go b/signing/infrastructure/repositoryimpl/link_do.go index 8d32860..bda6f3e 100644 --- a/signing/infrastructure/repositoryimpl/link_do.go +++ b/signing/infrastructure/repositoryimpl/link_do.go @@ -10,6 +10,7 @@ import ( const ( fieldOrg = "org" fieldCLAs = "clas" + fieldType = "type" fieldRemoved = "removed" fieldPlatform = "platform" ) @@ -19,6 +20,7 @@ func toLinkDO(v *domain.Link) linkDO { Id: v.Id, Org: toOrgInfoDO(&v.Org), Email: toEmailInfoDO(&v.Email), + Type: v.Type.LinkType(), Submitter: v.Submitter, CLANum: v.CLANum, } @@ -37,6 +39,7 @@ type linkDO struct { Id string `bson:"id" json:"id" required:"true"` Org orgInfoDO `bson:"org" json:"org" required:"true"` Email emailInfoDO `bson:"email" json:"email" required:"true"` + Type string `bson:"type" json:"type" required:"true"` Submitter string `bson:"submitter" json:"submitter" required:"true"` CLAs []claDO `bson:"clas" json:"clas"` CLANum int `bson:"cla_num" json:"cla_num"` @@ -51,6 +54,11 @@ func (do *linkDO) toLink(link *domain.Link) (err error) { return } + t, err := dp.NewLinkType(do.Type) + if err != nil { + return + } + clas := make([]domain.CLA, len(do.CLAs)) for i := range do.CLAs { if clas[i], err = do.CLAs[i].toCLA(); err != nil { @@ -62,6 +70,7 @@ func (do *linkDO) toLink(link *domain.Link) (err error) { Id: do.Id, Org: do.Org.toOrgInfo(), Email: e, + Type: t, CLAs: clas, Submitter: do.Submitter, CLANum: do.CLANum, From 6793a4431f73dfc61f42876519c25fe84d316e8c Mon Sep 17 00:00:00 2001 From: zengchen1024 Date: Wed, 26 Jul 2023 16:18:26 +0800 Subject: [PATCH 4/4] check link type --- models/adapter.go | 10 ++------ models/init.go | 2 -- signing/adapter/dco_link.go | 48 ------------------------------------- signing/app/cla.go | 23 +++++++++++++++--- signing/app/dco.go | 24 ++++++++++++++++--- signing/app/dco_link.go | 47 +++++++----------------------------- signing/app/link.go | 8 +++++++ 7 files changed, 59 insertions(+), 103 deletions(-) diff --git a/models/adapter.go b/models/adapter.go index 38b1f44..ba9f888 100644 --- a/models/adapter.go +++ b/models/adapter.go @@ -48,6 +48,8 @@ func ListLink(platform string, orgs []string) ([]LinkInfo, IModelError) { return linkAdapterInstance.List(platform, orgs) } +// function of signing + func GetLinkCLA(linkId, claId string) (OrgInfo, CLAInfo, IModelError) { return linkAdapterInstance.GetLinkCLA(linkId, claId) } @@ -92,18 +94,10 @@ func ListDCOLink(platform string, orgs []string) ([]LinkInfo, IModelError) { return dcoLinkAdapterInstance.List(platform, orgs) } -func GetLinkDCO1(linkId, dcoId string) (OrgInfo, CLAInfo, IModelError) { - return dcoLinkAdapterInstance.GetDCO(linkId, dcoId) -} - func ListDCOs(linkId string) ([]CLADetail, IModelError) { return dcoLinkAdapterInstance.ListDCOs(linkId) } -func GetDCOLink1(linkId string) (OrgInfo, IModelError) { - return dcoLinkAdapterInstance.GetLink(linkId) -} - // corp signing func VCOfCorpSigning(linkId, email string) (string, IModelError) { diff --git a/models/init.go b/models/init.go index 53bf9ab..cd47d5c 100644 --- a/models/init.go +++ b/models/init.go @@ -171,8 +171,6 @@ type dcoLinkAdapter interface { Add(submitter string, opt *DCOLinkCreateOption) IModelError Remove(linkId string) IModelError List(platform string, orgs []string) ([]LinkInfo, IModelError) - GetLink(linkId string) (org OrgInfo, merr IModelError) - GetDCO(linkId, dcoId string) (OrgInfo, CLAInfo, IModelError) ListDCOs(linkId string) ([]CLADetail, IModelError) } diff --git a/signing/adapter/dco_link.go b/signing/adapter/dco_link.go index 55c0308..a6512b6 100644 --- a/signing/adapter/dco_link.go +++ b/signing/adapter/dco_link.go @@ -5,7 +5,6 @@ import ( "github.com/opensourceways/app-cla-server/models" "github.com/opensourceways/app-cla-server/signing/app" - "github.com/opensourceways/app-cla-server/signing/domain" "github.com/opensourceways/app-cla-server/signing/domain/dp" ) @@ -25,53 +24,6 @@ type dcoLinkAdapter struct { s app.DCOLinkService } -func (adapter *dcoLinkAdapter) GetLink(linkId string) ( - org models.OrgInfo, merr models.IModelError, -) { - v, err := adapter.s.Find(linkId) - if err != nil { - merr = toModelError(err) - - return - } - - org.OrgID = v.Org.Org - org.Platform = v.Org.Platform - org.OrgAlias = v.Org.Alias - org.OrgEmail = v.Email.Addr.EmailAddr() - org.OrgEmailPlatform = v.Email.Platform - - return -} - -// GetDCOLinkDCO -func (adapter *dcoLinkAdapter) GetDCO(linkId, claId string) ( - org models.OrgInfo, cla models.CLAInfo, merr models.IModelError, -) { - v, err := adapter.s.FindDCO(&domain.CLAIndex{ - LinkId: linkId, - CLAId: claId, - }) - if err != nil { - merr = toModelError(err) - - return - } - - org.OrgID = v.Org.Org - org.Platform = v.Org.Platform - org.OrgAlias = v.Org.Alias - org.OrgEmail = v.Email.Addr.EmailAddr() - org.OrgEmailPlatform = v.Email.Platform - - cla.CLAId = v.CLA.Id - cla.CLAFile = v.CLA.LocalFile - cla.CLALang = v.CLA.Language - cla.Fields = toFields(v.CLA.Fileds) - - return -} - // ListDCOs func (adapter *dcoLinkAdapter) ListDCOs(linkId string) ([]models.CLADetail, models.IModelError) { v, err := adapter.s.FindDCOs(linkId) diff --git a/signing/app/cla.go b/signing/app/cla.go index 8b193de..79e9b5e 100644 --- a/signing/app/cla.go +++ b/signing/app/cla.go @@ -36,8 +36,25 @@ type claService struct { individual repository.IndividualSigning } +func (s *claService) findLink(linkId string) (domain.Link, error) { + v, err := s.repo.Find(linkId) + if err != nil { + if commonRepo.IsErrorResourceNotFound(err) { + err = domain.NewDomainError(domain.ErrorCodeLinkNotExists) + } + + return v, err + } + + if !dp.IsLinkTypeCLA(v.Type) { + return v, domain.NewDomainError(domain.ErrorCodeLinkNotExists) + } + + return v, nil +} + func (s *claService) Add(linkId string, cmd *CmdToAddCLA) error { - link, err := s.repo.Find(linkId) + link, err := s.findLink(linkId) if err != nil { if commonRepo.IsErrorResourceNotFound(err) { err = domain.NewDomainError(domain.ErrorCodeLinkNotExists) @@ -52,7 +69,7 @@ func (s *claService) Add(linkId string, cmd *CmdToAddCLA) error { } func (s *claService) Remove(cmd domain.CLAIndex) error { - link, err := s.repo.Find(cmd.LinkId) + link, err := s.findLink(cmd.LinkId) if err != nil { if commonRepo.IsErrorResourceNotFound(err) { err = domain.NewDomainError(domain.ErrorCodeLinkNotExists) @@ -115,7 +132,7 @@ func (s *claService) checkIfCanRemoveCorpCLA(cmd *domain.CLAIndex) (bool, error) } func (s *claService) List(linkId string) (individuals []CLADTO, corps []CLADTO, err error) { - v, err := s.repo.Find(linkId) + v, err := s.findLink(linkId) if err != nil { return } diff --git a/signing/app/dco.go b/signing/app/dco.go index 1dc1057..9bcfec1 100644 --- a/signing/app/dco.go +++ b/signing/app/dco.go @@ -4,6 +4,7 @@ import ( commonRepo "github.com/opensourceways/app-cla-server/common/domain/repository" "github.com/opensourceways/app-cla-server/signing/domain" "github.com/opensourceways/app-cla-server/signing/domain/claservice" + "github.com/opensourceways/app-cla-server/signing/domain/dp" "github.com/opensourceways/app-cla-server/signing/domain/repository" ) @@ -32,8 +33,25 @@ type dcoService struct { individual repository.IndividualSigning } +func (s *dcoService) findLink(linkId string) (domain.Link, error) { + v, err := s.repo.Find(linkId) + if err != nil { + if commonRepo.IsErrorResourceNotFound(err) { + err = domain.NewDomainError(domain.ErrorCodeDCOLinkNotExists) + } + + return v, err + } + + if dp.IsLinkTypeCLA(v.Type) { + return v, domain.NewDomainError(domain.ErrorCodeDCOLinkNotExists) + } + + return v, nil +} + func (s *dcoService) Add(linkId string, cmd *CmdToAddDCO) error { - link, err := s.repo.Find(linkId) + link, err := s.findLink(linkId) if err != nil { if commonRepo.IsErrorResourceNotFound(err) { err = domain.NewDomainError(domain.ErrorCodeDCOLinkNotExists) @@ -48,7 +66,7 @@ func (s *dcoService) Add(linkId string, cmd *CmdToAddDCO) error { } func (s *dcoService) Remove(cmd domain.CLAIndex) error { - link, err := s.repo.Find(cmd.LinkId) + link, err := s.findLink(cmd.LinkId) if err != nil { if commonRepo.IsErrorResourceNotFound(err) { err = domain.NewDomainError(domain.ErrorCodeDCOLinkNotExists) @@ -82,7 +100,7 @@ func (s *dcoService) checkIfCanRemove(cmd *domain.CLAIndex) error { } func (s *dcoService) List(linkId string) (dcos []CLADTO, err error) { - v, err := s.repo.Find(linkId) + v, err := s.findLink(linkId) if err != nil { return } diff --git a/signing/app/dco_link.go b/signing/app/dco_link.go index 097c956..fd59764 100644 --- a/signing/app/dco_link.go +++ b/signing/app/dco_link.go @@ -26,9 +26,7 @@ type DCOLinkService interface { Add(cmd *CmdToAddDCOLink) error Remove(linkId string) error List(cmd *CmdToListLink) ([]repository.LinkSummary, error) - Find(linkId string) (dto LinkDTO, err error) FindDCOs(string) ([]CLADetailDTO, error) - FindDCO(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) } type dcoLinkService struct { @@ -71,6 +69,10 @@ func (s *dcoLinkService) Remove(linkId string) error { return err } + if dp.IsLinkTypeCLA(v.Type) { + return nil + } + return s.repo.Remove(&v) } @@ -92,6 +94,10 @@ func (s *dcoLinkService) FindDCOs(linkId string) ([]CLADetailDTO, error) { return nil, err } + if dp.IsLinkTypeCLA(v.Type) { + return nil, nil + } + r := make([]CLADetailDTO, 0, len(v.CLAs)) for i := range v.CLAs { item := &v.CLAs[i] @@ -105,40 +111,3 @@ func (s *dcoLinkService) FindDCOs(linkId string) ([]CLADetailDTO, error) { return r, nil } - -func (s *dcoLinkService) FindDCO(cmd *domain.CLAIndex) (dto LinkCLADTO, err error) { - v, err := s.repo.Find(cmd.LinkId) - if err != nil { - return - } - - cla := v.FindCLA(cmd.CLAId) - if cla == nil { - err = domain.NewDomainError(domain.ErrorCodeDCONotExists) - - return - } - - dto.Org = v.Org - dto.Email = v.Email - dto.CLA = CLADetailDTO{ - Id: cla.Id, - Fileds: cla.Fields, - Language: cla.Language.Language(), - LocalFile: s.dco.CLALocalFilePath(cmd), - } - - return -} - -func (s *dcoLinkService) Find(linkId string) (dto LinkDTO, err error) { - v, err := s.repo.Find(linkId) - if err != nil { - return - } - - dto.Org = v.Org - dto.Email = v.Email - - return -} diff --git a/signing/app/link.go b/signing/app/link.go index 637076b..a26cf10 100644 --- a/signing/app/link.go +++ b/signing/app/link.go @@ -74,6 +74,10 @@ func (s *linkService) Remove(linkId string) error { return err } + if !dp.IsLinkTypeCLA(v.Type) { + return nil + } + return s.repo.Remove(&v) } @@ -103,6 +107,10 @@ func (s *linkService) FindCLAs(cmd *CmdToFindCLAs) ([]CLADetailDTO, error) { return nil, err } + if !dp.IsLinkTypeCLA(v.Type) { + return nil, nil + } + t := cmd.Type.CLAType() r := make([]CLADetailDTO, 0, len(v.CLAs))