Merge branch 'master' into refactor-workspaces-rescue
This commit is contained in:
@@ -54,13 +54,14 @@ class Invitations(object):
|
||||
return invite
|
||||
|
||||
@classmethod
|
||||
def create(cls, inviter, workspace_role):
|
||||
def create(cls, inviter, workspace_role, email):
|
||||
invite = Invitation(
|
||||
workspace_role=workspace_role,
|
||||
inviter=inviter,
|
||||
user=workspace_role.user,
|
||||
status=InvitationStatus.PENDING,
|
||||
expiration_time=Invitations.current_expiration_time(),
|
||||
email=email,
|
||||
)
|
||||
db.session.add(invite)
|
||||
db.session.commit()
|
||||
@@ -120,4 +121,6 @@ class Invitations(object):
|
||||
previous_invitation = Invitations._get(token)
|
||||
Invitations._update_status(previous_invitation, InvitationStatus.REVOKED)
|
||||
|
||||
return Invitations.create(user, previous_invitation.workspace_role)
|
||||
return Invitations.create(
|
||||
user, previous_invitation.workspace_role, previous_invitation.email
|
||||
)
|
||||
|
@@ -10,7 +10,7 @@ class CSPRole(Enum):
|
||||
NONSENSE_ROLE = "nonsense_role"
|
||||
|
||||
|
||||
class EnvironmentRole(Base, mixins.TimestampsMixin):
|
||||
class EnvironmentRole(Base, mixins.TimestampsMixin, mixins.AuditableMixin):
|
||||
__tablename__ = "environment_roles"
|
||||
|
||||
id = types.Id()
|
||||
@@ -29,6 +29,23 @@ class EnvironmentRole(Base, mixins.TimestampsMixin):
|
||||
self.role, self.user.full_name, self.environment.name, self.id
|
||||
)
|
||||
|
||||
@property
|
||||
def history(self):
|
||||
return self.get_changes()
|
||||
|
||||
@property
|
||||
def event_details(self):
|
||||
return {
|
||||
"updated_user_name": self.user.displayname,
|
||||
"updated_user_id": str(self.user_id),
|
||||
"environment": self.environment.displayname,
|
||||
"environment_id": str(self.environment_id),
|
||||
"project": self.environment.project.name,
|
||||
"project_id": str(self.environment.project_id),
|
||||
"workspace": self.environment.project.workspace.name,
|
||||
"workspace_id": str(self.environment.project.workspace.id),
|
||||
}
|
||||
|
||||
|
||||
Index(
|
||||
"environments_role_user_environment",
|
||||
|
@@ -42,11 +42,13 @@ class Invitation(Base, TimestampsMixin, AuditableMixin):
|
||||
|
||||
expiration_time = Column(TIMESTAMP(timezone=True))
|
||||
|
||||
token = Column(String(), index=True, default=lambda: secrets.token_urlsafe())
|
||||
token = Column(String, index=True, default=lambda: secrets.token_urlsafe())
|
||||
|
||||
email = Column(String, nullable=False)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Invitation(user='{}', workspace_role='{}', id='{}')>".format(
|
||||
self.user_id, self.workspace_role_id, self.id
|
||||
return "<Invitation(user='{}', workspace_role='{}', id='{}', email='{}')>".format(
|
||||
self.user_id, self.workspace_role_id, self.id, self.email
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -82,10 +84,6 @@ class Invitation(Base, TimestampsMixin, AuditableMixin):
|
||||
if self.workspace_role:
|
||||
return self.workspace_role.workspace
|
||||
|
||||
@property
|
||||
def user_email(self):
|
||||
return self.workspace_role.user.email
|
||||
|
||||
@property
|
||||
def user_name(self):
|
||||
return self.workspace_role.user.full_name
|
||||
|
@@ -17,9 +17,12 @@ class AuditableMixin(object):
|
||||
request_id = resource.auditable_request_id()
|
||||
resource_type = resource.auditable_resource_type()
|
||||
display_name = resource.auditable_displayname()
|
||||
changed_state = resource.auditable_changed_state()
|
||||
event_details = resource.auditable_event_details()
|
||||
|
||||
changed_state = (
|
||||
resource.auditable_changed_state() if action == ACTION_UPDATE else None
|
||||
)
|
||||
|
||||
audit_event = AuditEvent(
|
||||
user_id=user_id,
|
||||
workspace_id=workspace_id,
|
||||
@@ -52,14 +55,12 @@ class AuditableMixin(object):
|
||||
|
||||
@staticmethod
|
||||
def audit_update(mapper, connection, target):
|
||||
target.create_audit_event(connection, target, ACTION_UPDATE)
|
||||
if AuditableMixin.get_changes(target):
|
||||
target.create_audit_event(connection, target, ACTION_UPDATE)
|
||||
|
||||
def get_changes(self):
|
||||
"""
|
||||
This function borrows largely from a gist:
|
||||
https://gist.github.com/ngse/c20058116b8044c65d3fbceda3fdf423#file-audit_mixin-py-L106-L120
|
||||
|
||||
It returns a dictionary of the form {item: [from_value, to_value]},
|
||||
This function returns a dictionary of the form {item: [from_value, to_value]},
|
||||
where 'item' is the attribute on the target that has been updated,
|
||||
'from_value' is the value of the attribute before it was updated,
|
||||
and 'to_value' is the current value of the attribute.
|
||||
@@ -71,7 +72,9 @@ class AuditableMixin(object):
|
||||
for attr in attrs:
|
||||
history = getattr(inspect(self).attrs, attr.key).history
|
||||
if history.has_changes():
|
||||
previous_state[attr.key] = [history.deleted.pop(), history.added.pop()]
|
||||
deleted = history.deleted.pop() if history.deleted else None
|
||||
added = history.added.pop() if history.added else None
|
||||
previous_state[attr.key] = [deleted, added]
|
||||
return previous_state
|
||||
|
||||
def auditable_changed_state(self):
|
||||
|
Reference in New Issue
Block a user