Skip to content
Merged
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
8 changes: 8 additions & 0 deletions pybossa/cache/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from pybossa.data_access import data_access_levels
from pybossa.util import get_taskrun_date_range_sql_clause_params
from flask import current_app
from pybossa.cache import ONE_HOUR

session = db.slave_session

Expand Down Expand Up @@ -411,6 +412,13 @@ def get_user_by_id(user_id):
return user


@memoize(timeout=ONE_DAY)
def get_user_by_email(email):
assert email is not None
user = User.query.filter_by(email_addr=email).first()
return user


def get_user_profile_metadata(user_id):
user = get_user_by_id(user_id)
info = user.info or {} if user else {}
Expand Down
7 changes: 7 additions & 0 deletions pybossa/cloud_store_api/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ def upload_email_attachment(content, filename, user_email, project_id=None):

# generate signature for authorised access to the attachment
from pybossa.core import signer
from pybossa.core import sentinel
from pybossa.redis_lock import register_user_exported_report
from pybossa.cache.users import get_user_by_email

payload = {"project_id": project_id} if project_id else {}
payload["user_email"] = user_email
signature = signer.dumps(payload)
Expand All @@ -284,6 +288,9 @@ def upload_email_attachment(content, filename, user_email, project_id=None):
server_url = app.config.get('SERVER_URL')
url = f"{server_url}/attachment/{signature}/{timestamp}-{secure_file_name}"
app.logger.info("upload email attachment url %s", url)
user_id = get_user_by_email(user_email).id
cache_info = register_user_exported_report(user_id, url, sentinel.master)
app.logger.info("Cache updated for exported report %s", cache_info)
return url


Expand Down
3 changes: 2 additions & 1 deletion pybossa/emailsvc.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ def send(self, message):
self.request_type: {
"recipients": message["recipients"],
"subject": message["subject"],
"body": message["body"]
"body": message["body"],
"bcc": message.get("bcc") or []
}
}
response = requests.post(self.url, headers=self.headers, json=payload, verify=self.ssl_cert)
Expand Down
2 changes: 1 addition & 1 deletion pybossa/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from pybossa.core import email_service
from pybossa.cloud_store_api.s3 import upload_email_attachment


MINUTE = 60
IMPORT_TASKS_TIMEOUT = (20 * MINUTE)
TASK_DELETE_TIMEOUT = (60 * MINUTE)
Expand Down Expand Up @@ -984,7 +985,6 @@ def export_tasks(current_user_email_addr, short_name,
bucket_name = current_app.config.get('EXPORT_BUCKET')
max_email_size = current_app.config.get('EXPORT_MAX_EMAIL_SIZE', float('Inf'))
max_s3_upload_size = current_app.config.get('EXPORT_MAX_UPLOAD_SIZE', float('Inf'))

if len(content) > max_s3_upload_size and bucket_name:
current_app.logger.info("Task export project id %s: Task export exceeded max size %d, actual size: %d",
project.id, max_s3_upload_size, len(content))
Expand Down
34 changes: 32 additions & 2 deletions pybossa/redis_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,21 @@
# along with PYBOSSA. If not, see <http://www.gnu.org/licenses/>.

import json
from datetime import timedelta
from datetime import timedelta, datetime
from time import time

from pybossa.contributions_guard import ContributionsGuard
from pybossa.core import sentinel
from werkzeug.exceptions import BadRequest
import os

TASK_USERS_KEY_PREFIX = 'pybossa:project:task_requested:timestamps:{0}'
USER_TASKS_KEY_PREFIX = 'pybossa:user:task_acquired:timestamps:{0}'
TASK_ID_PROJECT_ID_KEY_PREFIX = 'pybossa:task_id:project_id:{0}'
ACTIVE_USER_KEY = 'pybossa:active_users_in_project:{}'
EXPIRE_LOCK_DELAY = 5
EXPIRE_RESERVE_TASK_LOCK_DELAY = 30*60

USER_EXPORTED_REPORTS_KEY = 'pybossa:user:exported:reports:{}'

def get_active_user_key(project_id):
return ACTIVE_USER_KEY.format(project_id)
Expand Down Expand Up @@ -127,6 +128,35 @@ def get_locked_tasks_project(project_id):
})
return tasks

def get_user_exported_reports_key(user_id):
# redis key to store exported reports for user_id
return USER_EXPORTED_REPORTS_KEY.format(user_id)

def register_user_exported_report(user_id, path, conn, ttl=60*60):
# register report path for user_id
# reports are stored as hset with key as user_id and field as timestamp:path
now = time()
key = get_user_exported_reports_key(user_id)
filename = os.path.basename(path)
value = json.dumps({"filename": filename, "path": path})
conn.hset(key, now, value)
conn.expire(key, ttl)
cache_info = f"Registered exported report for user_id {user_id} at {now} with value {value}"
return cache_info

def get_user_exported_reports(user_id, conn):
# obtain all reports for user_id
# reports are stored as hset with key as user_id and field as timestamp:path
# return list of (timestamp, path) tuples
key = get_user_exported_reports_key(user_id)
reports_data = conn.hgetall(key).items()
result = []
for k, v in reports_data:
decoded_value = json.loads(v.decode())
formatted_time = datetime.fromtimestamp(float(k.decode())).strftime('%Y-%m-%d %H:%M:%S:%f')[:-3]
result.append((formatted_time, decoded_value['filename'], decoded_value['path']))
return result


class LockManager(object):
"""
Expand Down
3 changes: 3 additions & 0 deletions pybossa/view/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,9 @@ def get_bookmarks(user_name, short_name, order_by, desc):
proj_bookmarks = taskbrowse_bookmarks.get(short_name, {})
return bookmarks_dict_to_array(proj_bookmarks, order_by, desc)

def get_user_reports(user_name):
user_reports = cached_users.get_user_reports(user_name)
return user_reports

def add_bookmark(user_name, short_name, bookmark_name, bookmark_url, order_by, desc):

Expand Down
6 changes: 4 additions & 2 deletions pybossa/view/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
from sqlalchemy.orm.attributes import flag_modified
from pybossa.util import admin_or_project_owner, validate_ownership_id
from pybossa.api.project import ProjectAPI
from pybossa.redis_lock import get_user_exported_reports

cors_headers = ['Content-Type', 'Authorization']

Expand Down Expand Up @@ -1849,7 +1850,7 @@ def get_users_completed(task):
get_users_fullname(page_tasks, lambda task: get_users_completed(task), 'completed_users')

taskbrowse_bookmarks = get_bookmarks(current_user.name, short_name, None, None)

user_reports = get_user_exported_reports(current_user.id, sentinel.master)
valid_user_preferences = app_settings.upref_mdata.get_valid_user_preferences() \
if app_settings.upref_mdata else {}
language_options = valid_user_preferences.get('languages')
Expand Down Expand Up @@ -1882,7 +1883,8 @@ def get_users_completed(task):
allow_taskrun_edit=allow_taskrun_edit,
regular_user=regular_user,
admin_subadmin_coowner=admin_subadmin_coowner,
taskbrowse_bookmarks=taskbrowse_bookmarks)
taskbrowse_bookmarks=taskbrowse_bookmarks,
user_reports=user_reports)


return handle_content_type(data)
Expand Down
Loading