Skip to content

Commit 5378b58

Browse files
committed
Merge branch 'feature/CH-226' of github.com:MetaCell/cloud-harness into feature/CH-226
2 parents 3879b24 + 3c30407 commit 5378b58

19 files changed

Lines changed: 72 additions & 74 deletions

File tree

applications/common/server/common/__main__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from cloudharness import log
55

66

7-
87
app = init_flask()
98

109
if __name__ == '__main__':

applications/common/server/common/util.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ def deserialize_date(string):
6767
:rtype: date
6868
"""
6969
if string is None:
70-
return None
71-
70+
return None
71+
7272
try:
7373
from dateutil.parser import parse
7474
return parse(string).date()
@@ -87,8 +87,8 @@ def deserialize_datetime(string):
8787
:rtype: datetime
8888
"""
8989
if string is None:
90-
return None
91-
90+
return None
91+
9292
try:
9393
from dateutil.parser import parse
9494
return parse(string)
@@ -144,4 +144,4 @@ def _deserialize_dict(data, boxed_type):
144144
:rtype: dict
145145
"""
146146
return {k: _deserialize(v, boxed_type)
147-
for k, v in data.items() }
147+
for k, v in data.items()}

applications/samples/backend/samples/controllers/resource_controller.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def create_sample_resource(sample_resource=None): # noqa: E501
2020
# Connexion 3.x with pythonic_params should auto-deserialize, but if not, get from Flask request
2121
if sample_resource is None:
2222
sample_resource = request.get_json()
23-
23+
2424
if isinstance(sample_resource, dict):
2525
sample_resource = SampleResource.from_dict(sample_resource)
2626

@@ -95,10 +95,10 @@ def update_sample_resource(sampleresource_id, sample_resource=None): # noqa: E5
9595
# Connexion 3.x with pythonic_params should auto-deserialize, but if not, get from Flask request
9696
if sample_resource is None:
9797
sample_resource = request.get_json()
98-
98+
9999
if isinstance(sample_resource, dict):
100100
sample_resource = SampleResource.from_dict(sample_resource)
101-
101+
102102
try:
103103
resource = resource_service.update_sample_resource(
104104
int(sampleresource_id), sample_resource)

applications/samples/backend/samples/controllers/security_controller_.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,25 @@ def info_from_cookieAuth(api_key):
2121
"""
2222
Check and retrieve authentication information from cookie-based API key.
2323
This function is called by Connexion when cookieAuth security is used.
24-
24+
2525
:param api_key Token provided by the kc-access cookie
2626
:type api_key: str
2727
:return: Decoded token information or None if token is invalid
2828
:rtype: dict | None
2929
"""
3030
if not api_key:
3131
return None
32-
32+
3333
# Set the authentication token in the middleware context
3434
# so that get_authentication_token() can access it
3535
set_authentication_token(api_key)
36-
36+
3737
# Decode and validate the token
3838
try:
3939
decoded = decode_token(api_key)
4040
if decoded:
4141
return decoded
4242
except Exception:
4343
pass
44-
44+
4545
return None

applications/samples/backend/samples/util.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ def deserialize_date(string):
6767
:rtype: date
6868
"""
6969
if string is None:
70-
return None
71-
70+
return None
71+
7272
try:
7373
from dateutil.parser import parse
7474
return parse(string).date()
@@ -87,8 +87,8 @@ def deserialize_datetime(string):
8787
:rtype: datetime
8888
"""
8989
if string is None:
90-
return None
91-
90+
return None
91+
9292
try:
9393
from dateutil.parser import parse
9494
return parse(string)
@@ -144,4 +144,4 @@ def _deserialize_dict(data, boxed_type):
144144
:rtype: dict
145145
"""
146146
return {k: _deserialize(v, boxed_type)
147-
for k, v in data.items() }
147+
for k, v in data.items()}

applications/volumemanager/server/volumemanager/util.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ def deserialize_date(string):
6767
:rtype: date
6868
"""
6969
if string is None:
70-
return None
71-
70+
return None
71+
7272
try:
7373
from dateutil.parser import parse
7474
return parse(string).date()
@@ -87,8 +87,8 @@ def deserialize_datetime(string):
8787
:rtype: datetime
8888
"""
8989
if string is None:
90-
return None
91-
90+
return None
91+
9292
try:
9393
from dateutil.parser import parse
9494
return parse(string)
@@ -144,4 +144,4 @@ def _deserialize_dict(data, boxed_type):
144144
:rtype: dict
145145
"""
146146
return {k: _deserialize(v, boxed_type)
147-
for k, v in data.items() }
147+
for k, v in data.items()}

applications/workflows/server/workflows_api/util.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ def deserialize_date(string):
6767
:rtype: date
6868
"""
6969
if string is None:
70-
return None
71-
70+
return None
71+
7272
try:
7373
from dateutil.parser import parse
7474
return parse(string).date()
@@ -87,8 +87,8 @@ def deserialize_datetime(string):
8787
:rtype: datetime
8888
"""
8989
if string is None:
90-
return None
91-
90+
return None
91+
9292
try:
9393
from dateutil.parser import parse
9494
return parse(string)
@@ -144,4 +144,4 @@ def _deserialize_dict(data, boxed_type):
144144
:rtype: dict
145145
"""
146146
return {k: _deserialize(v, boxed_type)
147-
for k, v in data.items() }
147+
for k, v in data.items()}

infrastructure/base-images/cloudharness-base/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ FROM ${PARENT}
33

44
RUN apt update && apt install -y --no-install-recommends \
55
gcc \
6+
g++ \
67
python3-dev \
78
libpq-dev \
89
nfs-common \

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/middleware.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,30 @@
1717
def _get_user(kc_user_id: str) -> User:
1818
"""
1919
Get or create a Django user for the given Keycloak user ID.
20-
20+
2121
CRITICAL SAFETY GUARANTEE: This function will NEVER return a User without a valid Member.
2222
If we cannot ensure a Member exists, we return None (which triggers anonymous user behavior).
23-
23+
2424
Returns:
2525
User: A Django User with a guaranteed Member relationship, or None for anonymous
2626
"""
2727
user = None
2828
if kc_user_id is None:
2929
return None
30-
30+
3131
try:
3232
# Try to get existing user by member relationship
3333
try:
3434
user = User.objects.get(member__kc_id=kc_user_id)
35-
35+
3636
# SAFETY CHECK: Verify member relationship is intact
3737
try:
3838
_ = user.member # Access to verify it exists
3939
except Member.DoesNotExist:
4040
# Member was deleted between the query and now - return None for safety
4141
log.error("User %s found but Member missing. Returning anonymous.", user.id)
4242
return None
43-
43+
4444
except User.DoesNotExist:
4545
# User doesn't exist - create it via sync_kc_user
4646
user_svc = get_user_service()
@@ -49,15 +49,15 @@ def _get_user(kc_user_id: str) -> User:
4949
# sync_kc_user is atomic and guarantees Member creation
5050
user = user_svc.sync_kc_user(kc_user)
5151
user_svc.sync_kc_user_groups(kc_user)
52-
52+
5353
# SAFETY CHECK: Final verification that Member exists
5454
try:
5555
_ = user.member
5656
except Member.DoesNotExist:
5757
# This should NEVER happen due to sync_kc_user safety, but be defensive
5858
log.error("sync_kc_user returned user %s without Member! Returning anonymous.", user.id)
5959
return None
60-
60+
6161
except UniqueViolation as e:
6262
# Race condition while creating the Member object
6363
log.warning("UniqueViolation error for kc_id %s. Probably a race condition. %s", kc_user_id, str(e))
@@ -69,28 +69,28 @@ def _get_user(kc_user_id: str) -> User:
6969
except (User.DoesNotExist, Member.DoesNotExist):
7070
log.error("Failed to retrieve user after UniqueViolation. Returning anonymous.")
7171
return None
72-
72+
7373
except User.MultipleObjectsReturned:
7474
# Race condition, multiple users created for the same kc_id
7575
log.warning("Multiple users found for kc_id %s, cleaning up...", kc_user_id)
7676
user = User.objects.filter(member__kc_id=kc_user_id).order_by('id').first()
7777
User.objects.filter(member__kc_id=kc_user_id).exclude(id=user.id).delete()
78-
78+
7979
# SAFETY CHECK: Verify the kept user has a Member
8080
try:
8181
_ = user.member
8282
except:
8383
log.error("Cleaned up user %s has no Member. Returning anonymous.", user.id)
8484
return None
85-
85+
8686
return user
8787

8888
except Exception as e:
8989
log.exception("User sync error, %s", kc_user.email)
9090
return None
91-
91+
9292
return user
93-
93+
9494
except KeycloakGetError:
9595
# KC user not found
9696
return None
@@ -120,7 +120,7 @@ def __call__(self, request):
120120
response = self.get_response(request)
121121
response.delete_cookie('kc-access')
122122
return response
123-
123+
124124
if kc_user:
125125
if not user or user.is_anonymous or getattr(user, "member", None) is None or user.member.kc_id != kc_user_id:
126126
user = _get_user(kc_user_id)
@@ -159,7 +159,7 @@ def authenticate(self, request):
159159
except Member.DoesNotExist:
160160
log.error("Authenticated user %s has no Member! Falling back to _get_user.", user.id)
161161
# Fall through to _get_user which will handle this safely
162-
162+
163163
try:
164164
kc_user = AuthClient.decode_token(authentication_token.split(' ')[-1])
165165
kc_user_id = kc_user.get('sub')
@@ -175,5 +175,5 @@ def authenticate(self, request):
175175
except Member.DoesNotExist:
176176
log.error("CRITICAL: _get_user returned user %s without Member! Returning None.", user.id)
177177
return None
178-
178+
179179
return None

infrastructure/common-images/cloudharness-django/libraries/cloudharness-django/cloudharness_django/services/user.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def sync_kc_user(self, kc_user: ch_models.User, is_superuser=False, delete=False
113113

114114
# Create user and member atomically
115115
user, user_created = User.objects.get_or_create(username=username)
116-
116+
117117
# CRITICAL: Ensure Member exists before proceeding
118118
try:
119119
member = Member.objects.get(user=user)
@@ -129,15 +129,15 @@ def sync_kc_user(self, kc_user: ch_models.User, is_superuser=False, delete=False
129129
user = self._map_kc_user(user, kc_user, is_superuser, delete)
130130
self.sync_kc_user_groups(kc_user)
131131
user.save()
132-
132+
133133
# FINAL SAFETY CHECK: Verify Member exists before returning
134134
# This ensures we never return a user without a Member
135135
try:
136136
_ = user.member # Access member to trigger DoesNotExist if missing
137137
except:
138138
# This should never happen, but if it does, create Member immediately
139139
Member.objects.create(kc_id=kc_user.id, user=user)
140-
140+
141141
return user
142142

143143
def sync_kc_user_groups(self, kc_user: ch_models.User):

0 commit comments

Comments
 (0)