forked from inveniosoftware/invenio-communities
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
cache: adds unmanaged groups to be cached and loaded in the identity
* closes inveniosoftware/invenio-app-rdm#2186 * fixes display of group names * updates hooks to invalidate cache on user/role change * adds identity cache * adds celery task to clean the identity cache Co-authored-by: jrcastro2 <[email protected]>
- Loading branch information
Showing
26 changed files
with
569 additions
and
103 deletions.
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
invenio_communities/alembic/02cd82910727_update_role_id_type_upgrade.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# | ||
# This file is part of Invenio. | ||
# Copyright (C) 2016-2018 CERN. | ||
# | ||
# Invenio is free software; you can redistribute it and/or modify it | ||
# under the terms of the MIT License; see LICENSE file for more details. | ||
|
||
"""Update role_id type. | ||
This recipe only contains the upgrade because as it directly depends on invenio-accounts recipe. That recipe is in | ||
charge of deleting all the constraints on the role_id, including foreign keys using the role_id declared in this module. | ||
Therefore, when in order to downgrade we need to split the recipes to be able to first execute the recipe in | ||
invenio-access (f9843093f686) - this will invoke the recipe from invenio-accounts and delete all the FKs - and after | ||
that we can execute the downgrade recipe (37b21951084c). | ||
""" | ||
|
||
import sqlalchemy as sa | ||
from alembic import op | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "02cd82910727" | ||
down_revision = ( | ||
"f9843093f686", | ||
"37b21951084c", | ||
) # Depends on invenio-access revision id (f9843093f686) | ||
branch_labels = () | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
"""Upgrade database.""" | ||
# Foreign keys are already dropped by invenio-accounts | ||
op.alter_column( | ||
"communities_archivedinvitations", | ||
"group_id", | ||
existing_type=sa.INTEGER(), | ||
type_=sa.String(length=80), | ||
existing_nullable=True, | ||
) | ||
op.create_foreign_key( | ||
op.f("fk_communities_archivedinvitations_group_id_accounts_role"), | ||
"communities_archivedinvitations", | ||
"accounts_role", | ||
["group_id"], | ||
["id"], | ||
ondelete="RESTRICT", | ||
) | ||
op.alter_column( | ||
"communities_members", | ||
"group_id", | ||
existing_type=sa.INTEGER(), | ||
type_=sa.String(length=80), | ||
existing_nullable=True, | ||
) | ||
op.create_foreign_key( | ||
op.f("fk_communities_members_group_id_accounts_role"), | ||
"communities_members", | ||
"accounts_role", | ||
["group_id"], | ||
["id"], | ||
ondelete="RESTRICT", | ||
) | ||
|
||
|
||
def downgrade(): | ||
"""Downgrade database.""" | ||
pass |
58 changes: 58 additions & 0 deletions
58
invenio_communities/alembic/37b21951084c_update_role_id_type_downgrade.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
# | ||
# This file is part of Invenio. | ||
# Copyright (C) 2016-2018 CERN. | ||
# | ||
# Invenio is free software; you can redistribute it and/or modify it | ||
# under the terms of the MIT License; see LICENSE file for more details. | ||
|
||
"""Update role_id type (downgrade recipe).""" | ||
|
||
import sqlalchemy as sa | ||
from alembic import op | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = "37b21951084c" | ||
down_revision = "a3f5a8635cbb" | ||
branch_labels = () | ||
depends_on = None | ||
|
||
|
||
def upgrade(): | ||
"""Upgrade database.""" | ||
pass | ||
|
||
|
||
def downgrade(): | ||
"""Downgrade database.""" | ||
op.alter_column( | ||
"communities_members", | ||
"group_id", | ||
existing_type=sa.String(length=80), | ||
type_=sa.INTEGER(), | ||
existing_nullable=True, | ||
postgresql_using="group_id::integer", | ||
) | ||
op.create_foreign_key( | ||
op.f("fk_communities_members_group_id_accounts_role"), | ||
"communities_members", | ||
"accounts_role", | ||
["group_id"], | ||
["id"], | ||
ondelete="RESTRICT", | ||
) | ||
op.alter_column( | ||
"communities_archivedinvitations", | ||
"group_id", | ||
existing_type=sa.String(length=80), | ||
type_=sa.INTEGER(), | ||
existing_nullable=True, | ||
postgresql_using="group_id::integer", | ||
) | ||
op.create_foreign_key( | ||
op.f("fk_communities_archivedinvitations_group_id_accounts_role"), | ||
"communities_archivedinvitations", | ||
"accounts_role", | ||
["group_id"], | ||
["id"], | ||
ondelete="RESTRICT", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# This file is part of Invenio. | ||
# Copyright (C) 2023 CERN. | ||
# | ||
# Invenio is free software; you can redistribute it and/or modify it | ||
# under the terms of the MIT License; see LICENSE file for more details. | ||
|
||
"""Cache implementations.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# This file is part of Invenio. | ||
# Copyright (C) 2023 CERN. | ||
# | ||
# Invenio is free software; you can redistribute it and/or modify it | ||
# under the terms of the MIT License; see LICENSE file for more details. | ||
|
||
"""Abstract simple identity cache definition.""" | ||
from abc import ABC, abstractmethod | ||
|
||
from flask import current_app | ||
from werkzeug.utils import cached_property | ||
|
||
|
||
class IdentityCache(ABC): | ||
"""Abstract cache layer.""" | ||
|
||
def __init__(self, app=None): | ||
"""Initialize the cache.""" | ||
|
||
@cached_property | ||
def timeout(self): | ||
"""Return default timeout from config.""" | ||
return current_app.config["COMMUNITIES_IDENTITIES_CACHE_TIME"] | ||
|
||
@abstractmethod | ||
def get(self, key): | ||
"""Return the key value. | ||
:param key: the object's key | ||
""" | ||
|
||
@abstractmethod | ||
def set(self, key, value, timeout=None): | ||
"""Cache the object. | ||
:param key: the object's key | ||
:param value: the stored object | ||
:param timeout: the cache timeout in seconds | ||
""" | ||
|
||
@abstractmethod | ||
def delete(self, key): | ||
"""Delete the specific key.""" | ||
|
||
@abstractmethod | ||
def flush(self): | ||
"""Flush the cache.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# -*- coding: utf-8 -*- | ||
# | ||
# This file is part of Invenio. | ||
# Copyright (C) 2023 CERN. | ||
# | ||
# Invenio is free software; you can redistribute it and/or modify it | ||
# under the terms of the MIT License; see LICENSE file for more details. | ||
|
||
"""Implements a Redis cache.""" | ||
from cachelib import RedisCache | ||
from flask import current_app | ||
from redis import StrictRedis | ||
|
||
from invenio_communities.cache.cache import IdentityCache | ||
|
||
|
||
class IdentityRedisCache(IdentityCache): | ||
"""Redis image cache.""" | ||
|
||
def __init__(self, app=None): | ||
"""Initialize the cache.""" | ||
super().__init__(app=app) | ||
app = app or current_app | ||
redis_url = app.config["COMMUNITIES_IDENTITIES_CACHE_REDIS_URL"] | ||
prefix = app.config.get("COMMUNITIES_IDENTITIES_CACHE_REDIS_PREFIX", "identity") | ||
self.cache = RedisCache(host=StrictRedis.from_url(redis_url), key_prefix=prefix) | ||
|
||
def get(self, key): | ||
"""Return the key value. | ||
:param key: the object's key | ||
:return: the stored object | ||
""" | ||
return self.cache.get(key) | ||
|
||
def set(self, key, value, timeout=None): | ||
"""Cache the object. | ||
:param key: the object's key | ||
:param value: the stored object | ||
:param timeout: the cache timeout in seconds | ||
""" | ||
timeout = timeout or self.timeout | ||
self.cache.set(key, value, timeout=timeout) | ||
|
||
def delete(self, key): | ||
"""Delete the specific key.""" | ||
self.cache.delete(key) | ||
|
||
def flush(self): | ||
"""Flush the cache.""" | ||
self.cache.clear() | ||
|
||
def append(self, key, value): | ||
"""Appends a new value to a list. | ||
:param key: the object's key | ||
:param value: the stored list | ||
""" | ||
values_list = self.cache.get(key) | ||
if values_list: | ||
if not isinstance(values_list, list): | ||
raise TypeError( | ||
"Value {value} must be a list but was {type}".format( | ||
value=values_list, type=type(values_list) | ||
) | ||
) | ||
if value not in values_list: | ||
values_list.append(value) | ||
else: | ||
values_list = [value] | ||
self.set(key, values_list) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.