From 80eaae054c83756fd5f90e51bb46627feec149fe Mon Sep 17 00:00:00 2001 From: octavioamu Date: Wed, 13 Nov 2019 10:32:27 -0300 Subject: [PATCH 1/6] add org optin --- app/app/settings.py | 11 ++++++++-- app/app/utils.py | 13 ++++++++++++ app/dashboard/views.py | 6 ++++++ app/marketing/views.py | 6 +++++- .../templates/settings/organizations.html | 21 +++++++++++++++++++ 5 files changed, 54 insertions(+), 3 deletions(-) diff --git a/app/app/settings.py b/app/app/settings.py index 5cb27278307..cd274c43068 100644 --- a/app/app/settings.py +++ b/app/app/settings.py @@ -140,7 +140,8 @@ ROOT_URLCONF = env('ROOT_URLCONF', default='app.urls') AUTHENTICATION_BACKENDS = ( - 'social_core.backends.github.GithubOAuth2', # for Github authentication + # 'social_core.backends.github.GithubOAuth2', # for Github authentication + 'app.utils.CustomGithubOAuth2', 'django.contrib.auth.backends.ModelBackend', ) @@ -532,9 +533,15 @@ SOCIAL_AUTH_GITHUB_SECRET = GITHUB_CLIENT_SECRET SOCIAL_AUTH_POSTGRES_JSONFIELD = True SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = ['username', 'first_name', 'last_name', 'email'] -SOCIAL_AUTH_GITHUB_SCOPE = ['read:user', 'user:email', 'read:org'] +SOCIAL_AUTH_GITHUB_SCOPE = ['read:user', 'user:email'] SOCIAL_AUTH_SANITIZE_REDIRECTS = True +#custom scopes +SOCIAL_AUTH_GH_CUSTOM_KEY = GITHUB_CLIENT_ID +SOCIAL_AUTH_GH_CUSTOM_SECRET = GITHUB_CLIENT_SECRET +SOCIAL_AUTH_GH_CUSTOM_SCOPE = ['read:org', 'public_repo'] + + SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', diff --git a/app/app/utils.py b/app/app/utils.py index 559797844f6..6852b2133e5 100644 --- a/app/app/utils.py +++ b/app/app/utils.py @@ -24,6 +24,7 @@ from ipware.ip import get_real_ip from marketing.utils import get_or_save_email_subscriber from pyshorteners import Shortener +from social_core.backends.github import GithubOAuth2 from social_django.models import UserSocialAuth logger = logging.getLogger(__name__) @@ -458,3 +459,15 @@ def get_profile(request): profile = sync_profile(request.user.username, request.user, hide_profile=False) return profile + +class CustomGithubOAuth2(GithubOAuth2): + print('GithubOAuth2', GithubOAuth2) + # name = 'github-custom' + def get_scope(self): + scope = super(CustomGithubOAuth2, self).get_scope() + print(self.data) + if self.data.get('extrascope'): + scope += ['public_repo', 'read:org'] + print(scope) + print(scope) + return scope diff --git a/app/dashboard/views.py b/app/dashboard/views.py index fb287aeadb7..b4e39f455a5 100644 --- a/app/dashboard/views.py +++ b/app/dashboard/views.py @@ -218,6 +218,12 @@ def gh_login(request): return redirect('social:begin', backend='github') +@csrf_exempt +def gh_org_login(request): + """Attempt to redirect the user to Github for authentication.""" + return redirect('social:begin', backend='gh-custom') + + def get_interest_modal(request): bounty_id = request.GET.get('pk') if not bounty_id: diff --git a/app/marketing/views.py b/app/marketing/views.py index 0b9b73d613d..01426bac3c7 100644 --- a/app/marketing/views.py +++ b/app/marketing/views.py @@ -41,6 +41,9 @@ from cacheops import cached_view from dashboard.models import Profile, TokenApproval from dashboard.utils import create_user_action, get_orgs_perms +from app.utils import CustomGithubOAuth2 +from social_core.backends.github import GithubOAuth2 + from enssubdomain.models import ENSSubdomainRegistration from gas.utils import recommend_min_gas_price_to_confirm_in_time from marketing.mails import new_feedback @@ -712,7 +715,8 @@ def org_settings(request): if not user or not profile or not is_logged_in: login_redirect = redirect('/login/github?next=' + request.get_full_path()) return login_redirect - + # scope = super(GithubOAuth2, self).get_scope() + # print(user.data) orgs = get_orgs_perms(profile) context = { 'is_logged_in': is_logged_in, diff --git a/app/retail/templates/settings/organizations.html b/app/retail/templates/settings/organizations.html index bfad6f3dee2..d0a1166762a 100644 --- a/app/retail/templates/settings/organizations.html +++ b/app/retail/templates/settings/organizations.html @@ -1,6 +1,27 @@ {% extends 'settings/settings.html' %} {% load i18n static avatar_tags %} {% block settings_content %} + +

Create an Organization

+

+ Funders in an organization can: +

+ + + + + {% trans "Sync with GitHub" %} + + + + +

Organization Permissions

The users below are able to fund, edit settings, approve contributors, and payout contributors on the bounties of the organization

{% if orgs %} From b43206bda7f683969d4b67fe48bf2cace572a0af Mon Sep 17 00:00:00 2001 From: octavioamu Date: Thu, 14 Nov 2019 02:33:40 -0300 Subject: [PATCH 2/6] add scope to oauth and sync --- app/app/utils.py | 8 +- app/assets/v2/images/org-robots.png | Bin 0 -> 27920 bytes .../management/commands/sync_orgs_repos.py | 0 app/marketing/views.py | 9 +- .../templates/settings/organizations.html | 89 ++++++++++-------- 5 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 app/assets/v2/images/org-robots.png rename app/{app => dashboard}/management/commands/sync_orgs_repos.py (100%) diff --git a/app/app/utils.py b/app/app/utils.py index 6852b2133e5..b1b74d0c2ee 100644 --- a/app/app/utils.py +++ b/app/app/utils.py @@ -461,13 +461,17 @@ def get_profile(request): return profile class CustomGithubOAuth2(GithubOAuth2): - print('GithubOAuth2', GithubOAuth2) - # name = 'github-custom' + EXTRA_DATA = [ + ('scope', 'scope'), + ] def get_scope(self): scope = super(CustomGithubOAuth2, self).get_scope() print(self.data) if self.data.get('extrascope'): scope += ['public_repo', 'read:org'] print(scope) + from dashboard.management.commands.sync_orgs_repos import Command + print('running') + Command().handle() print(scope) return scope diff --git a/app/assets/v2/images/org-robots.png b/app/assets/v2/images/org-robots.png new file mode 100644 index 0000000000000000000000000000000000000000..e9b3a86ff3093f64fa0cfe4bd983d194685ee1c5 GIT binary patch literal 27920 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
F7`yKa_+{Dy0|vOLi-GAM1Vox{XzECapUCc#ALH
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
IM6N<$f`{cRRsaA1

literal 0
HcmV?d00001

diff --git a/app/app/management/commands/sync_orgs_repos.py b/app/dashboard/management/commands/sync_orgs_repos.py
similarity index 100%
rename from app/app/management/commands/sync_orgs_repos.py
rename to app/dashboard/management/commands/sync_orgs_repos.py
diff --git a/app/marketing/views.py b/app/marketing/views.py
index 01426bac3c7..b6beb75a6a8 100644
--- a/app/marketing/views.py
+++ b/app/marketing/views.py
@@ -711,12 +711,16 @@ def org_settings(request):
     """
     msg = ''
     profile, es, user, is_logged_in = settings_helper_get_auth(request)
+    current_scopes = []
 
     if not user or not profile or not is_logged_in:
         login_redirect = redirect('/login/github?next=' + request.get_full_path())
         return login_redirect
-    # scope = super(GithubOAuth2, self).get_scope()
-    # print(user.data)
+
+    social_auth = user.social_auth.first()
+    if social_auth and social_auth.extra_data:
+        current_scopes = social_auth.extra_data.get('scope').split(',')
+    print(current_scopes)
     orgs = get_orgs_perms(profile)
     context = {
         'is_logged_in': is_logged_in,
@@ -728,6 +732,7 @@ def org_settings(request):
         'orgs': orgs,
         'profile': profile,
         'msg': msg,
+        'current_scopes': current_scopes,
     }
     return TemplateResponse(request, 'settings/organizations.html', context)
 
diff --git a/app/retail/templates/settings/organizations.html b/app/retail/templates/settings/organizations.html
index d0a1166762a..c99e642a5d0 100644
--- a/app/retail/templates/settings/organizations.html
+++ b/app/retail/templates/settings/organizations.html
@@ -2,50 +2,59 @@
 {% load i18n static avatar_tags %}
 {% block settings_content %}
 
-  

Create an Organization

-

- Funders in an organization can: -

-
    -
  • ✅ Fund issues on behalf of other team members
  • -
  • ✅ Modify bounty settings on behalf of other team members
  • -
  • ✅ Approve contributors for bounties on behalf of other team members
  • -
  • ✅ Payout bounties created on behalf of other team members
  • -
- - - {% trans "Sync with GitHub" %} - - - - - -

Organization Permissions

-

The users below are able to fund, edit settings, approve contributors, and payout contributors on the bounties of the organization

- {% if orgs %} - {% for org in orgs %} -
-
-
- {{org.name}} - {{org.name}} view profile -
- Manage on GitHub -
-
- {% for user in org.users %} -
- {{user.handle}} -
- {{user.name}} - {{user.handle}} + {% if 'public_repo' in current_scopes and 'read:org' in current_scopes %} +

Organization Permissions

+

The users below are able to fund, edit settings, approve contributors, and payout contributors on the bounties of the organization

+ {% if orgs %} + {% for org in orgs %} +
+
+
+ {{org.name}} + {{org.name}} view profile
+ Manage on GitHub
- {% endfor %} +
+ {% for user in org.users %} +
+ {{user.handle}} +
+ {{user.name}} + {{user.handle}} +
+
+ {% endfor %} +
+
+ {% endfor %} + {% else %} +

No organization permissions found

+ {% endif %} + + {% else %} +
+
+

Create an Organization

+ Org bots +

+ Funders in an organization can: +

+
    +
  • ✅ Fund issues on behalf of other team members
  • +
  • ✅ Modify bounty settings on behalf of other team members
  • +
  • ✅ Approve contributors for bounties on behalf of other team members
  • +
  • ✅ Payout bounties created on behalf of other team members
  • +
+ + + + {% trans "Sync with GitHub" %} +
- {% endfor %} {% endif %} + {% endblock %} From c994be0d442cd9d8c2af4c55645ed75614e5d89a Mon Sep 17 00:00:00 2001 From: octavioamu Date: Thu, 14 Nov 2019 02:42:24 -0300 Subject: [PATCH 3/6] remove imports --- app/marketing/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/marketing/views.py b/app/marketing/views.py index b6beb75a6a8..6b4dd162fa3 100644 --- a/app/marketing/views.py +++ b/app/marketing/views.py @@ -41,8 +41,6 @@ from cacheops import cached_view from dashboard.models import Profile, TokenApproval from dashboard.utils import create_user_action, get_orgs_perms -from app.utils import CustomGithubOAuth2 -from social_core.backends.github import GithubOAuth2 from enssubdomain.models import ENSSubdomainRegistration from gas.utils import recommend_min_gas_price_to_confirm_in_time From e01fd078901f3c4483b939a760c0c5153ce368f7 Mon Sep 17 00:00:00 2001 From: octavioamu Date: Thu, 14 Nov 2019 12:51:25 -0300 Subject: [PATCH 4/6] fix isort --- app/marketing/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/marketing/views.py b/app/marketing/views.py index 6b4dd162fa3..960b87b4741 100644 --- a/app/marketing/views.py +++ b/app/marketing/views.py @@ -41,7 +41,6 @@ from cacheops import cached_view from dashboard.models import Profile, TokenApproval from dashboard.utils import create_user_action, get_orgs_perms - from enssubdomain.models import ENSSubdomainRegistration from gas.utils import recommend_min_gas_price_to_confirm_in_time from marketing.mails import new_feedback From e20fe14f8be6fcbcf86f394c1a11fb1699c49d67 Mon Sep 17 00:00:00 2001 From: octavioamu Date: Thu, 14 Nov 2019 17:07:39 -0300 Subject: [PATCH 5/6] fix logic --- app/dashboard/utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/dashboard/utils.py b/app/dashboard/utils.py index 28b6610e249..43a8d150cb8 100644 --- a/app/dashboard/utils.py +++ b/app/dashboard/utils.py @@ -916,11 +916,11 @@ def get_orgs_perms(profile): if group_data[1] != "role": #skip repo level groups continue print(g.user_set.prefetch_related('profile').all()) - org_perms['users'].append( - *[{'handle': u.profile.handle, - 'role': group_data[2], - 'name': '{} {}'.format(u.first_name, u.last_name)} - for u in g.user_set.prefetch_related('profile').all()]) + org_perms['users'] = [{ + 'handle': u.profile.handle, + 'role': group_data[2], + 'name': '{} {}'.format(u.first_name, u.last_name) + } for u in g.user_set.prefetch_related('profile').all()] response_data.append(org_perms) return response_data From 58eda8a05c32dd1c76491642ba479e9d5ebd7944 Mon Sep 17 00:00:00 2001 From: octavioamu Date: Tue, 19 Nov 2019 18:01:24 -0300 Subject: [PATCH 6/6] remove prints --- app/app/utils.py | 4 ---- app/dashboard/utils.py | 3 --- app/marketing/views.py | 1 - 3 files changed, 8 deletions(-) diff --git a/app/app/utils.py b/app/app/utils.py index b1b74d0c2ee..2ea808515f4 100644 --- a/app/app/utils.py +++ b/app/app/utils.py @@ -466,12 +466,8 @@ class CustomGithubOAuth2(GithubOAuth2): ] def get_scope(self): scope = super(CustomGithubOAuth2, self).get_scope() - print(self.data) if self.data.get('extrascope'): scope += ['public_repo', 'read:org'] - print(scope) from dashboard.management.commands.sync_orgs_repos import Command - print('running') Command().handle() - print(scope) return scope diff --git a/app/dashboard/utils.py b/app/dashboard/utils.py index 43a8d150cb8..4574c399836 100644 --- a/app/dashboard/utils.py +++ b/app/dashboard/utils.py @@ -907,15 +907,12 @@ def get_orgs_perms(profile): response_data = [] for org in orgs: - print(org) org_perms = {'name': org.name, 'users': []} groups = org.groups.all().filter(user__isnull=False) for g in groups: # "admin", "write", "pull", "none" - print(g) group_data = g.name.split('-') if group_data[1] != "role": #skip repo level groups continue - print(g.user_set.prefetch_related('profile').all()) org_perms['users'] = [{ 'handle': u.profile.handle, 'role': group_data[2], diff --git a/app/marketing/views.py b/app/marketing/views.py index 960b87b4741..25dba8d291f 100644 --- a/app/marketing/views.py +++ b/app/marketing/views.py @@ -717,7 +717,6 @@ def org_settings(request): social_auth = user.social_auth.first() if social_auth and social_auth.extra_data: current_scopes = social_auth.extra_data.get('scope').split(',') - print(current_scopes) orgs = get_orgs_perms(profile) context = { 'is_logged_in': is_logged_in,