Compare commits

...

21 Commits

Author SHA1 Message Date
b969854592 Prevent deleted users from logging in 2020-07-24 12:45:06 +02:00
4e21b41ba6 On node save, detect changes in the download attr
If a change is detected, mark the previous file as _deleted. This
does not delete any file on the system or database document.
2019-08-28 21:41:05 +02:00
db9cb09c68 Further tweaks to notifications layout 2019-07-02 14:23:50 +02:00
d424febfeb Improve comments parsing
As part of #108 - dillo_post now becomes post, and the title of a
post, or the parsed content of a comment are displayed.
2019-06-27 01:22:45 +02:00
defa5abd18 PEP8 formatting 2019-06-27 01:17:15 +02:00
26858f01b7 Update package-lock.json 2019-05-16 19:23:10 +02:00
3bb35d0ab8 Merge branch 'master' into dillo 2019-04-24 22:24:23 +02:00
38e4c7c937 Merge branch 'master' into dillo
# Conflicts:
#	pillar/api/nodes/__init__.py
2019-04-20 22:26:51 +02:00
312b0a276a Merge branch 'master' into dillo 2019-04-08 23:24:56 +02:00
32361a0e70 Merge branch 'master' into dillo 2019-04-01 18:53:28 +02:00
b26402412b UI: Vertically center badges under comment avatar. 2019-03-21 01:04:21 +01:00
d5f2996704 Remove package-lock.json 2019-03-20 14:19:36 +01:00
d1143bad3e Merge branch 'master' into dillo 2019-03-12 20:27:54 +01:00
c64e24d80d Merge branch 'master' into dillo 2019-03-12 14:28:00 +01:00
446d31d807 Merge branch 'master' into dillo 2019-03-11 19:24:01 +01:00
145d512aa7 UI: Fix emojis margin-top on node description utility. 2019-03-11 03:13:01 +01:00
bf63148852 CSS: Remove primary buttons gradient.
Doesn't always look nice, fallback to default bootstrap primary color instead.
2019-03-11 01:32:17 +01:00
812d911195 Merge branch 'master' into dillo 2019-02-20 23:26:04 +01:00
f0031d44b2 Merge branch 'master' into dillo 2019-02-03 15:51:22 +01:00
5660f4b606 Turn log warning message into debug 2019-02-03 15:50:48 +01:00
6b6a5310f8 Temp fixes for Dillo integration 2019-02-01 19:49:58 +01:00
8 changed files with 12839 additions and 12798 deletions

25568
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
import logging
from html.parser import HTMLParser
from flask import request, current_app
from pillar.api.utils import gravatar
@ -7,6 +8,15 @@ from pillar.auth import current_user
log = logging.getLogger(__name__)
class CommentHTMLParser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.data = []
def handle_data(self, data):
self.data.append(data)
def notification_parse(notification):
activities_collection = current_app.data.driver.db['activities']
activities_subscriptions_collection = \
@ -30,9 +40,14 @@ def notification_parse(notification):
object_type = 'comment'
object_name = ''
object_id = activity['object']
context_object_type = node['parent']['node_type']
# If node_type is 'dillo_post', just call it 'post'
node_type = 'post' if context_object_type.endswith('_post') else \
context_object_type
if node['parent']['user'] == current_user.user_id:
owner = "your {0}".format(node['parent']['node_type'])
owner = f"your {node_type}"
else:
parent_comment_user = users_collection.find_one(
{'_id': node['parent']['user']})
@ -40,10 +55,22 @@ def notification_parse(notification):
user_name = 'their'
else:
user_name = "{0}'s".format(parent_comment_user['username'])
owner = "{0} {1}".format(user_name, node['parent']['node_type'])
context_object_type = node['parent']['node_type']
context_object_name = owner
owner = f"{user_name} {node_type}"
context_object_name = f"{node['parent']['name'][:50]}..."
if context_object_type == 'comment':
# Parse the comment content, which might be HTML and extract
# some text from it.
parser = CommentHTMLParser()
# Trim the comment content to 50 chars, the parser will handle it
parser.feed(node['properties']['content'][:50])
try:
comment_content = parser.data[0]
except KeyError:
comment_content = '...'
# Trim the parsed text down to 15 charss
context_object_name = f"{comment_content[:50]}..."
context_object_id = activity['context_object']
if activity['verb'] == 'replied':
action = 'replied to'
@ -52,13 +79,15 @@ def notification_parse(notification):
else:
action = activity['verb']
action = f'{action} {owner}'
lookup = {
'user': current_user.user_id,
'context_object_type': 'node',
'context_object': context_object_id,
}
subscription = activities_subscriptions_collection.find_one(lookup)
if subscription and subscription['notifications']['web'] == True:
if subscription and subscription['notifications']['web'] is True:
is_subscribed = True
else:
is_subscribed = False

View File

@ -13,7 +13,8 @@ from pillar.web.utils import pretty_date
log = logging.getLogger(__name__)
blueprint = Blueprint('nodes_api', __name__)
ROLES_FOR_SHARING = ROLES_FOR_COMMENTING = {'subscriber', 'demo'}
# TODO(fsiddi) Propose changes to make commenting roles a configuration value.
ROLES_FOR_SHARING = ROLES_FOR_COMMENTING = set()
@blueprint.route('/<node_id>/share', methods=['GET', 'POST'])

View File

@ -69,6 +69,22 @@ def before_replacing_node(item, original):
check_permissions('nodes', original, 'PUT')
update_file_name(item)
# XXX Dillo specific feature (for Graphicall)
if 'download' in original['properties']:
# Check if the file referenced in the download property was updated.
# If so, mark the old file as deleted. A cronjob will take care of
# removing the actual file based on the _delete status of file docs.
original_file_id = original['properties']['download']
new_file_id = item['properties']['download']
if original_file_id == new_file_id:
return
# Mark the original file as _deleted
files = current_app.data.driver.db['files']
files.update_one({'_id': original_file_id}, {'$set': {'_deleted': True}})
log.info('Marking file %s as _deleted' % original_file_id)
def after_replacing_node(item, original):
"""Push an update to the Algolia index when a node item is updated. If the

View File

@ -53,7 +53,7 @@ def find_for_comment(project, node):
'_deleted': {'$ne': True}
}}, api=api)
except ResourceNotFound:
log.warning(
log.debug(
'url_for_node(node_id=%r): Unable to find parent node %r',
node['_id'], parent.parent)
raise ValueError('Unable to find parent node %r' % parent.parent)

View File

@ -50,6 +50,7 @@ def iter_node_properties(node_type):
@functools.lru_cache(maxsize=1)
def tag_choices() -> typing.List[typing.Tuple[str, str]]:
"""Return (value, label) tuples for the NODE_TAGS config setting."""
#TODO(fsiddi) consider allowing tags based on custom_properties in the project.
tags = current_app.config.get('NODE_TAGS') or []
return [(tag, tag.title()) for tag in tags] # (value, label) tuples
@ -70,9 +71,7 @@ def add_form_properties(form_class, node_type):
# Recursive call if detects a dict
field_type = schema_prop['type']
if prop_name == 'tags' and field_type == 'list':
field = SelectMultipleField(choices=tag_choices())
elif field_type == 'dict':
if field_type == 'dict':
assert prop_name == 'attachments'
field = attachments.attachment_form_group_create(schema_prop)
elif field_type == 'list':

View File

@ -72,6 +72,9 @@ def oauth_callback(provider):
# Find or create user
user_info = {'id': oauth_user.id, 'email': oauth_user.email, 'full_name': ''}
db_user = find_user_in_db(user_info, provider=provider)
if '_deleted' in db_user and db_user['_deleted'] is True:
log.debug('User has been deleted and will not be logge in')
return redirect(next_after_login)
db_id, status = upsert_user(db_user)
# TODO(Sybren): If the user doesn't have any badges, but the access token

View File

@ -137,6 +137,7 @@
& .nc-text
width: 90%
white-space: normal
& .nc-date
display: block