Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,5 @@ ssl/
# vi
.*.swp
.DS_Store

dev_middleware.py
30 changes: 27 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from gql.transport.requests import RequestsHTTPTransport


from models import User, AccessGroup, Repo, Facility, Cluster, CoactRequest, CoactRequestStatus, AuditTrail, AuditTrailObjectType, CoactDatetime
from models import User, AccessGroup, Repo, Facility, Cluster, CoactRequest, CoactRequestStatus, AuditTrail, AuditTrailObjectType, CoactDatetime, UserGidsInfo
from schema import Query, Mutation, Subscription, start_change_stream_queues

import smtplib
Expand Down Expand Up @@ -85,6 +85,19 @@
"""
)

lookupUserGids = gql(
"""
query users($filter: UserInput!) {
users(filter: $filter) {
username
uidnumber
gidNumber
secondaryGidNumbers
}
}
"""
)

class CustomContext(BaseContext):

LOG = logging.getLogger(__name__)
Expand All @@ -100,7 +113,7 @@ class CustomContext(BaseContext):
def __init__(self, *args, **kwargs):
self.db = DB(mongo,DB_NAME)
self.email = Email(EMAIL_SERVER_HOST, EMAIL_SERVER_PORT)
self.userlookup = Client(transport=RequestsHTTPTransport(url=USER_LOOKUP_URL, verify=True, retries=3), fetch_schema_from_transport=True)
self.userlookup = Client(transport=RequestsHTTPTransport(url=USER_LOOKUP_URL, verify=True, retries=3), fetch_schema_from_transport=False)

def __str__(self):
return f"CustomContext User: {self.username} is_admin {self.is_admin}"
Expand Down Expand Up @@ -269,7 +282,18 @@ def lookupUsersFromService(self, filter):
except Exception as e:
LOG.error("Exception looking up user from service")
return []


def lookupUserGidsByUsername(self, username: str) -> Optional[UserGidsInfo]:
resp = self.userlookup.execute(lookupUserGids, variable_values={"filter": {"username": username}})
users = resp.get("users") or []
if not users:
return None
u = users[0]
return UserGidsInfo(
uidnumber=int(u["uidnumber"]),
primaryGid=int(u["gidNumber"]) if u.get("gidNumber") is not None else None,
secondaryGidNumbers=u.get("secondaryGidNumbers") or []
)

class DB:
LOG = logging.getLogger(__name__)
Expand Down
30 changes: 30 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,13 @@ class UserInput:
publichtml: bool = False
isbot: bool = False

@strawberry.type
class UserGidsInfo:
uidnumber: int
primaryGid: int
secondaryGidNumbers: Optional[List[int]]


@strawberry.type
class User(UserInput):
# eppnObjs is most likely a call to some external service to get the details of an eppn
Expand All @@ -280,6 +287,29 @@ def eppnObjs(self, info) -> List[Eppn]:
@strawberry.field
def facilities(self, info) -> List[str]:
return sorted(list(set([x["facility"] for x in info.context.db.collection("repos").find({"name": "default", "users": self.username}, {"_id": 0, "facility": 1})])))

@strawberry.field
def gids(self, info) -> List[int]:
""" A view of the gidNumbers this user belongs to, as nested in each Repo's posixgroup feature. """
gids = set()
repo_filter = {
"$or": [
{"users": self.username},
{"leaders": self.username},
{"principal": self.username},
]
}
for repo in info.context.db.collection("repos").find(repo_filter, {"_id": 0, "features.posixgroup.options": 1}):
for opt in repo.get("features", {}).get("posixgroup", {}).get("options", []):
try:
parsed = json.loads(opt) if isinstance(opt, str) else opt
gid = parsed.get("gidNumber")
if gid is not None:
gids.add(int(gid))
except (ValueError, TypeError, AttributeError):
continue
return sorted(gids)

@strawberry.field
def isAdmin(self, info) -> bool:
admins = re.sub(r"\s", "", os.environ.get("ADMIN_USERNAMES",'')).split(',')
Expand Down
6 changes: 5 additions & 1 deletion schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
AuditTrailObjectType, AuditTrail, AuditTrailInput, \
NotificationInput, Notification, ComputeRequirement, BulkOpsResult, StatusResult, \
CoactDatetime, NormalizedJob, FacillityPastXUsage, RepoPastXUsage, \
NameDesc, RepoFeature, RepoFeatureInput
NameDesc, RepoFeature, RepoFeatureInput, UserGidsInfo

import logging
LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -122,6 +122,10 @@ def usersMatchingUserNames(self, info: Info, regexes: List[str]) -> Optional[Lis
@strawberry.field( permission_classes=[ IsAuthenticated ] )
def usersLookupFromService(self, info: Info, filter: UserInput ) -> List[User]:
return info.context.lookupUsersFromService( filter )

@strawberry.field( permission_classes=[ IsAuthenticated ] )
def myGids(self, info: Info) -> Optional[UserGidsInfo]:
return info.context.lookupUserGidsByUsername(info.context.username)

@strawberry.field( permission_classes=[ IsAuthenticated ] )
def clusters(self, info: Info, filter: Optional[ClusterInput]={} ) -> List[Cluster]:
Expand Down