Skip to content
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

global: start registering activities #1653

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
71 changes: 71 additions & 0 deletions cap/activities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
#
# This file is part of CERN Analysis Preservation Framework.
# Copyright (C) 2016 CERN.
#
# CERN Analysis Preservation Framework is free software; you can redistribute
# it and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# CERN Analysis Preservation Framework is distributed in the hope that it will
# be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CERN Analysis Preservation Framework; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307, USA.
#
# In applying this license, CERN does not
# waive the privileges and immunities granted to it by virtue of its status
# as an Intergovernmental Organization or submit itself to any jurisdiction.
"""CAP utilities for registering activities with SQL-Continuum plugin."""
from flask import current_app
from invenio_db import db

# list of available activities -> message to show to user (for serializers)
ACTIVITIES = {
'create deposit': None,
'update permissions': None,
'publish analysis': None,
'reedit published analysis': None,
'update analysis': None,
'patch analysis': None,
}


def get_activity_model():
"""Return SQLAlchemy activities model if registered."""
return getattr(current_app.extensions['invenio-db'].versioning_manager,
'activity_cls', None)


def register_activity(verb,
object=None,
object_id=None,
data=None,
target=None,
target_id=None):
"""Register activity if activities plugin on."""

activity_model = get_activity_model()

# check if activities plugin is there
if not activity_model:
return

assert isinstance(object_id, int) if object_id else True
assert isinstance(target_id, int) if target_id else True

assert verb in ACTIVITIES.keys()

with db.session.begin_nested():
db.session.add(
activity_model(verb=verb,
data=data,
object=object,
object_id=object_id,
target=target,
target_id=target_id))
43 changes: 43 additions & 0 deletions cap/alembic/bceec8433ecb_add_table_for_tracking_acitivities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#
# 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.
"""Add table for tracking acitivities."""

import sqlalchemy as sa
from alembic import op

from cap.types import json_type

# revision identifiers, used by Alembic.
revision = 'bceec8433ecb'
down_revision = 'dd3ef5d1ac6f'
branch_labels = ()
depends_on = None


def upgrade():
"""Upgrade database."""
op.create_table(
'activity', sa.Column('id', sa.BigInteger(), nullable=False),
sa.Column('verb', sa.Unicode(length=255), nullable=True),
sa.Column('transaction_id', sa.BigInteger(), nullable=False),
sa.Column('data', json_type),
sa.Column('object_type', sa.String(length=255), nullable=True),
sa.Column('object_id', sa.BigInteger(), nullable=True),
sa.Column('object_tx_id', sa.BigInteger(), nullable=True),
sa.Column('target_type', sa.String(length=255), nullable=True),
sa.Column('target_id', sa.BigInteger(), nullable=True),
sa.Column('target_tx_id', sa.BigInteger(), nullable=True),
sa.PrimaryKeyConstraint('id', name=op.f('pk_activity')))
op.create_index(op.f('ix_activity_transaction_id'),
'activity', ['transaction_id'],
unique=False)


def downgrade():
"""Downgrade database."""
op.drop_index(op.f('ix_activity_transaction_id'), table_name='activity')
op.drop_table('activity')
2 changes: 2 additions & 0 deletions cap/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,3 +650,5 @@ def _(x):

LOGGING_SENTRY_CELERY = True
"""Configure Celery to send logging to Sentry."""

DB_EXTRA_PLUGINS = ['sqlalchemy_continuum.plugins.ActivityPlugin']
83 changes: 20 additions & 63 deletions cap/modules/deposit/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"""Deposit API."""

import copy
from functools import wraps

from flask import current_app, request
from flask_login import current_user
Expand All @@ -45,13 +44,13 @@
from sqlalchemy.orm.exc import NoResultFound
from werkzeug.local import LocalProxy

from cap.activities import register_activity
from cap.modules.deposit.errors import DisconnectWebhookError, FileUploadError
from cap.modules.deposit.validators import DepositValidator
from cap.modules.experiments.permissions import exp_need_factory
from cap.modules.records.api import CAPRecord
from cap.modules.repos.errors import GitError
from cap.modules.repos.factory import create_git_api
from cap.modules.repos.models import GitWebhook, GitWebhookSubscriber
from cap.modules.repos.tasks import download_repo, download_repo_file
from cap.modules.repos.utils import (create_webhook, disconnect_subscriber,
parse_git_url)
Expand All @@ -70,15 +69,14 @@

_datastore = LocalProxy(lambda: current_app.extensions['security'].datastore)

PRESERVE_FIELDS = (
PROTECTED_FIELDS = (
'_deposit',
'_buckets',
'_files',
'_experiment',
'_access',
'_user_edited',
'_fetched_from',
'general_title',
'$schema',
)

Expand Down Expand Up @@ -130,59 +128,6 @@ def build_deposit_schema(self, record):
"""Get schema path for deposit."""
return current_jsonschemas.path_to_url(self.schema.deposit_path)

def pop_from_data(method, fields=None):
"""Remove fields from deposit data.

:param fields: List of fields to remove (default: ``('_deposit',)``).
"""
fields = fields or (
'_deposit',
'_access',
'_experiment',
'_fetched_from',
'_user_edited',
'general_title',
'$schema',
)

@wraps(method)
def wrapper(self, *args, **kwargs):
"""Check current deposit status."""
for field in fields:
if field in args[0]:
args[0].pop(field)

return method(self, *args, **kwargs)

return wrapper

def pop_from_data_patch(method, fields=None):
"""Remove fields from deposit data.

:param fields: List of fields to remove (default: ``('_deposit',)``).
"""
fields = fields or (
'/_deposit',
'/_access',
'/_files',
'/_experiment',
'/_fetched_from',
'/_user_edited',
'/$schema',
)

@wraps(method)
def wrapper(self, *args, **kwargs):
"""Check current deposit status."""
for field in fields:
for k, patch in enumerate(args[0]):
if field == patch.get("path", None):
del args[0][k]

return method(self, *args, **kwargs)

return wrapper

@mark_as_action
def permissions(self, pid=None):
"""Permissions action.
Expand All @@ -196,9 +141,7 @@ def permissions(self, pid=None):
}]
"""
with AdminDepositPermission(self).require(403):

data = request.get_json()

return self.edit_permissions(data)

@mark_as_action
Expand Down Expand Up @@ -352,16 +295,25 @@ def edit(self, *args, **kwargs):

return self

@pop_from_data
def update(self, *args, **kwargs):
"""Update deposit."""
with UpdateDepositPermission(self).require(403):
# filter out protected fields
for field in PROTECTED_FIELDS:
if field in args[0]:
args[0].pop(field)

super(CAPDeposit, self).update(*args, **kwargs)

@pop_from_data_patch
def patch(self, *args, **kwargs):
"""Patch deposit."""
with UpdateDepositPermission(self).require(403):
# filter out protected fields
for field in ('/' + field for field in PROTECTED_FIELDS):
for patch in args[0]:
if patch.get("path", "").startswith(field):
args[0].remove(patch)

return super(CAPDeposit, self).patch(*args, **kwargs)

def edit_permissions(self, data):
Expand Down Expand Up @@ -427,7 +379,7 @@ def edit_permissions(self, data):

return self

@preserve(result=False, fields=PRESERVE_FIELDS)
@preserve(result=False, fields=PROTECTED_FIELDS)
def clear(self, *args, **kwargs):
"""Clear only drafts."""
super(CAPDeposit, self).clear(*args, **kwargs)
Expand Down Expand Up @@ -602,9 +554,14 @@ def create(cls, data, id_=None, owner=current_user):
deposit._create_buckets()
deposit._set_experiment()
deposit._init_owner_permissions(owner)

deposit.commit()

register_activity(
'create deposit',
data=data,
object=deposit.model,
)

return deposit

@classmethod
Expand Down
1 change: 1 addition & 0 deletions requirements-local-forks.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-e git+git://github.com/annatrz/invenio-db@master#egg=invenio-db[postgresql,versioning]
-e git+git://github.com/annatrz/invenio-deposit.git#egg=invenio-deposit
# -e git+git://github.com/reanahub/reana-client.git@master#egg=reana-client
# -e git+git://github.com/reanahub/reana-commons.git@master#egg=reana-commons
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ invenio-config==1.0.0 # via invenio, invenio-app
git+git://github.com/annatrz/invenio-deposit.git#egg=invenio-deposit
git+git://github.com/reanahub/reana-client.git@master#egg=reana-client
git+git://github.com/reanahub/reana-commons.git@master#egg=reana-commons
invenio-db[postgresql,versioning]==1.0.1 # via invenio, invenio-accounts-rest, invenio-admin
git+git://github.com/annatrz/invenio-db@master#egg=invenio-db[postgresql,versioning]
invenio-formatter==1.0.1 # via invenio
invenio-i18n==1.0.0 # via invenio, invenio-accounts, invenio-theme
invenio-indexer==1.0.1 # via invenio, invenio-records-rest
Expand Down