diff --git a/.bicep/logicapps/workflows/CleanupOrganization/workflow.json b/.bicep/logicapps/workflows/CleanupOrganization/workflow.json index f0a5b923..fb6f6d46 100644 --- a/.bicep/logicapps/workflows/CleanupOrganization/workflow.json +++ b/.bicep/logicapps/workflows/CleanupOrganization/workflow.json @@ -14,6 +14,23 @@ }, "runAfter": {}, "trackedProperties": {} + }, + "HTTP_DEMOTE_ADMIN_OUTSIDE_COLLABORATORS": { + "inputs": { + "authentication": { + "identity": "@concat('/subscriptions/59d64684-e7c9-4397-8982-6b775a473b74/resourcegroups/OpenTech_GitHub_Mgmt/providers/Microsoft.ManagedIdentity/userAssignedIdentities/', parameters('ManagedIdentityName'))", + "type": "ManagedServiceIdentity" + }, + "method": "GET", + "uri": "@concat(parameters('GHMgmDomain'), '/utility/demote-outside-collaborators-admin')" + }, + "runAfter": { + "HTTP_ORG_CLEANUP": [ + "SUCCEEDED" + ] + }, + "trackedProperties": {}, + "type": "Http" } }, "contentVersion": "1.0.0.0", diff --git a/src/goapp/controller/approval-type/approval-type-controller-interface.go b/src/goapp/controller/approval-type/approval-type-controller-interface.go new file mode 100644 index 00000000..09d3ec44 --- /dev/null +++ b/src/goapp/controller/approval-type/approval-type-controller-interface.go @@ -0,0 +1,8 @@ +package approvaltype + +import "net/http" + +type ApprovalTypeController interface { + GetApprovalTypeById(w http.ResponseWriter, r *http.Request) + GetApprovalTypes(w http.ResponseWriter, r *http.Request) +} diff --git a/src/goapp/controller/approval-type/approval-type-controller.go b/src/goapp/controller/approval-type/approval-type-controller.go new file mode 100644 index 00000000..f3f48153 --- /dev/null +++ b/src/goapp/controller/approval-type/approval-type-controller.go @@ -0,0 +1,96 @@ +package approvaltype + +import ( + "encoding/json" + "main/model" + "main/pkg/appinsights_wrapper" + "main/service" + "net/http" + "strconv" + + "github.com/gorilla/mux" +) + +type approvalTypeController struct { + *service.Service +} + +func NewApprovalTypeController(service *service.Service) ApprovalTypeController { + return &approvalTypeController{service} +} + +func (c *approvalTypeController) GetApprovalTypeById(w http.ResponseWriter, r *http.Request) { + logger := appinsights_wrapper.NewClient() + defer logger.EndOperation() + + vars := mux.Vars(r) + id, _ := strconv.Atoi(vars["id"]) + + approvalType, err := c.ApprovalType.GetById(id) + if err != nil { + logger.TrackException(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(approvalType) +} + +func (c *approvalTypeController) GetApprovalTypes(w http.ResponseWriter, r *http.Request) { + logger := appinsights_wrapper.NewClient() + defer logger.EndOperation() + + var approvalTypes []model.ApprovalType + var total int64 + var err error + + params := r.URL.Query() + if params.Has("offset") && params.Has("filter") { + filter, _ := strconv.Atoi(params["filter"][0]) + offset, _ := strconv.Atoi(params["offset"][0]) + opt := model.FilterOptions{ + Filter: filter, + Offset: offset, + Search: params.Get("search"), + Orderby: params.Get("orderby"), + Ordertype: params.Get("ordertype"), + } + approvalTypes, total, err = c.ApprovalType.Get(&opt) + if err != nil { + logger.TrackException(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + } else { + approvalTypes, total, err = c.ApprovalType.Get(nil) + if err != nil { + logger.TrackException(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } + + for i, v := range approvalTypes { + approvers, err := c.Approver.Get(v.Id) + if err != nil { + logger.TrackException(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + approvalTypes[i].Approvers = approvers + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(struct { + Data []model.ApprovalType `json:"data"` + Total int64 `json:"total"` + }{ + Data: approvalTypes, + Total: total, + }) +} diff --git a/src/goapp/controller/controller.go b/src/goapp/controller/controller.go index d3449e7d..e6401348 100644 --- a/src/goapp/controller/controller.go +++ b/src/goapp/controller/controller.go @@ -3,6 +3,7 @@ package controller import ( cActivity "main/controller/activity" cActivityType "main/controller/activitytype" + cApprovalType "main/controller/approval-type" cContributionArea "main/controller/contributionarea" cExternalLink "main/controller/externallink" cOssContributionSponsor "main/controller/osscontributionsponsor" @@ -12,6 +13,7 @@ import ( type Controller struct { Activity cActivity.ActivityController ActivityType cActivityType.ActivityTypeController + ApprovalType cApprovalType.ApprovalTypeController ContributionArea cContributionArea.ContributionAreaController ExternalLink cExternalLink.ExternalLinkController OssContributionSponsor cOssContributionSponsor.OSSContributionSponsorController @@ -41,6 +43,12 @@ func NewActivityTypeController(serv *service.Service) ControllerOptionFunc { } } +func NewApprovalTypeController(serv *service.Service) ControllerOptionFunc { + return func(c *Controller) { + c.ApprovalType = cApprovalType.NewApprovalTypeController(serv) + } +} + func NewContributionAreaController(serv *service.Service) ControllerOptionFunc { return func(c *Controller) { c.ContributionArea = cContributionArea.NewContributionAreaController(serv) diff --git a/src/goapp/init.go b/src/goapp/init.go index 72535f7c..d4c165dc 100644 --- a/src/goapp/init.go +++ b/src/goapp/init.go @@ -14,19 +14,23 @@ var ( db database.Database = database.NewDatabase(conf) repo = r.NewRepository( - r.NewActivity(db), - r.NewActivityContributionArea(db), - r.NewActivityHelp(db), - r.NewActivityType(db), - r.NewContributionArea(db), - r.NewExternalLink(db), - r.NewOssContributionSponsor(db)) + r.NewActivity(&db), + r.NewActivityContributionArea(&db), + r.NewActivityHelp(&db), + r.NewActivityType(&db), + r.NewApprovalType(&db), + r.NewApprover(&db), + r.NewContributionArea(&db), + r.NewExternalLink(&db), + r.NewOssContributionSponsor(&db)) serv = s.NewService( s.NewActivityService(repo), s.NewActivityTypeService(repo), - s.NewContributionAreaService(repo), s.NewActivityHelpService(repo), + s.NewApprovalTypeService(repo), + s.NewApproverService(repo), + s.NewContributionAreaService(repo), s.NewEmailService(conf), s.NewExternalLinkService(repo), s.NewOssContributionSponsorService(repo)) @@ -34,6 +38,7 @@ var ( cont = c.NewController( c.NewActivityController(serv), c.NewActivityTypeController(serv), + c.NewApprovalTypeController(serv), c.NewContributionAreaController(serv), c.NewExternalLinkController(serv), c.NewOssContributionSponsorController(serv)) diff --git a/src/goapp/model/approval-type.go b/src/goapp/model/approval-type.go new file mode 100644 index 00000000..3ec17279 --- /dev/null +++ b/src/goapp/model/approval-type.go @@ -0,0 +1,15 @@ +package model + +import "time" + +type ApprovalType struct { + Id int `json:"id"` + Name string `json:"name"` + Approvers []RepositoryApprover `json:"approvers"` + IsActive bool `json:"isActive"` + IsArchived bool `json:"isArchived"` + Created time.Time `json:"created"` + CreatedBy string `json:"createdBy"` + Modified time.Time `json:"modified"` + ModifiedBy string `json:"modifiedBy"` +} diff --git a/src/goapp/model/common.go b/src/goapp/model/common.go new file mode 100644 index 00000000..796bc469 --- /dev/null +++ b/src/goapp/model/common.go @@ -0,0 +1,9 @@ +package model + +type FilterOptions struct { + Filter int + Offset int + Search string + Orderby string + Ordertype string +} diff --git a/src/goapp/model/repository-approver.go b/src/goapp/model/repository-approver.go new file mode 100644 index 00000000..903afb99 --- /dev/null +++ b/src/goapp/model/repository-approver.go @@ -0,0 +1,7 @@ +package model + +type RepositoryApprover struct { + ApprovalTypeId int `json:"approvalTypeId"` + ApproverEmail string `json:"approverEmail"` + ApproverName string `json:"approverName"` +} diff --git a/src/goapp/pkg/ghmgmtdb/approvalTypesDb.go b/src/goapp/pkg/ghmgmtdb/approvalTypesDb.go index b0134a9e..82ca57d4 100644 --- a/src/goapp/pkg/ghmgmtdb/approvalTypesDb.go +++ b/src/goapp/pkg/ghmgmtdb/approvalTypesDb.go @@ -1,8 +1,6 @@ package ghmgmt import ( - "fmt" - "strconv" "time" ) @@ -28,89 +26,6 @@ func GetAllActiveApprovers() interface{} { return result } -func SelectApprovalTypes() ([]map[string]interface{}, error) { - db := ConnectDb() - defer db.Close() - - result, err := db.ExecuteStoredProcedureWithResult("usp_RepositoryApprovalType_Select", nil) - if err != nil { - return nil, err - } - - return result, nil -} - -func SelectApprovalTypesByFilter(offset, filter int, orderby, ordertype, search string) ([]map[string]interface{}, error) { - db := ConnectDb() - defer db.Close() - - param := map[string]interface{}{ - "Offset": offset, - "Filter": filter, - "Search": search, - "OrderBy": orderby, - "OrderType": ordertype, - } - - result, err := db.ExecuteStoredProcedureWithResult("usp_RepositoryApprovalType_Select_ByOption", param) - if err != nil { - return nil, err - } - - return result, nil -} - -func SelectTotalApprovalTypes() int { - db := ConnectDb() - defer db.Close() - - result, _ := db.ExecuteStoredProcedureWithResult("usp_RepositoryApprovalType_TotalCount", nil) - total, err := strconv.Atoi(fmt.Sprint(result[0]["Total"])) - if err != nil { - return 0 - } - return total -} - -func SelectApprovalTypeById(id int) (*ApprovalType, error) { - db := ConnectDb() - defer db.Close() - - param := map[string]interface{}{ - "Id": id, - } - - result, err := db.ExecuteStoredProcedureWithResult("usp_RepositoryApprovalType_Select_ById", param) - if err != nil { - return nil, err - } - - approvalType := ApprovalType{ - Id: int(result[0]["Id"].(int64)), - Name: result[0]["Name"].(string), - IsActive: result[0]["IsActive"].(bool), - IsArchived: result[0]["IsArchived"].(bool), - } - - if result[0]["Created"] != nil { - approvalType.Created = result[0]["Created"].(time.Time) - } - - if result[0]["CreatedBy"] != nil { - approvalType.CreatedBy = result[0]["CreatedBy"].(string) - } - - if result[0]["Modified"] != nil { - approvalType.Modified = result[0]["Modified"].(time.Time) - } - - if result[0]["ModifiedBy"] != nil { - approvalType.ModifiedBy = result[0]["ModifiedBy"].(string) - } - - return &approvalType, nil -} - func InsertApprovalType(approvalType ApprovalType) (int, error) { db := ConnectDb() defer db.Close() diff --git a/src/goapp/pkg/github/github.go b/src/goapp/pkg/github/github.go index 6d234ec4..1ba71be5 100644 --- a/src/goapp/pkg/github/github.go +++ b/src/goapp/pkg/github/github.go @@ -104,6 +104,15 @@ func GetRepository(repoName string, org string) (*github.Repository, error) { return repo, nil } +func GetPermissionLevel(repoOwner string, repoName string, username string) (string, error) { + client := CreateClient(os.Getenv("GH_TOKEN")) + permission, _, err := client.Repositories.GetPermissionLevel(context.Background(), repoOwner, repoName, username) + if err != nil { + return "", err + } + return permission.GetPermission(), nil +} + func GetRepositoryReadmeById(owner, repoName string) (string, error) { client := CreateClient(os.Getenv("GH_TOKEN")) diff --git a/src/goapp/repository/activity/implement.go b/src/goapp/repository/activity/implement.go index ebdcc9b2..a109ecc7 100644 --- a/src/goapp/repository/activity/implement.go +++ b/src/goapp/repository/activity/implement.go @@ -8,10 +8,10 @@ import ( ) type activityRepository struct { - db.Database + *db.Database } -func NewActivityRepository(database db.Database) ActivityRepository { +func NewActivityRepository(database *db.Database) ActivityRepository { return &activityRepository{database} } diff --git a/src/goapp/repository/activitycontributionarea/implement.go b/src/goapp/repository/activitycontributionarea/implement.go index da643a53..4380d9d3 100644 --- a/src/goapp/repository/activitycontributionarea/implement.go +++ b/src/goapp/repository/activitycontributionarea/implement.go @@ -7,10 +7,10 @@ import ( ) type activityContributionAreaRepository struct { - db.Database + *db.Database } -func NewActivityContributionAreaRepository(database db.Database) ActivityContributionAreaRepository { +func NewActivityContributionAreaRepository(database *db.Database) ActivityContributionAreaRepository { return &activityContributionAreaRepository{database} } diff --git a/src/goapp/repository/activityhelp/implement.go b/src/goapp/repository/activityhelp/implement.go index 930a722a..7c1ac497 100644 --- a/src/goapp/repository/activityhelp/implement.go +++ b/src/goapp/repository/activityhelp/implement.go @@ -6,10 +6,10 @@ import ( ) type activityHelpRepository struct { - db.Database + *db.Database } -func NewActivityHelpRepository(database db.Database) ActivityHelpRepository { +func NewActivityHelpRepository(database *db.Database) ActivityHelpRepository { return &activityHelpRepository{database} } diff --git a/src/goapp/repository/activitytype/implement.go b/src/goapp/repository/activitytype/implement.go index c4bb6a09..b39f0023 100644 --- a/src/goapp/repository/activitytype/implement.go +++ b/src/goapp/repository/activitytype/implement.go @@ -7,10 +7,10 @@ import ( ) type activityTypeRepository struct { - db.Database + *db.Database } -func NewActivityTypeRepository(db db.Database) ActivityTypeRepository { +func NewActivityTypeRepository(db *db.Database) ActivityTypeRepository { return &activityTypeRepository{db} } diff --git a/src/goapp/repository/approval-type/approval-type-repository-interface.go b/src/goapp/repository/approval-type/approval-type-repository-interface.go new file mode 100644 index 00000000..8073938a --- /dev/null +++ b/src/goapp/repository/approval-type/approval-type-repository-interface.go @@ -0,0 +1,12 @@ +package approvalType + +import ( + "main/model" +) + +type ApprovalTypeRepository interface { + Select() ([]model.ApprovalType, error) + SelectById(id int) (*model.ApprovalType, error) + SelectByOption(opt model.FilterOptions) ([]model.ApprovalType, error) + Total() (int64, error) +} diff --git a/src/goapp/repository/approval-type/approval-type-repository.go b/src/goapp/repository/approval-type/approval-type-repository.go new file mode 100644 index 00000000..f0801c47 --- /dev/null +++ b/src/goapp/repository/approval-type/approval-type-repository.go @@ -0,0 +1,107 @@ +package approvalType + +import ( + "database/sql" + db "main/infrastructure/database" + "main/model" +) + +type approvalTypeRepository struct { + *db.Database +} + +func NewApprovalTypeRepository(db *db.Database) ApprovalTypeRepository { + return &approvalTypeRepository{db} +} + +func (r *approvalTypeRepository) Select() ([]model.ApprovalType, error) { + rows, err := r.Query("usp_RepositoryApprovalType_Select") + if err != nil { + return nil, err + } + defer rows.Close() + + approvalTypes, err := r.RowsToMap(rows) + if err != nil { + return nil, err + } + + var result []model.ApprovalType + for _, approvalType := range approvalTypes { + result = append(result, model.ApprovalType{ + Id: int(approvalType["Id"].(int64)), + Name: approvalType["Name"].(string), + IsActive: approvalType["IsActive"].(bool), + IsArchived: approvalType["IsArchived"].(bool), + }) + } + + return result, nil +} + +func (r *approvalTypeRepository) SelectById(id int) (*model.ApprovalType, error) { + row, err := r.QueryRow("usp_RepositoryApprovalType_Select_ById", sql.Named("Id", id)) + if err != nil { + return nil, err + } + + approvalType := model.ApprovalType{} + err = row.Scan( + &approvalType.Id, + &approvalType.Name, + &approvalType.IsArchived, + &approvalType.IsActive, + &approvalType.Created, + &approvalType.CreatedBy, + &approvalType.Modified, + &approvalType.ModifiedBy, + ) + + return &approvalType, err +} + +func (r *approvalTypeRepository) SelectByOption(opt model.FilterOptions) ([]model.ApprovalType, error) { + rows, err := r.Query("usp_RepositoryApprovalType_Select_ByOption", + sql.Named("Offset", opt.Offset), + sql.Named("Filter", opt.Filter), + sql.Named("OrderBy", opt.Orderby), + sql.Named("OrderType", opt.Ordertype), + sql.Named("Search", opt.Search), + ) + if err != nil { + return nil, err + } + defer rows.Close() + + approvalTypes, err := r.RowsToMap(rows) + if err != nil { + return nil, err + } + + var result []model.ApprovalType + for _, approvalType := range approvalTypes { + result = append(result, model.ApprovalType{ + Id: int(approvalType["Id"].(int64)), + Name: approvalType["Name"].(string), + IsActive: approvalType["IsActive"].(bool), + IsArchived: approvalType["IsArchived"].(bool), + }) + } + + return result, nil +} + +func (r *approvalTypeRepository) Total() (int64, error) { + row, err := r.QueryRow("usp_RepositoryApprovalType_TotalCount") + if err != nil { + return 0, err + } + + var total int64 + err = row.Scan(&total) + if err != nil { + return 0, err + } + + return total, nil +} diff --git a/src/goapp/repository/approver/approver-repository-interface.go b/src/goapp/repository/approver/approver-repository-interface.go new file mode 100644 index 00000000..32c39337 --- /dev/null +++ b/src/goapp/repository/approver/approver-repository-interface.go @@ -0,0 +1,9 @@ +package approver + +import ( + "main/model" +) + +type ApproverRepository interface { + SelectByApprovalTypeId(approvalTypeId int) ([]model.RepositoryApprover, error) +} diff --git a/src/goapp/repository/approver/approver-repository.go b/src/goapp/repository/approver/approver-repository.go new file mode 100644 index 00000000..86dee396 --- /dev/null +++ b/src/goapp/repository/approver/approver-repository.go @@ -0,0 +1,39 @@ +package approver + +import ( + "database/sql" + db "main/infrastructure/database" + "main/model" +) + +type approverRepository struct { + *db.Database +} + +func NewApproverRepository(db *db.Database) ApproverRepository { + return &approverRepository{db} +} + +func (r *approverRepository) SelectByApprovalTypeId(approvalTypeId int) ([]model.RepositoryApprover, error) { + rows, err := r.Query("usp_RepositoryApprover_Select_ByApprovalTypeId", sql.Named("RepositoryApprovalTypeId", approvalTypeId)) + if err != nil { + return nil, err + } + defer rows.Close() + + approvers, err := r.RowsToMap(rows) + if err != nil { + return nil, err + } + + var result []model.RepositoryApprover + for _, approver := range approvers { + result = append(result, model.RepositoryApprover{ + ApprovalTypeId: int(approver["RepositoryApprovalTypeId"].(int64)), + ApproverEmail: approver["ApproverUserPrincipalName"].(string), + ApproverName: approver["ApproverName"].(string), + }) + } + + return result, nil +} diff --git a/src/goapp/repository/contributionarea/implement.go b/src/goapp/repository/contributionarea/implement.go index c15ff6dd..71773412 100644 --- a/src/goapp/repository/contributionarea/implement.go +++ b/src/goapp/repository/contributionarea/implement.go @@ -8,10 +8,10 @@ import ( ) type contributionAreaRepository struct { - db.Database + *db.Database } -func NewContributionAreaRepository(database db.Database) ContributionAreaRepository { +func NewContributionAreaRepository(database *db.Database) ContributionAreaRepository { return &contributionAreaRepository{database} } diff --git a/src/goapp/repository/externallink/implement.go b/src/goapp/repository/externallink/implement.go index 724dbbc8..f2e9b887 100644 --- a/src/goapp/repository/externallink/implement.go +++ b/src/goapp/repository/externallink/implement.go @@ -8,10 +8,10 @@ import ( ) type externalLinkRepository struct { - db.Database + *db.Database } -func NewExternalLinkRepository(database db.Database) ExternalLinkRepository { +func NewExternalLinkRepository(database *db.Database) ExternalLinkRepository { return &externalLinkRepository{ Database: database, } diff --git a/src/goapp/repository/osscontributionsponsor/implement.go b/src/goapp/repository/osscontributionsponsor/implement.go index 405e0827..8596b523 100644 --- a/src/goapp/repository/osscontributionsponsor/implement.go +++ b/src/goapp/repository/osscontributionsponsor/implement.go @@ -7,10 +7,10 @@ import ( ) type ossContributionSponsorRepository struct { - db.Database + *db.Database } -func NewOSSContributionSponsorRepository(database db.Database) OssContributionSponsorRepository { +func NewOSSContributionSponsorRepository(database *db.Database) OssContributionSponsorRepository { return &ossContributionSponsorRepository{ Database: database, } diff --git a/src/goapp/repository/repository.go b/src/goapp/repository/repository.go index b413a459..4cbc79c1 100644 --- a/src/goapp/repository/repository.go +++ b/src/goapp/repository/repository.go @@ -6,6 +6,8 @@ import ( rActivityContributionArea "main/repository/activitycontributionarea" rActivityHelp "main/repository/activityhelp" rActivityType "main/repository/activitytype" + rApprovalType "main/repository/approval-type" + rApprover "main/repository/approver" rContributionArea "main/repository/contributionarea" rExternalLink "main/repository/externallink" rOssContributionSponsor "main/repository/osscontributionsponsor" @@ -16,6 +18,8 @@ type Repository struct { ActivityContributionArea rActivityContributionArea.ActivityContributionAreaRepository ActivityHelp rActivityHelp.ActivityHelpRepository ActivityType rActivityType.ActivityTypeRepository + ApprovalType rApprovalType.ApprovalTypeRepository + Approver rApprover.ApproverRepository ContributionArea rContributionArea.ContributionAreaRepository ExternalLink rExternalLink.ExternalLinkRepository OssContributionSponsor rOssContributionSponsor.OssContributionSponsorRepository @@ -33,43 +37,55 @@ func NewRepository(repoOpts ...RepositoryOptionFunc) *Repository { return repository } -func NewActivity(db database.Database) RepositoryOptionFunc { +func NewActivity(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.Activity = rActivity.NewActivityRepository(db) } } -func NewActivityContributionArea(db database.Database) RepositoryOptionFunc { +func NewActivityContributionArea(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.ActivityContributionArea = rActivityContributionArea.NewActivityContributionAreaRepository(db) } } -func NewActivityType(db database.Database) RepositoryOptionFunc { +func NewActivityType(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.ActivityType = rActivityType.NewActivityTypeRepository(db) } } -func NewContributionArea(db database.Database) RepositoryOptionFunc { +func NewApprovalType(db *database.Database) RepositoryOptionFunc { + return func(r *Repository) { + r.ApprovalType = rApprovalType.NewApprovalTypeRepository(db) + } +} + +func NewApprover(db *database.Database) RepositoryOptionFunc { + return func(r *Repository) { + r.Approver = rApprover.NewApproverRepository(db) + } +} + +func NewContributionArea(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.ContributionArea = rContributionArea.NewContributionAreaRepository(db) } } -func NewExternalLink(db database.Database) RepositoryOptionFunc { +func NewExternalLink(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.ExternalLink = rExternalLink.NewExternalLinkRepository(db) } } -func NewOssContributionSponsor(db database.Database) RepositoryOptionFunc { +func NewOssContributionSponsor(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.OssContributionSponsor = rOssContributionSponsor.NewOSSContributionSponsorRepository(db) } } -func NewActivityHelp(db database.Database) RepositoryOptionFunc { +func NewActivityHelp(db *database.Database) RepositoryOptionFunc { return func(r *Repository) { r.ActivityHelp = rActivityHelp.NewActivityHelpRepository(db) } diff --git a/src/goapp/routes.go b/src/goapp/routes.go index bb5125c9..ee3c94d9 100644 --- a/src/goapp/routes.go +++ b/src/goapp/routes.go @@ -200,9 +200,9 @@ func setApiRoutes() { httpRouter.POST("/api/approval-types", m.Chain(rtApi.CreateApprovalType, m.AzureAuth())) httpRouter.PUT("/api/approval-types/{id}", m.Chain(rtApi.EditApprovalTypeById, m.AzureAuth())) httpRouter.PUT("/api/approval-types/{id}/archived", m.Chain(rtApi.SetIsArchivedApprovalTypeById, m.AzureAuth())) - httpRouter.GET("/api/approval-types", m.Chain(rtApi.GetApprovalTypes, m.AzureAuth())) + httpRouter.GET("/api/approval-types", m.Chain(cont.ApprovalType.GetApprovalTypes, m.AzureAuth())) httpRouter.GET("/api/approval-types/active", m.Chain(rtApi.GetActiveApprovalTypes, m.AzureAuth(), m.GitHubAuth())) - httpRouter.GET("/api/approval-types/{id}", m.Chain(rtApi.GetApprovalTypeById, m.AzureAuth())) + httpRouter.GET("/api/approval-types/{id}", m.Chain(cont.ApprovalType.GetApprovalTypeById, m.AzureAuth())) //EXTERNAL LINKS API httpRouter.GET("/api/external-links", m.Chain(cont.ExternalLink.GetExternalLinks, m.AzureAuth(), m.IsUserAdmin())) @@ -269,6 +269,7 @@ func setUtilityRoutes() { httpRouter.GET("/utility/check-ava-inner-source", m.Chain(rtApi.CheckAvaInnerSource, m.GuidAuth())) httpRouter.GET("/utility/check-ava-open-source", m.Chain(rtApi.CheckAvaOpenSource, m.GuidAuth())) httpRouter.GET("/utility/clear-org-members", m.Chain(rtApi.ClearOrgMembers, m.GuidAuth())) + httpRouter.GET("/utility/demote-outside-collaborators-admin", m.Chain(rtApi.DemoteOutsideCollaboratorAdmin, m.GuidAuth())) httpRouter.GET("/utility/repo-owner-scan", m.Chain(rtApi.RepoOwnerScan, m.GuidAuth())) httpRouter.GET("/utility/repo-owner-cleanup", m.Chain(rtApi.RepoOwnersCleanup, m.GuidAuth())) httpRouter.GET("/utility/recurring-approval", m.Chain(rtApi.RecurringApproval, m.GuidAuth())) diff --git a/src/goapp/routes/api/approvalTypes.go b/src/goapp/routes/api/approvalTypes.go index 9cab0f22..df3d4a56 100644 --- a/src/goapp/routes/api/approvalTypes.go +++ b/src/goapp/routes/api/approvalTypes.go @@ -27,107 +27,6 @@ type ApproverDto struct { ApproverName string `json:"approverName"` } -func GetApprovalTypes(w http.ResponseWriter, r *http.Request) { - logger := appinsights_wrapper.NewClient() - defer logger.EndOperation() - - var data []map[string]interface{} - var total int - - params := r.URL.Query() - - if params.Has("offset") && params.Has("filter") { - filter, _ := strconv.Atoi(params["filter"][0]) - offset, _ := strconv.Atoi(params["offset"][0]) - search := params["search"][0] - orderby := params["orderby"][0] - ordertype := params["ordertype"][0] - result, err := db.SelectApprovalTypesByFilter(offset, filter, orderby, ordertype, search) - if err != nil { - logger.LogException(err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - data = result - } else { - result, err := db.SelectApprovalTypes() - if err != nil { - logger.LogException(err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - data = result - } - - //MOVE APPROVAL TYPES FROM DATABASE RESULT TO API DTO - var approvalTypesDto []ApprovalTypeDto - for _, v := range data { - approvalTypeDto := ApprovalTypeDto{ - Id: int(v["Id"].(int64)), - Name: v["Name"].(string), - IsActive: v["IsActive"].(bool), - IsArchived: v["IsArchived"].(bool), - } - - approversResult, err := getApproversByApprovalTypeId(approvalTypeDto.Id) - if err != nil { - logger.LogException(err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - approvalTypeDto.Approvers = *approversResult - - approvalTypesDto = append(approvalTypesDto, approvalTypeDto) - } - - total = db.SelectTotalApprovalTypes() - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(struct { - Data []ApprovalTypeDto `json:"data"` - Total int `json:"total"` - }{ - Data: approvalTypesDto, - Total: total, - }) -} - -func GetApprovalTypeById(w http.ResponseWriter, r *http.Request) { - logger := appinsights_wrapper.NewClient() - defer logger.EndOperation() - - vars := mux.Vars(r) - id, _ := strconv.Atoi(vars["id"]) - - result, err := db.SelectApprovalTypeById(id) - if err != nil { - logger.LogException(err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - approversDto, err := getApproversByApprovalTypeId(result.Id) - if err != nil { - logger.LogException(err) - http.Error(w, err.Error(), http.StatusBadRequest) - return - } - - approvalTypeDto := ApprovalTypeDto{ - Id: result.Id, - Name: result.Name, - Approvers: *approversDto, - IsActive: result.IsActive, - IsArchived: result.IsArchived, - } - - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - json.NewEncoder(w).Encode(approvalTypeDto) -} - func CreateApprovalType(w http.ResponseWriter, r *http.Request) { logger := appinsights_wrapper.NewClient() defer logger.EndOperation() diff --git a/src/goapp/routes/api/github.go b/src/goapp/routes/api/github.go index cc94a81f..59048f1b 100644 --- a/src/goapp/routes/api/github.go +++ b/src/goapp/routes/api/github.go @@ -219,6 +219,46 @@ func ExpiringInvitation(w http.ResponseWriter, r *http.Request) { sendNotification(token, opensourceName, logger) } +func DemoteOutsideCollaboratorAdmin(w http.ResponseWriter, r *http.Request) { + logger := appinsights_wrapper.NewClient() + defer logger.EndOperation() + + org := os.Getenv("GH_ORG_OPENSOURCE") + token := os.Getenv("GH_TOKEN") + + outsideCollaborators := ghAPI.ListOutsideCollaborators(token, org) + + repositories, err := ghAPI.GetRepositoriesFromOrganization(org) + if err != nil { + logger.LogException(err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + for _, outsideCollaborator := range outsideCollaborators { + for _, repository := range repositories { + permission, err := ghAPI.GetPermissionLevel(org, repository.Name, *outsideCollaborator.Login) + if err != nil { + logger.LogException(err) + continue + } + + if permission == "admin" { + // Edit the permission of the outside collaborator to write + resp, err := ghAPI.AddCollaborator(org, repository.Name, outsideCollaborator.GetLogin(), "write") + if err != nil { + logger.LogException(err) + continue + } + + if resp.StatusCode == 204 { + logger.TrackTrace(fmt.Sprintf("Demoted %s to write access in %s", *outsideCollaborator.Login, repository.Name), contracts.Information) + } + } + } + } +} + // Send notifications to those who has pending org invitation that is about to expire tom. func sendNotification(token, org string, logger *appinsights_wrapper.TelemetryClient) { invitations := ghAPI.ListPendingOrgInvitations(token, org) diff --git a/src/goapp/service/approval-type/approval-type-service-interface.go b/src/goapp/service/approval-type/approval-type-service-interface.go new file mode 100644 index 00000000..136ec2b6 --- /dev/null +++ b/src/goapp/service/approval-type/approval-type-service-interface.go @@ -0,0 +1,10 @@ +package approvaltype + +import ( + "main/model" +) + +type ApprovalTypeService interface { + Get(opt *model.FilterOptions) ([]model.ApprovalType, int64, error) + GetById(id int) (*model.ApprovalType, error) +} diff --git a/src/goapp/service/approval-type/approval-type-service.go b/src/goapp/service/approval-type/approval-type-service.go new file mode 100644 index 00000000..dbee60dc --- /dev/null +++ b/src/goapp/service/approval-type/approval-type-service.go @@ -0,0 +1,52 @@ +package approvaltype + +import ( + "main/model" + "main/repository" +) + +type approvalTypeService struct { + Repository *repository.Repository +} + +func NewApprovalTypeService(repository *repository.Repository) ApprovalTypeService { + return &approvalTypeService{repository} +} + +func (s *approvalTypeService) Get(opt *model.FilterOptions) ([]model.ApprovalType, int64, error) { + var approvalTypes []model.ApprovalType + if opt == nil { + data, err := s.Repository.ApprovalType.Select() + if err != nil { + return nil, 0, err + } + approvalTypes = data + } else { + data, err := s.Repository.ApprovalType.SelectByOption(*opt) + if err != nil { + return nil, 0, err + } + approvalTypes = data + } + + total, err := s.Repository.ApprovalType.Total() + if err != nil { + return nil, 0, err + } + + return approvalTypes, total, nil +} + +func (s *approvalTypeService) GetById(id int) (*model.ApprovalType, error) { + data, err := s.Repository.ApprovalType.SelectById(id) + if err != nil { + return nil, err + } + + data.Approvers, err = s.Repository.Approver.SelectByApprovalTypeId(data.Id) + if err != nil { + return nil, err + } + + return data, nil +} diff --git a/src/goapp/service/approver/approver-service-interface.go b/src/goapp/service/approver/approver-service-interface.go new file mode 100644 index 00000000..b56eb9a6 --- /dev/null +++ b/src/goapp/service/approver/approver-service-interface.go @@ -0,0 +1,9 @@ +package approver + +import ( + "main/model" +) + +type ApproverService interface { + Get(approvalTypeId int) ([]model.RepositoryApprover, error) +} diff --git a/src/goapp/service/approver/approver-service.go b/src/goapp/service/approver/approver-service.go new file mode 100644 index 00000000..b3dcb0e7 --- /dev/null +++ b/src/goapp/service/approver/approver-service.go @@ -0,0 +1,18 @@ +package approver + +import ( + "main/model" + "main/repository" +) + +type approverService struct { + Repository *repository.Repository +} + +func NewApproverService(repository *repository.Repository) ApproverService { + return &approverService{repository} +} + +func (s *approverService) Get(approvalTypeId int) ([]model.RepositoryApprover, error) { + return s.Repository.Approver.SelectByApprovalTypeId(approvalTypeId) +} diff --git a/src/goapp/service/service.go b/src/goapp/service/service.go index 3f115f60..512801b2 100644 --- a/src/goapp/service/service.go +++ b/src/goapp/service/service.go @@ -6,6 +6,8 @@ import ( sActivity "main/service/activity" sActivityHelp "main/service/activityhelp" sActivityType "main/service/activitytype" + sApprovalType "main/service/approval-type" + sApprover "main/service/approver" sContributionArea "main/service/contributionarea" sEmail "main/service/email" sExternalLink "main/service/externallink" @@ -16,6 +18,8 @@ type Service struct { Activity sActivity.ActivityService ActivityHelp sActivityHelp.ActivityHelpService ActivityType sActivityType.ActivityTypeService + ApprovalType sApprovalType.ApprovalTypeService + Approver sApprover.ApproverService ContributionArea sContributionArea.ContributionAreaService ExternalLink sExternalLink.ExternalLinkService OssContributionSponsor sOssContributionSponsor.OssContributionSponsorService @@ -52,6 +56,18 @@ func NewActivityTypeService(repo *repository.Repository) ServiceOptionFunc { } } +func NewApprovalTypeService(repo *repository.Repository) ServiceOptionFunc { + return func(s *Service) { + s.ApprovalType = sApprovalType.NewApprovalTypeService(repo) + } +} + +func NewApproverService(repo *repository.Repository) ServiceOptionFunc { + return func(s *Service) { + s.Approver = sApprover.NewApproverService(repo) + } +} + func NewContributionAreaService(repo *repository.Repository) ServiceOptionFunc { return func(s *Service) { s.ContributionArea = sContributionArea.NewContributionAreaService(repo)