Skip to content

Add Google Drive API #81

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

Merged
merged 4 commits into from
Sep 1, 2024
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# main
src/run/
logs/

# google drive api
google_key.json

# Python - Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ uvicorn[standard]==0.27.1
sqlalchemy==2.0.27
asyncpg==0.29.0
alembic==1.13.1
google-api-python-client==2.143.0

# minor
pyOpenSSL==24.0.0 # for generating cryptographically secure random numbers
Expand Down
Empty file added src/google_api/__init__.py
Empty file.
34 changes: 34 additions & 0 deletions src/google_api/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import os
import pathlib

# this google account runs the google workspace for executives
GOOGLE_WORKSPACE_ACCOUNT = "[email protected]"

# any officer from the past 5 semesters has access to these
# TODO: ask the pres if we still want these rules, or not
FIVE_SEM_OFFICER_ACCESS = [
"CSSS@SFU",
]

EXECUTIVE_ACCESS = [
"CSSS Gallery",
"CSSS@SFU",
"Deep-Exec",
"Exec_Photos",
"Private Gallery",
]

# scopes are like permissions to google
GOOGLE_API_SCOPES = [
# google drive permission
"https://www.googleapis.com/auth/drive"
]

# TODO: make this into an enum, or something
GOOGLE_DRIVE_PERMISSION_ROLES = [
"organizer",
"fileOrganizer",
]

_this_file_path = pathlib.Path(__file__).parent.resolve()
SERVICE_ACCOUNT_KEY_PATH = str((_this_file_path / "../../google_key.json").resolve())
68 changes: 68 additions & 0 deletions src/google_api/internals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# google workspace (shared drives) + google drive api

from google.oauth2 import service_account
from googleapiclient.discovery import build

from google_api.constants import GOOGLE_API_SCOPES, GOOGLE_WORKSPACE_ACCOUNT, SERVICE_ACCOUNT_KEY_PATH

# TODO: understand how these work
credentials = service_account.Credentials.from_service_account_file(
filename=SERVICE_ACCOUNT_KEY_PATH,
scopes=GOOGLE_API_SCOPES
)
delegated_credentials = credentials.with_subject(GOOGLE_WORKSPACE_ACCOUNT)
service = build("drive", "v3", credentials=delegated_credentials)

def _list_shared_drives() -> list:
return (
service
.drives()
.list(
#pageSize = 50,
#q = "name contains 'CSSS'",
#useDomainAdminAccess = True,
)
.execute()
)

def list_drive_permissions(drive_id: str) -> list:
return (
service
.permissions()
.list(
fileId = drive_id,
# important to find the shared drive
supportsAllDrives = True,
fields = "*",
)
.execute()
)

def create_drive_permission(drive_id: str, permission: dict):
return (
service
.permissions()
.create(
fileId = drive_id,

# TODO: update message
emailMessage = "You were just given permission to an SFU CSSS shared google drive!",
sendNotificationEmail = True,
supportsAllDrives = True,

body=permission,
)
.execute()
)

def delete_drive_permission(drive_id: str, permission_id: str):
return (
service
.permissions()
.delete(
fileId = drive_id,
permissionId = permission_id,
supportsAllDrives = True,
)
.execute()
)
4 changes: 2 additions & 2 deletions src/officers/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ def serializable_dict(self):

@staticmethod
def from_data(
term: officers.tables.OfficerTerm,
officer_info: officers.tables.OfficerInfo,
term: OfficerTerm,
officer_info: OfficerInfo,
include_private: bool,
is_active: bool,
) -> OfficerData:
Expand Down
4 changes: 4 additions & 0 deletions src/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
from datetime import datetime

from officers.tables import OfficerInfo, OfficerTerm
Expand Down Expand Up @@ -32,3 +33,6 @@ def is_valid_phone_number(phone_number: str) -> bool:
len(phone_number) == 10
and phone_number.isnumeric()
)

def is_valid_email(email: str):
return not re.match(r"^[^@]+@[^@]+\.[a-zA-Z]*$", email)
25 changes: 25 additions & 0 deletions tests/integration/test_google.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from google_api import internals


def test__list_drives():
"""should not fail"""
drive_list = internals._list_shared_drives()
print(drive_list)

drive_id = drive_list["drives"][0]["id"]
print(drive_id)

permissions = internals.list_drive_permissions(drive_id)
print(permissions)

# NOTE: this will raise an exception if the email address is a non-google account
"""
internals.create_drive_permission(
drive_id,
{
"type": "user",
"emailAddress": "[email protected]",
"role": "fileOrganizer",
}
)
"""
Loading