Skip to content

Commit

Permalink
Merge pull request #498 from ubclaunchpad/cheukyin699/#495-email-edit…
Browse files Browse the repository at this point in the history
…-trigger

Trigger Google Drive shared folder sync on user email edit
  • Loading branch information
Cheuk Yin Ng authored Sep 26, 2020
2 parents 82261dd + 547abde commit 3cbfcc0
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 41 deletions.
38 changes: 2 additions & 36 deletions app/controller/command/commands/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from interface.github import GithubAPIException, GithubInterface
from interface.slack import SlackAPIError
from interface.gcp import GCPInterface
from interface.gcp_utils import sync_team_email_perms
from config import Config
from app.model import Team, User
from utils.slack_parse import check_permissions
Expand Down Expand Up @@ -682,39 +683,4 @@ def refresh_all_drive_permissions(self):

all_teams: List[Team] = self.facade.query(Team)
for t in all_teams:
self.refresh_drive_permissions(t)

def refresh_drive_permissions(self, t: Team):
"""
Refresh Google Drive permissions for provided team. If no GCP client
is provided, this function is a no-op.
"""

if self.gcp is None:
logging.debug("GCP not enabled, skipping drive permissions")
return

if len(t.folder) == 0:
return

# Generate who to share with
emails: List[str] = []
for github_id in t.members:
users = self.facade. \
query(User, [('github_user_id', github_id)])
if len(users) != 1:
logging.warn(f"None/multiple users for GitHub ID {github_id}")

# For now, naiively iterate over all users, due to
# https://github.com/ubclaunchpad/rocket2/issues/493
for user in users:
if len(user.email) > 0:
emails.append(user.email)

# Sync permissions
if len(emails) > 0:
logging.info("Synchronizing permissions for "
+ f"{t.github_team_name}'s folder ({t.folder}) "
+ f"to {emails}")
self.gcp.set_drive_permissions(
t.github_team_name, t.folder, emails)
sync_team_email_perms(self.gcp, self.facade, t)
10 changes: 8 additions & 2 deletions app/controller/command/commands/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
from app.controller.command.commands.base import Command
from db.facade import DBFacade
from interface.github import GithubAPIException, GithubInterface
from interface.gcp import GCPInterface
from interface.gcp_utils import sync_user_email_perms
from app.model import User, Permissions
from typing import Dict, cast
from typing import Dict, cast, Optional
from utils.slack_parse import escape_email


Expand All @@ -24,7 +26,8 @@ class UserCommand(Command):

def __init__(self,
db_facade: DBFacade,
github_interface: GithubInterface):
github_interface: GithubInterface,
gcp: Optional[GCPInterface]):
"""Initialize user command."""
logging.info("Initializing UserCommand instance")
self.parser = ArgumentParser(prog="/rocket")
Expand All @@ -33,6 +36,7 @@ def __init__(self,
self.help = self.get_help()
self.facade = db_facade
self.github = github_interface
self.gcp = gcp

def init_subparsers(self) -> _SubParsersAction:
"""Initialize subparsers for user command."""
Expand Down Expand Up @@ -220,6 +224,8 @@ def edit_helper(self,
" level.")

self.facade.store(edited_user)
sync_user_email_perms(self.gcp, self.facade, edited_user)

ret = {'attachments': [edited_user.get_attachment()]}
if msg != "":
# mypy doesn't like the fact that there could be different types
Expand Down
4 changes: 3 additions & 1 deletion app/controller/command/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ def __init__(self,
self.__bot = bot
self.__github = gh_interface
self.__gcp = gcp
self.commands["user"] = UserCommand(self.__facade, self.__github)
self.commands["user"] = UserCommand(self.__facade,
self.__github,
self.__gcp)
self.commands["team"] = TeamCommand(config, self.__facade,
self.__github,
self.__bot,
Expand Down
64 changes: 64 additions & 0 deletions interface/gcp_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Utilities for common-used interactions with Google API."""
import logging
from typing import List, Optional
from interface.gcp import GCPInterface
from db import DBFacade
from app.model import User, Team


def sync_user_email_perms(gcp: Optional[GCPInterface],
db: DBFacade,
user: User):
"""
Refresh Google Drive permissions for a provided user. If no GCP client is
provided, this function is a no-op.
Finds folders for user by checking all teams the user is a part of, and
calling ``sync_team_email_perms()``.
"""
if gcp is None:
logging.debug('GCP not enabled, skipping drive permissions')
return

if len(user.email) == 0 or len(user.github_id) == 0:
return

teams_user_is_in = db.query(Team, [('members', user.github_id)])
for team in teams_user_is_in:
sync_team_email_perms(gcp, db, team)


def sync_team_email_perms(gcp: Optional[GCPInterface],
db: DBFacade,
team: Team):
"""
Refresh Google Drive permissions for provided team. If no GCP client
is provided, this function is a no-op.
"""
if gcp is None:
logging.debug("GCP not enabled, skipping drive permissions")
return

if len(team.folder) == 0:
return

# Generate who to share with
emails: List[str] = []
for github_id in team.members:
users = db.query(User, [('github_user_id', github_id)])
if len(users) != 1:
logging.warn(f"None/multiple users for GitHub ID {github_id}")

# For now, naiively iterate over all users, due to
# https://github.com/ubclaunchpad/rocket2/issues/493
for user in users:
if len(user.email) > 0:
emails.append(user.email)

# Sync permissions
if len(emails) > 0:
logging.info("Synchronizing permissions for "
+ f"{team.github_team_name}'s folder ({team.folder}) "
+ f"to {emails}")
gcp.set_drive_permissions(
team.github_team_name, team.folder, emails)
2 changes: 1 addition & 1 deletion tests/app/controller/command/commands/user_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def setUp(self):
self.db = MemoryDB(users=[self.u0, self.u1, self.admin])

self.mock_github = mock.MagicMock(GithubInterface)
self.testcommand = UserCommand(self.db, self.mock_github)
self.testcommand = UserCommand(self.db, self.mock_github, None)
self.maxDiff = None

def test_get_help(self):
Expand Down
4 changes: 4 additions & 0 deletions tests/utils/slack_parse_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,7 @@ def test_escape_email(self):
email = "<mailto:[email protected]|[email protected]>"
ret = util.escape_email(email)
self.assertEqual(ret, "[email protected]")

def test_escape_normal_email(self):
email = '[email protected]'
self.assertEqual(util.escape_email(email), email)
7 changes: 6 additions & 1 deletion utils/slack_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,12 @@ def escape_email(email: str) -> str:
[email protected]
Does nothing if the email is not escaped.
:param email: email to convert
:return: unescaped email
"""
return email.split('|')[0][8:]
if email.startswith('<'):
return email.split('|')[0][8:]
else:
return email

0 comments on commit 3cbfcc0

Please sign in to comment.