Skip to content

Commit

Permalink
Merge pull request #3120 from gravitl/ACC-638
Browse files Browse the repository at this point in the history
ACC-638: SaaS user mgmt compatibility changes
  • Loading branch information
abhishek9686 committed Sep 11, 2024
2 parents e3c3a27 + 4d56a7e commit ddfd1e8
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 35 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/branchtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ name: Deploy and Test Branch

on:
workflow_dispatch:
inputs:
branches:
description: 'Branch to deploy and test'
required: true
default: 'develop'
pull_request:
types: [opened, synchronize, reopened]
branches: [develop]
Expand All @@ -28,7 +33,7 @@ jobs:
uses: actions/checkout@v4
with:
repository: gravitl/netclient
ref: develop
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || 'develop' }}
- name: check if branch exists
id: getbranch
run: |
Expand All @@ -45,6 +50,6 @@ jobs:
needs: [getbranch, skip-check]
with:
netclientbranch: ${{ needs.getbranch.outputs.netclientbranch }}
netmakerbranch: ${{ github.head_ref }}
netmakerbranch: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.head_ref }}
tag: ${{ github.run_id }}-${{ github.run_attempt }}
secrets: inherit
28 changes: 22 additions & 6 deletions .github/workflows/deletedroplets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
- name: delete droplets
if: success() || failure()
run: |
sleep 5m
sleep 1m
response=$(curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
Expand All @@ -56,8 +56,9 @@ jobs:
echo "Failed to delete droplets. Status code: $status_code"
exit 1
fi
sleep 1m
env:
DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}
DIGITALOCEAN_TOKEN: ${{ secrets.DO_TEST_TOKEN }}
TAG: ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}
- name: mark server as available
if: success() || failure()
Expand Down Expand Up @@ -108,13 +109,28 @@ jobs:
- name: delete droplets
if: success() || failure()
run: |
sleep 3h
curl -X DELETE \
sleep 1m
response=$(curl -X DELETE \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DIGITALOCEAN_TOKEN" \
"https://api.digitalocean.com/v2/droplets?tag_name=$TAG"
-w "\n%{http_code}" \
"https://api.digitalocean.com/v2/droplets?tag_name=$TAG")
status_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
echo "Response body: $body"
echo "Status code: $status_code"
if [ "$status_code" -eq 204 ]; then
echo "Droplets deleted successfully"
else
echo "Failed to delete droplets. Status code: $status_code"
exit 1
fi
sleep 1m
env:
DIGITALOCEAN_TOKEN: ${{ secrets.DIGITALOCEAN_TOKEN }}
DIGITALOCEAN_TOKEN: ${{ secrets.DO_TEST_TOKEN }}
TAG: ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }}
- name: mark server as available
if: success() || failure()
Expand Down
12 changes: 12 additions & 0 deletions pro/controllers/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ func inviteUsers(w http.ResponseWriter, r *http.Request) {
}
for _, inviteeEmail := range inviteReq.UserEmails {
// check if user with email exists, then ignore
if !email.IsValid(inviteeEmail) {
logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("invalid email "+inviteeEmail), "badrequest"))
return
}
_, err := logic.GetUser(inviteeEmail)
if err == nil {
// user exists already, so ignore
Expand All @@ -228,6 +232,14 @@ func inviteUsers(w http.ResponseWriter, r *http.Request) {
slog.Error("failed to parse to invite url", "error", err)
return
}
if servercfg.DeployedByOperator() {
u, err = url.Parse(fmt.Sprintf("%s/invite?tenant_id=%s&email=%s&invite_code=%s",
proLogic.GetAccountsUIHost(), url.QueryEscape(servercfg.GetNetmakerTenantID()), url.QueryEscape(invite.Email), url.QueryEscape(invite.InviteCode)))
if err != nil {
slog.Error("failed to parse to invite url", "error", err)
return
}
}
invite.InviteURL = u.String()
err = logic.InsertUserInvite(invite)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions pro/email/email.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package email

import (
"context"
"regexp"

"github.com/gravitl/netmaker/servercfg"
)
Expand Down Expand Up @@ -52,3 +53,8 @@ type Notification struct {
func GetClient() (e EmailSender) {
return client
}

func IsValid(email string) bool {
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`)
return emailRegex.MatchString(email)
}
14 changes: 2 additions & 12 deletions pro/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/netclient/ncutils"
proLogic "github.com/gravitl/netmaker/pro/logic"
"github.com/gravitl/netmaker/servercfg"
)

Expand Down Expand Up @@ -206,7 +207,7 @@ func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, bool

req, err := http.NewRequest(
http.MethodPost,
getAccountsHost()+"/api/v1/license/validate",
proLogic.GetAccountsHost()+"/api/v1/license/validate",
bytes.NewReader(requestBody),
)
if err != nil {
Expand Down Expand Up @@ -255,17 +256,6 @@ func validateLicenseKey(encryptedData []byte, publicKey *[32]byte) ([]byte, bool
return nil, false, err
}

func getAccountsHost() string {
switch servercfg.GetEnvironment() {
case "dev":
return accountsHostDevelopment
case "staging":
return accountsHostStaging
default:
return accountsHostProduction
}
}

func cacheResponse(response []byte) error {
lrc := licenseResponseCache{
Body: response,
Expand Down
10 changes: 6 additions & 4 deletions pro/license_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
package pro

import (
"github.com/gravitl/netmaker/config"
"testing"

"github.com/gravitl/netmaker/config"
proLogic "github.com/gravitl/netmaker/pro/logic"
)

func Test_getAccountsHost(t *testing.T) {
func Test_GetAccountsHost(t *testing.T) {
tests := []struct {
name string
envK string
Expand Down Expand Up @@ -69,8 +71,8 @@ func Test_getAccountsHost(t *testing.T) {
if tt.envK != "" {
t.Setenv(tt.envK, tt.envV)
}
if got := getAccountsHost(); got != tt.want {
t.Errorf("getAccountsHost() = %v, want %v", got, tt.want)
if got := proLogic.GetAccountsHost(); got != tt.want {
t.Errorf("GetAccountsHost() = %v, want %v", got, tt.want)
}
})
}
Expand Down
43 changes: 43 additions & 0 deletions pro/logic/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ import (

"github.com/gravitl/netmaker/logic"
"github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/servercfg"
)

// constants for accounts api hosts
const (
// accountsHostDevelopment is the accounts api host for development environment
accountsHostDevelopment = "https://api.dev.accounts.netmaker.io"
// accountsHostStaging is the accounts api host for staging environment
accountsHostStaging = "https://api.staging.accounts.netmaker.io"
// accountsHostProduction is the accounts api host for production environment
accountsHostProduction = "https://api.accounts.netmaker.io"
)

// constants for accounts UI hosts
const (
// accountsUIHostDevelopment is the accounts UI host for development environment
accountsUIHostDevelopment = "https://account.dev.netmaker.io"
// accountsUIHostStaging is the accounts UI host for staging environment
accountsUIHostStaging = "https://account.staging.netmaker.io"
// accountsUIHostProduction is the accounts UI host for production environment
accountsUIHostProduction = "https://account.netmaker.io"
)

func NetworkPermissionsCheck(username string, r *http.Request) error {
Expand Down Expand Up @@ -186,3 +207,25 @@ func checkPermissionScopeWithReqMethod(scope models.RsrcPermissionScope, reqmeth
}
return errors.New("operation not permitted")
}

func GetAccountsHost() string {
switch servercfg.GetEnvironment() {
case "dev":
return accountsHostDevelopment
case "staging":
return accountsHostStaging
default:
return accountsHostProduction
}
}

func GetAccountsUIHost() string {
switch servercfg.GetEnvironment() {
case "dev":
return accountsUIHostDevelopment
case "staging":
return accountsUIHostStaging
default:
return accountsUIHostProduction
}
}
1 change: 0 additions & 1 deletion pro/logic/user_mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ func DeleteRole(rid models.UserRoleID, force bool) error {
}
}
}

return database.DeleteRecord(database.USER_PERMISSIONS_TABLE_NAME, rid.String())
}

Expand Down
10 changes: 0 additions & 10 deletions pro/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,6 @@ import (
"fmt"
)

// constants for accounts api hosts
const (
// accountsHostDevelopment is the accounts api host for development environment
accountsHostDevelopment = "https://api.dev.accounts.netmaker.io"
// accountsHostStaging is the accounts api host for staging environment
accountsHostStaging = "https://api.staging.accounts.netmaker.io"
// accountsHostProduction is the accounts api host for production environment
accountsHostProduction = "https://api.accounts.netmaker.io"
)

const (
license_cache_key = "license_response_cache"
license_validation_err_msg = "invalid license"
Expand Down

0 comments on commit ddfd1e8

Please sign in to comment.