Skip to content

Commit 166bfff

Browse files
authored
Merge pull request #27 from britive/develop
v0.5.0
2 parents aaaf92f + 3085192 commit 166bfff

File tree

9 files changed

+49
-31
lines changed

9 files changed

+49
-31
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@
22

33
All changes to the package starting with v0.3.1 will be logged here.
44

5+
## v0.5.0 [2022-10-11]
6+
#### What's New
7+
* None
8+
9+
#### Enhancements
10+
* Allow for non `*.britive-app.com` tenants. Default to `britive-app.com` if no valid URL is provided (for backwards compatibility)
11+
12+
#### Bug Fixes
13+
* None
14+
15+
#### Dependencies
16+
* `britive~=2.10.0` from `britive~=2.9.0`
17+
18+
#### Other
19+
* None
20+
521
## v0.4.1 [2022-09-30]
622
#### What's New
723
* None

docs/index.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,15 @@ who may have access to an EA and GA tenant.
4848

4949
## Tenant Selection Logic
5050

51+
Given the URL `https://example.britive-app.com` used to access your Britive tenant, tenant value can be provided in a number of formats.
52+
53+
1. `example`
54+
2. `example.britive-app.com`
55+
3. `https://example.britive-app.com`
56+
5157
There are numerous ways to provide the CLI with the Britive tenant that should be used. The below list is the
5258
order of operations for determining the tenant.
5359

54-
The tenant excludes `.britive-app.com`. Just include the leftmost part.
55-
Example: `example.britive-app.com` will have a tenant name in the CLI of `example`.
56-
5760
1. Value retrieved from CLI option/flag `--tenant/-t`
5861
2. Value retrieved from environment variable `BRITIVE_TENANT`
5962
3. Value retrieved from `~/.britive/pybritive.config` global variable `default_tenant`

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
britive~=2.9.0
1+
britive~=2.10.0
22
certifi==2022.6.15
33
charset-normalizer==2.1.0
44
click==8.1.3

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = pybritive
3-
version = 0.4.1
3+
version = 0.5.0
44
author = Britive Inc.
55
author_email = support@britive.com
66
description = A pure Python CLI for Britive

src/pybritive/britive_cli.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import io
2-
import time
3-
2+
import socket
43
from britive.britive import Britive
54
from .helpers.config import ConfigManager
65
from .helpers.credentials import FileCredentialManager, EncryptedFileCredentialManager
@@ -36,6 +35,22 @@ def __init__(self, tenant_name: str = None, token: str = None, silent: bool = Fa
3635
def set_output_format(self, output_format: str):
3736
self.output_format = self.config.get_output_format(output_format)
3837

38+
# it is preferable to do this in the sdk as a static method
39+
# as this will eliminate the duplicate code
40+
def parse_tenant(self):
41+
domain = self.tenant_name.replace('https://', '').replace('http://', '') # remove scheme
42+
domain = domain.split('/')[0] # remove any paths as they will not be needed
43+
try:
44+
socket.gethostbyname_ex(domain) # if success then a full domain was provided
45+
return domain
46+
except socket.gaierror: # assume just the tenant name was provided (originally the only supported method)
47+
domain = f'{self.tenant_name}.britive-app.com'
48+
try:
49+
socket.gethostbyname_ex(domain) # validate the hostname is real
50+
return domain
51+
except socket.gaierror:
52+
raise Exception(f'Invalid tenant provided: {self.tenant_name}')
53+
3954
def set_credential_manager(self):
4055
if self.credential_manager:
4156
return
@@ -97,7 +112,7 @@ def logout(self):
97112
if self.token:
98113
raise click.ClickException('Logout not available when using an API token.')
99114
self.login()
100-
self.b.delete(f'https://{self.tenant_name}.britive-app.com/api/auth')
115+
self.b.delete(f'https://{self.parse_tenant()}/api/auth')
101116
self._cleanup_credentials()
102117

103118
# will take a list of dicts and print to the screen based on the format specified in the config file

src/pybritive/commands/configure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def tenant(ctx, configure_tenant, configure_alias, output_format, configure_prom
4242
type=output_format_choices
4343
)
4444

45-
if not tenant_name or len(tenant_name.strip()) == 0:
45+
if not tenant_name or len(tenant_name.strip()) == 0:
4646
raise click.ClickException('Tenant Name not provided.')
4747
if not alias:
4848
alias = tenant_name

src/pybritive/helpers/config.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ def load(self, force=False):
9797
self.profile_aliases = self.config.get('profile-aliases', {})
9898
self.loaded = True
9999

100-
101100
def get_tenant(self):
102101
# load up the config - doing it here instead of __init__ for the configure commands since config won't
103102
# yet exist and we don't want to error
@@ -141,10 +140,7 @@ def save(self):
141140

142141
def save_tenant(self, tenant: str, alias: str = None, output_format: str = None):
143142
self.load()
144-
tenant = tenant.replace('.britive-app.com', '')
145-
if alias:
146-
alias = alias.replace('.britive-app.com', '')
147-
else:
143+
if not alias:
148144
alias = tenant
149145
if f'tenant-{alias}' not in self.config.keys():
150146
self.config[f'tenant-{alias}'] = {}
@@ -160,7 +156,7 @@ def save_global(self, default_tenant_name: str = None, output_format: str = None
160156
if 'global' not in self.config.keys():
161157
self.config['global'] = {}
162158
if default_tenant_name:
163-
self.config['global']['default_tenant'] = default_tenant_name.replace('.britive-app.com', '')
159+
self.config['global']['default_tenant'] = default_tenant_name
164160
if output_format:
165161
self.config['global']['output_format'] = output_format
166162
if backend:
@@ -266,10 +262,6 @@ def validate_tenant(self, section, fields):
266262
if field == 'output_format' and value not in output_format_choices.choices:
267263
error = f'Invalid {section} field {field} value {value} provided. Invalid value choice.'
268264
self.validation_error_messages.append(error)
269-
if field == 'name' and 'britive-app.com' in value:
270-
error = f'Invalid {section} field {field} value {value} provided. Tenant name cannot include ' \
271-
'britive-app.com'
272-
self.validation_error_messages.append(error)
273265

274266
def auto_refresh_profile_cache(self):
275267
self.load()

src/pybritive/helpers/credentials.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import click
99
import configparser
1010
import json
11-
from .config import ConfigManager
1211
import os
1312
from .encryption import StringEncryption, InvalidPassphraseException
1413

@@ -42,11 +41,11 @@ def b64_encode_url_safe(value: bytes):
4241

4342
# this base class expects self.credentials to be a dict - so sub classes need to convert to dict
4443
class CredentialManager:
45-
def __init__(self, tenant_name: str, tenant_alias: str, cli: ConfigManager):
44+
def __init__(self, tenant_name: str, tenant_alias: str, cli):
4645
self.cli = cli
4746
self.tenant = tenant_name
4847
self.alias = tenant_alias
49-
self.base_url = f'https://{self.tenant}.britive-app.com'
48+
self.base_url = f'https://{cli.parse_tenant()}'
5049

5150
# not sure if we really need 32 random bytes or if any random string would work
5251
# but the current britive-cli in node.js does it this way so it will be done the same
@@ -138,7 +137,7 @@ def has_valid_credentials(self):
138137

139138

140139
class FileCredentialManager(CredentialManager):
141-
def __init__(self, tenant_name: str, tenant_alias: str, cli: ConfigManager):
140+
def __init__(self, tenant_name: str, tenant_alias: str, cli):
142141
home = os.getenv('PYBRITIVE_HOME_DIR', str(Path.home()))
143142
self.path = str(Path(home) / '.britive' / 'pybritive.credentials')
144143
super().__init__(tenant_name, tenant_alias, cli)
@@ -179,7 +178,7 @@ def delete(self):
179178

180179

181180
class EncryptedFileCredentialManager(CredentialManager):
182-
def __init__(self, tenant_name: str, tenant_alias: str, cli: ConfigManager, passphrase: str = None):
181+
def __init__(self, tenant_name: str, tenant_alias: str, cli, passphrase: str = None):
183182
home = os.getenv('PYBRITIVE_HOME_DIR', str(Path.home()))
184183
self.path = str(Path(home) / '.britive' / 'pybritive.credentials.encrypted')
185184
self.passphrase = passphrase
Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
11
import click
22

33

4-
def validate_tenant(ctx, self, value):
5-
if value is None:
6-
return None
7-
return value.replace('.britive-app.com', '') # just in case
8-
9-
104
option = click.option(
115
'--tenant', '-t', 'configure_tenant',
12-
callback=validate_tenant,
136
default=None,
147
help='The name of the tenant: [tenant].britive-app.com.'
158
)

0 commit comments

Comments
 (0)