Skip to content
This repository was archived by the owner on Apr 16, 2023. It is now read-only.

Commit eb5145f

Browse files
authored
Merge pull request #1 from Genzer/feature/adapt-with-bitbucket-drop-using-username
Feature/adapt with bitbucket drop using username
2 parents 8ce7e4f + e0fb11b commit eb5145f

File tree

7 files changed

+101
-20
lines changed

7 files changed

+101
-20
lines changed

.env

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
# The user used here should be granted with
55
# enough permissions. See README.md OAuth
6-
BITBUCKET_USERNAME=
7-
BITBUCKET_PASSWORD=
6+
# BITBUCKET_USERNAME=
7+
# BITBUCKET_PASSWORD=
88

99
# If you don't have a dedicated BitBucket App, simply
1010
# create an OAuth2 Consumer in your BitBucket Settings.
11-
BITBUCKET_CLIENT_ID=
12-
BITBUCKET_CLIENT_SECRET=
11+
# BITBUCKET_CLIENT_ID=
12+
# BITBUCKET_CLIENT_SECRET=
1313

14-
BITBUCKET_TEAM=
14+
# BITBUCKET_TEAM=

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ bitbucklet groups list-user developers
7878

7979
# Add a user into the team
8080
# Here you can use both username or primary email address.
81-
bitbucklet users add [email protected]
81+
bitbucklet users invite [email protected]
8282

8383
```
8484

bitbucklet/groups_cli.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
from bitbucklet.token import get_access_token, BearerAuth
1010
from bitbucklet.urls import groups_url
1111

12+
import logging
13+
14+
logger = logging.getLogger("groups_cli")
15+
1216
@click.group(name='groups', help = 'Managing groups')
1317
def groups_cli():
1418
pass
@@ -71,6 +75,9 @@ def groups_del(group_name: str):
7175
@click.option('--verbose', is_flag=True, default=False, help="Print JSON output")
7276
@click.argument('group_name')
7377
def groups_list_user(verbose: bool, group_name: str):
78+
from tabulate import tabulate
79+
from itertools import count
80+
7481
bitbucket_team_name = os.getenv('BITBUCKET_TEAM')
7582

7683
access_token = get_access_token()
@@ -87,8 +94,11 @@ def groups_list_user(verbose: bool, group_name: str):
8794
return
8895

8996
members = response.json()
90-
[print(member['username']) for member in members]
9197

98+
table = [[member['display_name'], member['account_id'], member['uuid'], member['resource_uri']] for member in members ]
99+
headers = ['display_name', 'account_id', 'uuid', 'resource_uri']
100+
print(tabulate(table, headers=headers, showindex=range(1, len(table) + 1), tablefmt='github'))
101+
92102
@click.command(name='add-user', help = 'Add a user into a group')
93103
@click.argument('group_name')
94104
@click.argument('username')

bitbucklet/urls.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ def groups_url():
99
return 'https://api.bitbucket.org/1.0/groups/{team}'
1010

1111
def teams_url():
12-
return 'https://api.bitbucket.org/2.0/teams/{team}'
12+
return 'https://api.bitbucket.org/2.0/teams/{team}'
13+
14+
def team_invitations_url():
15+
return "https://api.bitbucket.org/1.0/users/{team}/invitations"

bitbucklet/users.py

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from requests import HTTPError
88

99
from bitbucklet.token import get_access_token, BearerAuth
10-
from bitbucklet.urls import teams_url
10+
from bitbucklet.urls import teams_url, team_invitations_url
1111
from bitbucklet.groups_cli import __group_add_user
1212

1313
@click.group(name='users', help = 'Managing users')
@@ -17,6 +17,8 @@ def users_cli():
1717
@click.command(name = 'list', help = 'List all the users (sort of)')
1818
@click.option('--verbose', is_flag=True, default=False)
1919
def list_users(verbose: bool):
20+
from tabulate import tabulate
21+
2022
bitbucket_team_name = os.getenv('BITBUCKET_TEAM')
2123

2224
access_token = get_access_token()
@@ -31,15 +33,77 @@ def list_users(verbose: bool):
3133
return
3234

3335
members = response.json()
34-
[print(member['username']) for member in members['values']]
36+
37+
table = [[member['display_name'], member['account_id'], member['uuid']] for member in members['values'] ]
38+
headers = ['display_name', 'account_id', 'uuid']
39+
print(tabulate(table, headers=headers, showindex=range(1, len(table) + 1), tablefmt='github'))
3540

36-
@click.command(name = 'add', help = 'Add an user')
37-
@click.argument('username')
38-
def add_user(username: str):
39-
# Normally, adding a user into any group making it a member of the Team.
40-
# By default, BitBucket creates two groups `administrators` and `developers`.
41-
# So obviously, adding a new user into `developers` makes sense here.
42-
__group_add_user('developers', username)
41+
@click.command(name = 'invite', help = 'Invite an user by their primary email')
42+
@click.argument('email')
43+
@click.argument('group', default='developers')
44+
def add_user(email: str, group: str):
45+
import json
46+
# Since June 2019, BitBucket changed their policy which a new user
47+
# can only be invited via their email address. Once they accept the
48+
# invitation email address, their username will be added into the team
49+
# `developers`.
50+
51+
bitbucket_team_name = os.getenv('BITBUCKET_TEAM')
52+
access_token = get_access_token()
53+
54+
response = requests.put(
55+
f"{team_invitations_url()}"
56+
.format(team=bitbucket_team_name),
57+
auth = BearerAuth(access_token),
58+
headers = {
59+
'Content-Type': 'application/json'
60+
},
61+
data = json.dumps({
62+
'email': email,
63+
'group_slug': group
64+
})
65+
)
66+
67+
print(response.text)
68+
69+
@click.command(name = 'list-pending', help = 'List unaccepted invitations')
70+
def list_pending_users():
71+
from tabulate import tabulate
72+
73+
bitbucket_team_name = os.getenv('BITBUCKET_TEAM')
74+
access_token = get_access_token()
75+
76+
response = requests.get(
77+
f"{team_invitations_url()}"
78+
.format(team=bitbucket_team_name),
79+
auth = BearerAuth(access_token)
80+
)
81+
82+
invitations = response.json()
83+
headers = ['email', 'invited_by', 'utc_sent_on']
84+
table = [[i['email'], i['invited_by']['display_name'], i['utc_sent_on']] for i in invitations]
85+
print(tabulate(table, headers=headers, showindex=range(1, len(table) + 1), tablefmt='github'))
86+
87+
@click.command(name = 'del-invitation', help = 'Delete an unaccepted invitation')
88+
@click.argument('email')
89+
def delete_invitation(email: str):
90+
import json
91+
bitbucket_team_name = os.getenv('BITBUCKET_TEAM')
92+
access_token = get_access_token()
93+
94+
response = requests.delete(
95+
f"{team_invitations_url()}"
96+
.format(team=bitbucket_team_name),
97+
auth = BearerAuth(access_token),
98+
headers = {
99+
'Content-Type' : 'application/json'
100+
},
101+
data = json.dumps({
102+
'email' : email
103+
})
104+
)
105+
106+
print(response)
43107

44108
@click.command(name = 'del', help = 'Delete an user')
45109
@click.argument('username')
@@ -50,4 +114,6 @@ def del_user(username: str):
50114

51115
users_cli.add_command(list_users)
52116
users_cli.add_command(add_user)
117+
users_cli.add_command(list_pending_users)
118+
users_cli.add_command(delete_invitation)
53119
users_cli.add_command(del_user)

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
requests>=2.21.0
22
python-dotenv>=0.10.2
3-
click==7.0
3+
click==7.0
4+
tabulate==0.7.7

setup.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
description = "A small CLI to manage BitBucket Cloud",
66
author = "Genzer Hawker",
77
author_email = "[email protected]",
8-
version='0.2.0',
8+
version='0.3.0',
99
py_modules=['bitbucklet.cli'],
1010
packages = find_packages(),
1111
install_requires=[
1212
'Click',
1313
'requests',
14-
'python-dotenv'
14+
'python-dotenv',
15+
'tabulate'
1516
],
1617
entry_points='''
1718
[console_scripts]

0 commit comments

Comments
 (0)