Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trigger Google Drive shared folder sync on user email edit #498

Merged
merged 3 commits into from
Sep 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
chuck-sys marked this conversation as resolved.
Show resolved Hide resolved
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