forked from baron/baron-sso
Update dev workflow and org chart settings
This commit is contained in:
@@ -331,8 +331,10 @@ func main() {
|
||||
ServiceAccount: getEnv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT", ""),
|
||||
PrivateKey: worksmobilePrivateKey,
|
||||
Scope: getEnv("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
TokenURL: getEnv("WORKS_ADMIN_OAUTH_TOKEN_URL", ""),
|
||||
},
|
||||
)
|
||||
configureWorksmobileClientFromEnv(worksmobileClient)
|
||||
worksmobileService := service.NewWorksmobileSyncService(tenantService, userRepo, worksmobileOutboxRepo, worksmobileClient)
|
||||
worksmobileRelayWorker := service.NewWorksmobileRelayWorker(worksmobileOutboxRepo, worksmobileClient)
|
||||
go worksmobileRelayWorker.Start(context.Background())
|
||||
@@ -898,3 +900,10 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func configureWorksmobileClientFromEnv(client *service.WorksmobileHTTPClient) {
|
||||
if client == nil {
|
||||
return
|
||||
}
|
||||
client.BaseURL = strings.TrimSpace(getEnv("WORKS_ADMIN_API_BASE_URL", ""))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"baron-sso-backend/internal/service"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
@@ -37,3 +38,14 @@ func TestGetEnvFileOrValueFallsBackToRawEnv(t *testing.T) {
|
||||
t.Fatalf("secret value = %q, want raw env value", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigureWorksmobileClientFromEnvOverridesAPIBaseURL(t *testing.T) {
|
||||
t.Setenv("WORKS_ADMIN_API_BASE_URL", "https://proxy.example.com/works")
|
||||
client := service.NewWorksmobileHTTPClientWithTokens("", "")
|
||||
|
||||
configureWorksmobileClientFromEnv(client)
|
||||
|
||||
if client.BaseURL != "https://proxy.example.com/works" {
|
||||
t.Fatalf("BaseURL = %q, want env override", client.BaseURL)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultWorksmobileAPIBaseURL = "https://www.worksapis.com"
|
||||
defaultWorksmobileOAuthTokenURL = "https://auth.worksmobile.com/oauth2/v2.0/token"
|
||||
defaultWorksmobileOAuthScope = "directory"
|
||||
defaultWorksmobileOAuthScope = "directory"
|
||||
)
|
||||
|
||||
type WorksmobileDirectoryClient interface {
|
||||
@@ -74,9 +72,6 @@ func (c WorksmobileOAuthConfig) normalized() WorksmobileOAuthConfig {
|
||||
c.Scope = defaultWorksmobileOAuthScope
|
||||
}
|
||||
c.TokenURL = strings.TrimSpace(c.TokenURL)
|
||||
if c.TokenURL == "" {
|
||||
c.TokenURL = defaultWorksmobileOAuthTokenURL
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -87,6 +82,9 @@ func (c WorksmobileOAuthConfig) validate() error {
|
||||
if strings.TrimSpace(c.ServiceAccount) == "" || strings.TrimSpace(c.PrivateKey) == "" {
|
||||
return fmt.Errorf("worksmobile oauth service account is not configured")
|
||||
}
|
||||
if strings.TrimSpace(c.TokenURL) == "" {
|
||||
return fmt.Errorf("worksmobile oauth token url is not configured")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -163,14 +161,12 @@ func (e WorksmobileHTTPError) Error() string {
|
||||
|
||||
func NewWorksmobileHTTPClient(scimToken string) *WorksmobileHTTPClient {
|
||||
return &WorksmobileHTTPClient{
|
||||
BaseURL: defaultWorksmobileAPIBaseURL,
|
||||
SCIMToken: strings.Trim(strings.TrimSpace(scimToken), `"`),
|
||||
}
|
||||
}
|
||||
|
||||
func NewWorksmobileHTTPClientWithTokens(directoryToken string, scimToken string) *WorksmobileHTTPClient {
|
||||
return &WorksmobileHTTPClient{
|
||||
BaseURL: defaultWorksmobileAPIBaseURL,
|
||||
DirectoryToken: strings.Trim(strings.TrimSpace(directoryToken), `"`),
|
||||
SCIMToken: strings.Trim(strings.TrimSpace(scimToken), `"`),
|
||||
}
|
||||
@@ -178,7 +174,6 @@ func NewWorksmobileHTTPClientWithTokens(directoryToken string, scimToken string)
|
||||
|
||||
func NewWorksmobileHTTPClientWithAuth(directoryToken string, scimToken string, oauthConfig WorksmobileOAuthConfig) *WorksmobileHTTPClient {
|
||||
return &WorksmobileHTTPClient{
|
||||
BaseURL: defaultWorksmobileAPIBaseURL,
|
||||
DirectoryToken: strings.Trim(strings.TrimSpace(directoryToken), `"`),
|
||||
SCIMToken: strings.Trim(strings.TrimSpace(scimToken), `"`),
|
||||
OAuthConfig: oauthConfig.normalized(),
|
||||
@@ -437,7 +432,11 @@ func (c *WorksmobileHTTPClient) getJSON(ctx context.Context, path string, target
|
||||
if token == "" {
|
||||
return fmt.Errorf("worksmobile read token is not configured")
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.TrimRight(c.baseURL(), "/")+path, nil)
|
||||
requestURL, err := c.requestURL(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -461,7 +460,11 @@ func (c *WorksmobileHTTPClient) getDirectoryJSON(ctx context.Context, path strin
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.TrimRight(c.baseURL(), "/")+path, nil)
|
||||
requestURL, err := c.requestURL(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -672,7 +675,11 @@ func (c *WorksmobileHTTPClient) sendJSONWithToken(ctx context.Context, method st
|
||||
body = bytes.NewReader(data)
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, strings.TrimRight(c.baseURL(), "/")+path, body)
|
||||
requestURL, err := c.requestURL(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, method, requestURL, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1117,12 +1124,17 @@ func boolPointerFromMap(values map[string]any, keys ...string) *bool {
|
||||
}
|
||||
|
||||
func (c *WorksmobileHTTPClient) baseURL() string {
|
||||
if strings.TrimSpace(c.BaseURL) == "" {
|
||||
return defaultWorksmobileAPIBaseURL
|
||||
}
|
||||
return c.BaseURL
|
||||
}
|
||||
|
||||
func (c *WorksmobileHTTPClient) requestURL(path string) (string, error) {
|
||||
baseURL := strings.TrimSpace(c.baseURL())
|
||||
if baseURL == "" {
|
||||
return "", fmt.Errorf("worksmobile api base url is not configured")
|
||||
}
|
||||
return strings.TrimRight(baseURL, "/") + path, nil
|
||||
}
|
||||
|
||||
func (c *WorksmobileHTTPClient) httpClient() *http.Client {
|
||||
if c.HTTPClient != nil {
|
||||
return c.HTTPClient
|
||||
|
||||
@@ -181,6 +181,46 @@ func TestWorksmobileHTTPClientRequestsJWTBearerAccessToken(t *testing.T) {
|
||||
require.Equal(t, float64(1710003600), payload["exp"])
|
||||
}
|
||||
|
||||
func TestWorksmobileHTTPClientRequiresConfiguredAPIBaseURL(t *testing.T) {
|
||||
client := &WorksmobileHTTPClient{
|
||||
DirectoryToken: "directory-token-1",
|
||||
HTTPClient: &http.Client{Transport: &captureRoundTripper{statusCode: http.StatusCreated, body: `{}`}},
|
||||
}
|
||||
|
||||
err := client.CreateUser(context.Background(), WorksmobileUserPayload{
|
||||
DomainID: 300285955,
|
||||
Email: "tester@samaneng.com",
|
||||
UserExternalKey: "user-1",
|
||||
UserName: WorksmobileUserName{LastName: "Tester"},
|
||||
PasswordConfig: WorksmobilePasswordConfig{PasswordCreationType: "ADMIN", Password: "Aa1!Aa1!Aa1!Aa1!"},
|
||||
})
|
||||
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "worksmobile api base url is not configured")
|
||||
}
|
||||
|
||||
func TestWorksmobileHTTPClientRequiresConfiguredOAuthTokenURL(t *testing.T) {
|
||||
privateKey := testRSAPrivateKeyPEM(t)
|
||||
client := &WorksmobileHTTPClient{
|
||||
BaseURL: "https://works.example.test",
|
||||
OAuthConfig: WorksmobileOAuthConfig{
|
||||
ClientID: "client-id-1",
|
||||
ClientSecret: "client-secret-1",
|
||||
ServiceAccount: "service-account-1",
|
||||
PrivateKey: privateKey,
|
||||
Scope: "directory",
|
||||
},
|
||||
}
|
||||
|
||||
_, _, err := client.requestDirectoryAccessToken(
|
||||
context.Background(),
|
||||
time.Unix(1710000000, 0),
|
||||
)
|
||||
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "worksmobile oauth token url is not configured")
|
||||
}
|
||||
|
||||
func TestWorksmobileHTTPClientListUsersUsesDirectoryAPIFirst(t *testing.T) {
|
||||
t.Setenv("SAMAN_DOMAIN_ID", "300285955")
|
||||
transport := &captureRoundTripper{
|
||||
@@ -393,13 +433,7 @@ func TestWorksmobileLiveJWTTokenExchange(t *testing.T) {
|
||||
if os.Getenv("WORKSMOBILE_LIVE_JWT_TOKEN_EXCHANGE") != "1" {
|
||||
t.Skip("live Worksmobile token exchange is disabled")
|
||||
}
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
|
||||
token, err := client.directoryAccessToken(context.Background())
|
||||
|
||||
@@ -989,6 +1023,19 @@ func getenvDefault(key string, fallback string) string {
|
||||
return fallback
|
||||
}
|
||||
|
||||
func newWorksmobileLiveClient() *WorksmobileHTTPClient {
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
TokenURL: os.Getenv("WORKS_ADMIN_OAUTH_TOKEN_URL"),
|
||||
})
|
||||
client.BaseURL = os.Getenv("WORKS_ADMIN_API_BASE_URL")
|
||||
return client
|
||||
}
|
||||
|
||||
func (f *fakeWorksmobileDirectoryClient) CreateOrgUnit(ctx context.Context, payload WorksmobileOrgUnitPayload) error {
|
||||
f.createdOrgUnits = append(f.createdOrgUnits, payload)
|
||||
return nil
|
||||
|
||||
@@ -33,13 +33,7 @@ func TestWorksmobileLiveSamanUsersDirectoryProvisioning(t *testing.T) {
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
outboxRepo := repository.NewWorksmobileOutboxRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
syncService := NewWorksmobileSyncService(tenantService, userRepo, outboxRepo, client)
|
||||
worker := NewWorksmobileRelayWorker(outboxRepo, client)
|
||||
|
||||
@@ -145,13 +139,7 @@ func TestWorksmobileLiveSyncHanmacFamilyOrgUnits(t *testing.T) {
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
|
||||
root, err := tenantService.GetTenantBySlug(ctx, HanmacFamilyTenantSlug)
|
||||
require.NoError(t, err)
|
||||
@@ -239,13 +227,7 @@ func TestWorksmobileLiveInspectGPDTDCOrgUnits(t *testing.T) {
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
|
||||
gpdtdcTenant, err := tenantService.GetTenantBySlug(ctx, "gpdtdc")
|
||||
require.NoError(t, err)
|
||||
@@ -322,13 +304,7 @@ func TestWorksmobileLiveRecoverGPDTDCOrgUnits(t *testing.T) {
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
|
||||
gpdtdcTenant, err := tenantService.GetTenantBySlug(ctx, "gpdtdc")
|
||||
require.NoError(t, err)
|
||||
@@ -502,13 +478,7 @@ func runWorksmobileLiveCompanyOrgUnitProvisioning(t *testing.T, companySlug stri
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
|
||||
companyTenant, err := tenantService.GetTenantBySlug(ctx, companySlug)
|
||||
require.NoError(t, err)
|
||||
@@ -565,13 +535,7 @@ func runWorksmobileLiveBaronGroupOrgUnitProvisioning(t *testing.T) {
|
||||
userRepo := repository.NewUserRepository(db)
|
||||
userGroupRepo := repository.NewUserGroupRepository(db)
|
||||
tenantService := NewTenantService(tenantRepo, userRepo, userGroupRepo, nil)
|
||||
client := NewWorksmobileHTTPClientWithAuth("", os.Getenv("SAMAN_SCIM_LONGLIVE_TOKEN"), WorksmobileOAuthConfig{
|
||||
ClientID: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_ID"),
|
||||
ClientSecret: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SECRET"),
|
||||
ServiceAccount: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_SERVICE_ACCOUNT"),
|
||||
PrivateKey: os.Getenv("WORKS_ADMIN_OAUTH_CLIENT_PRIVATE_KEY"),
|
||||
Scope: getenvDefault("WORKS_ADMIN_OAUTH_SCOPE", "directory"),
|
||||
})
|
||||
client := newWorksmobileLiveClient()
|
||||
|
||||
baronGroup, err := tenantService.GetTenantBySlug(ctx, "baron-group")
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user