Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .bicep/webapp/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"APPROVAL_SYSTEM_APP_MODULE_ORGANIZATION":"",
"APPROVAL_SYSTEM_APP_MODULE_COPILOT":"",
"APPROVAL_SYSTEM_APP_MODULE_ORGACCESS":"",
"APPROVAL_SYSTEM_APP_MODULE_PREMIUM_BUDGET_ALLOCATION":"",
"APPROVALREQUESTS_RETRY_FREQ":"",

"GH_AZURE_AD_GROUP":"",
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/setup-appservice-resource.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:
parameters.appServiceSettings.value.APPROVAL_SYSTEM_APP_MODULE_ORGANIZATION : ${{ vars.APPROVAL_SYSTEM_APP_MODULE_ORGANIZATION }}
parameters.appServiceSettings.value.APPROVAL_SYSTEM_APP_MODULE_COPILOT : ${{ vars.APPROVAL_SYSTEM_APP_MODULE_COPILOT }}
parameters.appServiceSettings.value.APPROVAL_SYSTEM_APP_MODULE_ORGACCESS : ${{ vars.APPROVAL_SYSTEM_APP_MODULE_ORGACCESS }}
parameters.appServiceSettings.value.APPROVAL_SYSTEM_APP_MODULE_PREMIUM_BUDGET_ALLOCATION : ${{ vars.APPROVAL_SYSTEM_APP_MODULE_PREMIUM_BUDGET_ALLOCATION }}
parameters.appServiceSettings.value.APPROVALREQUESTS_RETRY_FREQ: ${{ vars.APPROVALREQUESTS_RETRY_FREQ }}
parameters.appServiceSettings.value.GH_AZURE_AD_GROUP : ${{ vars.GH_AZURE_AD_GROUP }}
parameters.appServiceSettings.value.GH_AZURE_AD_ADMIN_GROUP : ${{ vars.GH_AZURE_AD_ADMIN_GROUP }}
Expand Down
1 change: 1 addition & 0 deletions src/goapp/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ APPROVAL_SYSTEM_APP_MODULE_COMMUNITY=
APPROVAL_SYSTEM_APP_MODULE_ORGANIZATION=
APPROVAL_SYSTEM_APP_MODULE_COPILOT=
APPROVAL_SYSTEM_APP_MODULE_ORGACCESS=
APPROVAL_SYSTEM_APP_MODULE_PREMIUM_BUDGET_ALLOCATION=
APPROVALREQUESTS_RETRY_FREQ=<In Minutes. Defaults to 15>
GH_AZURE_AD_GROUP=<AZURE AD GROUP ID>
GH_AZURE_AD_ADMIN_GROUP=<AZURE AD GROUP FOR COMMUNITY ADMINS>
Expand Down
Binary file added src/goapp/__debug_bin1553489815
Binary file not shown.
Binary file added src/goapp/__debug_bin571931451
Binary file not shown.
1 change: 1 addition & 0 deletions src/goapp/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func checkFailedApprovalRequests() {
rtApi.ReprocessCommunityApprovalRequestOrganizationAccess()
rtApi.ReprocessCommunityApprovalRequestGitHubCoPilots()
rtApi.ReprocessCommunityApprovalRequestNewOrganizations()
rtApi.ReprocessCommunityApprovalRequestGHCPPremiumBudgetAllocation()
}
}
}
208 changes: 208 additions & 0 deletions src/goapp/pkg/ghmgmtdb/ghcpPremiumBudgetAllocation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
package ghmgmt

import (
"fmt"
"strconv"
"strings"
"time"
)

type InsertGHCPPremiumBudgetAllocationInput struct {
OrganizationGitHubId int64
OrganizationGitHubLogin string
UserGitHubId int64
UserGitHubLogin string
Amount int64
CreatedBy string
}

type InsertGHCPPremiumBudgetAllocationApprovalRequestInput struct {
GHCPPremiumBudgetAllocationID int64
ApprovalRequestId int64
}

func InsertGHCPPremiumBudgetAllocation(input InsertGHCPPremiumBudgetAllocationInput) (id int64, err error) {
db := ConnectDb()
defer db.Close()

param := map[string]interface{}{
"OrganizationGitHubID": input.OrganizationGitHubId,
"OrganizationGitHubLogin": input.OrganizationGitHubLogin,
"UserGitHubID": input.UserGitHubId,
"UserGitHubLogin": input.UserGitHubLogin,
"Amount": input.Amount,
"CreatedBy": input.CreatedBy,
}

result, err := db.ExecuteStoredProcedureWithResult("usp_GHCPPremiumBudgetAllocation_Insert", param)
if err != nil {
return 0, err
}

id, err = strconv.ParseInt(fmt.Sprint(result[0]["Id"]), 10, 64)
if err != nil {
return 0, err
}

return id, nil
}

func InsertGHCPPremiumBudgetAllocationApprovalRequest(input InsertGHCPPremiumBudgetAllocationApprovalRequestInput) error {
db := ConnectDb()
defer db.Close()

param := map[string]interface{}{
"GHCPPremiumBudgetAllocationId": input.GHCPPremiumBudgetAllocationID,
"ApprovalRequestId": input.ApprovalRequestId,
}

_, err := db.ExecuteStoredProcedureWithResult("usp_GHCPPremiumBudgetAllocationApprovalRequest_Insert", param)
if err != nil {
return err
}

return nil
}

type GHCPPremiumBudgetAllocation struct {
Id int64
OrganizationGitHubID int64
OrganizationGitHubLogin string
UserGitHubID int64
UserGitHubLogin string
Amount int64
Created time.Time
CreatedBy string
}

func GetGHCPPremiumBudgetAllocationRequestByUsername(username string) (ghcpPremiuBudgetAllocationRequests []GHCPPremiumBudgetAllocation, err error) {
db := ConnectDb()
defer db.Close()

param := map[string]interface{}{
"Username": username,
}

result, err := db.ExecuteStoredProcedureWithResult("usp_GHCPPremiumBudgetAllocation_Select_ByUsername", param)
if err != nil {
return nil, err
}

for _, v := range result {
ghcpPremiuBudgetAllocationRequests = append(ghcpPremiuBudgetAllocationRequests, GHCPPremiumBudgetAllocation{
Id: v["Id"].(int64),
OrganizationGitHubID: v["OrganizationGitHubID"].(int64),
OrganizationGitHubLogin: v["OrganizationGitHubLogin"].(string),
UserGitHubID: v["UserGitHubID"].(int64),
UserGitHubLogin: v["UserGitHubLogin"].(string),
Amount: v["Amount"].(int64),
Created: v["Created"].(time.Time),
CreatedBy: v["CreatedBy"].(string),
})
}

return ghcpPremiuBudgetAllocationRequests, nil
}

type GHCPPremiumBudgetAllocationApprovalRequest struct {
Id int64
Approver string
Status string
Remarks *string
ResponseDate *time.Time
Description *string
}

func GetGHCPPremiumBudgetAllocationApprovalRequest(id int64) (ghcpPremiumBudgetAllocationApprovalRequest []GHCPPremiumBudgetAllocationApprovalRequest, err error) {
db := ConnectDb()
defer db.Close()

param := map[string]interface{}{
"GHCPPremiumBudgetAllocationId": id,
}

result, err := db.ExecuteStoredProcedureWithResult("usp_GHCPPremiumBudgetAllocationApprovalRequest_Select_ByGHCPPremiumBudgetAllocationId", param)
if err != nil {
return nil, err
}

for _, v := range result {
var remarks *string
if v["ApprovalRemarks"] != nil {
remarksValue := v["ApprovalRemarks"].(string)
remarks = &remarksValue
}

var responseDate *time.Time
if v["ApprovalDate"] != nil {
responseDateValue := v["ApprovalDate"].(time.Time)
responseDate = &responseDateValue
}

var description *string
if v["ApprovalDescription"] != nil {
descriptionValue := v["ApprovalDescription"].(string)
description = &descriptionValue
}

ghcpPremiumBudgetAllocationApprovalRequest = append(ghcpPremiumBudgetAllocationApprovalRequest, GHCPPremiumBudgetAllocationApprovalRequest{
Id: v["Id"].(int64),
Approver: v["ApproverUserPrincipalName"].(string),
Status: v["ApprovalStatus"].(string),
Remarks: remarks,
ResponseDate: responseDate,
Description: description,
})
}

return ghcpPremiumBudgetAllocationApprovalRequest, nil
}

type FailedCommunityApprovalRequestGHCPPremiumBudgetAllocation struct {
GHCPPremiumBudgetAllocation
Approvers []string
RequestIds []int64
}

func GetFailedCommunityApprovalRequestGHCPPremiumBudgetAllocation() (failedCommunityApprovalRequestGHCPPremiumBudgetAllocations []FailedCommunityApprovalRequestGHCPPremiumBudgetAllocation) {
db := ConnectDb()
defer db.Close()

result, _ := db.ExecuteStoredProcedureWithResult("usp_ApprovalRequest_Select_FailedRequestGHCPPremiumBudgetAllocation", nil)

for _, v := range result {
failedCommunityApprovalRequestGHCPPremiumBudgetAllocation := FailedCommunityApprovalRequestGHCPPremiumBudgetAllocation{
GHCPPremiumBudgetAllocation: GHCPPremiumBudgetAllocation{
Id: v["Id"].(int64),
OrganizationGitHubID: v["OrganizationGitHubId"].(int64),
OrganizationGitHubLogin: v["OrganizationGitHubLogin"].(string),
UserGitHubID: v["UserGitHubId"].(int64),
UserGitHubLogin: v["UserGitHubLogin"].(string),
Amount: v["Amount"].(int64),
Created: v["Requested"].(time.Time),
CreatedBy: v["RequestedBy"].(string),
},
}
if v["Approvers"] != nil {
approversStr := v["Approvers"].(string)
failedCommunityApprovalRequestGHCPPremiumBudgetAllocation.Approvers = strings.Split(approversStr, ",")
}

if v["RequestIds"] != nil {
requestIdsStr := v["RequestIds"].(string)
requestIds := strings.Split(requestIdsStr, ",")

for _, v := range requestIds {
requestId, err := strconv.ParseInt(v, 0, 64)
if err != nil {
continue
}
failedCommunityApprovalRequestGHCPPremiumBudgetAllocation.RequestIds = append(failedCommunityApprovalRequestGHCPPremiumBudgetAllocation.RequestIds, int64(requestId))
}
}

failedCommunityApprovalRequestGHCPPremiumBudgetAllocations = append(failedCommunityApprovalRequestGHCPPremiumBudgetAllocations, failedCommunityApprovalRequestGHCPPremiumBudgetAllocation)
}

return failedCommunityApprovalRequestGHCPPremiumBudgetAllocations
}
68 changes: 68 additions & 0 deletions src/goapp/pkg/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,47 @@ func GetOrganizationsWithinEnterprise(enterprise string, token string) (*GetOrga
return &result, nil
}

func GetUserOwnedEnterpriseOrganizations(token string, enterprise string, memberLogin string, organizationQuery string) (*GetUserOwnedEnterpriseOrganizationsResult, error) {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
httpClient := oauth2.NewClient(context.Background(), src)

client := githubv4.NewClient(httpClient)

var result GetUserOwnedEnterpriseOrganizationsResult
var cursor *githubv4.String

for {
var queryResult GetUserOwnedEnterpriseOrganizationsQuery
variables := map[string]interface{}{
"enterprise": githubv4.String(enterprise),
"memberLogin": githubv4.String(memberLogin),
"organizationQuery": githubv4.String(organizationQuery),
"cursor": cursor,
}
err := client.Query(context.Background(), &queryResult, variables)
if err != nil {
return nil, err
}

for _, org := range queryResult.Enterprise.Members.Nodes[0].EnterpriseUserAccount.Organizations.Edges {
result.Organizations = append(result.Organizations, Organization{
Login: string(org.Node.Login),
DatabaseId: int64(org.Node.DatabaseId),
})
}

if !queryResult.Enterprise.Members.Nodes[0].EnterpriseUserAccount.Organizations.PageInfo.HasNextPage {
break
}

cursor = &queryResult.Enterprise.Members.Nodes[0].EnterpriseUserAccount.Organizations.PageInfo.EndCursor
}

return &result, nil
}

type customTransport struct {
Transport http.RoundTripper
}
Expand Down Expand Up @@ -862,6 +903,29 @@ type GetOrganizationsWithinEnterpriseQuery struct {
} `graphql:"enterprise(slug: $enterprise)"`
}

type GetUserOwnedEnterpriseOrganizationsQuery struct {
Enterprise struct {
Members struct {
Nodes []struct {
EnterpriseUserAccount struct {
Organizations struct {
Edges []struct {
Node struct {
DatabaseId githubv4.Int
Login githubv4.String
}
}
PageInfo struct {
HasNextPage bool
EndCursor githubv4.String
}
} `graphql:"organizations(first: 100, after: $cursor, role: OWNER, query: $organizationQuery)"`
} `graphql:"... on EnterpriseUserAccount"`
}
} `graphql:"members(first: 100, query: $memberLogin)"`
} `graphql:"enterprise(slug: $enterprise)"`
}

type GetMembersByEnterpriseQuery struct {
Enterprise struct {
OwnerInfo struct {
Expand Down Expand Up @@ -936,6 +1000,10 @@ type GetOrganizationsByGithubNameResult struct {
Organizations []Organization
}

type GetUserOwnedEnterpriseOrganizationsResult struct {
Organizations []Organization
}

type GetOrganizationsWithinEnterpriseResult struct {
Organizations []Organization
}
Expand Down
Loading