Skip to content

Commit 12539c1

Browse files
committed
Merge branch 'release/19.29.0'
2 parents 93f5ed3 + 2c1bc42 commit 12539c1

22 files changed

+327
-259
lines changed

CHANGELOG

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
We follow the CalVer (https://calver.org/) versioning scheme: YY.MINOR.MICRO.
44

5+
19.29.0 (2019-10-02)
6+
===================
7+
- Use new pagecounter fields for increased query efficiency
8+
- Allow meetings to be sorted on download count
9+
- Remove old permissions fields now that we have Guardian
10+
511
19.28.0 (2019-09-24)
612
===================
713
- API v2: Use consistent naming for JSON API type (kebab-case)

Dockerfile

Lines changed: 79 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,27 @@
1-
FROM python:2.7-slim-stretch
2-
3-
ENV GOSU_VERSION=1.10 \
4-
NODE_ENV=production \
5-
NODE_VERSION=8.6.0 \
6-
YARN_VERSION=1.1.0
7-
8-
# Libraries such as matplotlib require a HOME directory for cache and configuration
9-
RUN set -ex \
10-
&& mkdir -p /var/www \
11-
&& chown www-data:www-data /var/www \
12-
&& apt-get update \
13-
&& apt-get install -y gnupg2 \
14-
&& for key in \
15-
# GOSU
16-
B42F6819007F00F88E364FD4036A9C25BF357DD4 \
17-
# https://github.com/nodejs/docker-node/blob/9c25cbe93f9108fd1e506d14228afe4a3d04108f/8.2/Dockerfile
18-
# gpg keys listed at https://github.com/nodejs/node#release-team
19-
# Node
20-
9554F04D7259F04124DE6B476D5A82AC7E37093B \
21-
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
22-
FD3A5288F042B6850C66B31F09FE44734EB7990E \
23-
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
24-
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
25-
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
26-
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
27-
56730D5401028683275BD23C23EFEFE93C4CFFFE \
28-
# Yarn
29-
6A010C5166006599AA17F08146C2130DFD2497F5 \
30-
; do \
31-
gpg --keyserver hkp://ipv4.pool.sks-keyservers.net:80 --recv-keys "$key" || \
32-
gpg --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-keys "$key" || \
33-
gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" || \
34-
gpg --keyserver hkp://keyserver.pgp.com:80 --recv-keys "$key" \
35-
; done \
36-
# Install dependancies
37-
&& apt-get install -y \
38-
git \
39-
libev4 \
40-
libev-dev \
41-
libevent-dev \
42-
libxml2-dev \
43-
libxslt1-dev \
44-
zlib1g-dev \
45-
curl \
46-
# cryptography
47-
build-essential \
48-
libssl-dev \
49-
libffi-dev \
50-
python-dev \
51-
# postgresql
52-
libpq-dev \
53-
# file audits
54-
par2 \
55-
&& ARCH= \
56-
&& dpkgArch="$(dpkg --print-architecture)" \
57-
&& case "${dpkgArch##*-}" in \
58-
amd64) ARCH='x64';; \
59-
ppc64el) ARCH='ppc64le';; \
60-
*) echo "unsupported architecture"; exit 1 ;; \
61-
esac \
62-
# grab gosu for easy step-down from root
63-
&& curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
64-
&& curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc" \
65-
&& gpg --verify /usr/local/bin/gosu.asc \
66-
&& rm /usr/local/bin/gosu.asc \
67-
&& chmod +x /usr/local/bin/gosu \
68-
# Node
69-
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \
70-
&& curl -SLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
71-
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
72-
&& grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
73-
&& tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 \
74-
&& rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
75-
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs \
76-
# Yarn
77-
&& curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
78-
&& curl -fSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
79-
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
80-
&& mkdir -p /opt/yarn \
81-
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/yarn --strip-components=1 \
82-
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarn \
83-
&& ln -s /opt/yarn/bin/yarn /usr/local/bin/yarnpkg \
84-
&& yarn global add bower \
85-
&& yarn cache clean \
86-
&& rm -rf \
87-
yarn-v$YARN_VERSION.tar.gz.asc \
88-
yarn-v$YARN_VERSION.tar.gz \
89-
$HOME/.gnupg \
90-
$HOME/.cache \
91-
&& apt-get remove -y \
92-
curl \
93-
&& apt-get clean \
94-
&& apt-get autoremove -y \
95-
&& rm -rf /var/lib/apt/lists/* \
96-
&& mkdir -p /code
1+
FROM node:8-alpine
2+
3+
# Source: https://github.com/docker-library/httpd/blob/7976cabe162268bd5ad2d233d61e340447bfc371/2.4/alpine/Dockerfile#L3
4+
RUN set -x \
5+
&& addgroup -g 82 -S www-data \
6+
&& adduser -h /var/www -u 82 -D -S -G www-data www-data
7+
8+
RUN apk add --no-cache --virtual .run-deps \
9+
su-exec \
10+
bash \
11+
python \
12+
py-pip \
13+
git \
14+
# lxml2
15+
libxml2 \
16+
libxslt \
17+
# psycopg2
18+
postgresql-libs \
19+
# cryptography
20+
libffi \
21+
# gevent
22+
libev \
23+
libevent \
24+
&& yarn global add bower
9725

9826
WORKDIR /code
9927

@@ -118,7 +46,22 @@ COPY ./addons/twofactor/requirements.txt ./addons/twofactor/
11846
#COPY ./addons/wiki/requirements.txt ./addons/wiki/
11947
COPY ./addons/zotero/requirements.txt ./addons/zotero/
12048

121-
RUN for reqs_file in \
49+
RUN set -ex \
50+
&& mkdir -p /var/www \
51+
&& chown www-data:www-data /var/www \
52+
&& apk add --no-cache --virtual .build-deps \
53+
build-base \
54+
linux-headers \
55+
python-dev \
56+
# lxml2
57+
musl-dev \
58+
libxml2-dev \
59+
libxslt-dev \
60+
# psycopg2
61+
postgresql-dev \
62+
# cryptography
63+
libffi-dev \
64+
&& for reqs_file in \
12265
/code/requirements.txt \
12366
/code/requirements/release.txt \
12467
/code/addons/*/requirements.txt \
@@ -128,17 +71,10 @@ RUN for reqs_file in \
12871
&& (pip uninstall uritemplate.py --yes || true) \
12972
&& pip install --no-cache-dir uritemplate.py==0.3.0 \
13073
# Fix: https://github.com/CenterForOpenScience/osf.io/pull/6783
131-
&& python -m compileall /usr/local/lib/python2.7 || true
132-
133-
# OSF: Assets
134-
COPY ./.bowerrc ./bower.json ./
135-
RUN bower install --production --allow-root \
136-
&& bower cache clean --allow-root
137-
138-
COPY ./package.json ./.yarnrc ./yarn.lock ./
139-
RUN yarn install --frozen-lockfile \
140-
&& yarn cache clean
74+
&& python -m compileall /usr/lib/python2.7 || true \
75+
&& apk del .build-deps
14176

77+
# Settings
14278
COPY ./tasks/ ./tasks/
14379
COPY ./website/settings/ ./website/settings/
14480
COPY ./api/base/settings/ ./api/base/settings/
@@ -148,8 +84,29 @@ RUN mv ./website/settings/local-dist.py ./website/settings/local.py \
14884
&& mv ./api/base/settings/local-dist.py ./api/base/settings/local.py \
14985
&& sed 's/DEBUG_MODE = True/DEBUG_MODE = False/' -i ./website/settings/local.py
15086

87+
# Bower Assets
88+
COPY ./.bowerrc ./bower.json ./
89+
COPY ./admin/.bowerrc ./admin/bower.json ./admin/
90+
RUN \
91+
# OSF
92+
bower install --production --allow-root \
93+
&& bower cache clean --allow-root \
94+
# Admin
95+
&& cd ./admin \
96+
&& bower install --production --allow-root \
97+
&& bower cache clean --allow-root
98+
99+
# Webpack Assets
100+
#
101+
## OSF
102+
COPY ./package.json ./.yarnrc ./yarn.lock ./
151103
COPY ./webpack* ./
152104
COPY ./website/static/ ./website/static/
105+
## Admin
106+
COPY ./admin/package.json ./admin/yarn.lock ./admin/
107+
COPY ./admin/webpack* ./admin/
108+
COPY ./admin/static/ ./admin/static/
109+
## Addons
153110
COPY ./addons/bitbucket/static/ ./addons/bitbucket/static/
154111
COPY ./addons/box/static/ ./addons/box/static/
155112
COPY ./addons/citations/static/ ./addons/citations/static/
@@ -168,34 +125,29 @@ COPY ./addons/s3/static/ ./addons/s3/static/
168125
COPY ./addons/twofactor/static/ ./addons/twofactor/static/
169126
COPY ./addons/wiki/static/ ./addons/wiki/static/
170127
COPY ./addons/zotero/static/ ./addons/zotero/static/
171-
RUN mkdir -p ./website/static/built/ \
128+
RUN \
129+
# OSF
130+
yarn install --frozen-lockfile \
131+
&& mkdir -p ./website/static/built/ \
172132
&& invoke build_js_config_files \
173-
&& yarn run webpack-prod
174-
# /OSF: Assets
175-
176-
# Admin: Assets
177-
COPY ./admin/.bowerrc ./admin/bower.json ./admin/
178-
RUN cd ./admin \
179-
&& bower install --production --allow-root \
180-
&& bower cache clean --allow-root
181-
182-
COPY ./admin/package.json ./admin/yarn.lock ./admin/
183-
RUN cd ./admin \
133+
&& yarn run webpack-prod \
134+
# Admin
135+
&& cd ./admin \
184136
&& yarn install --frozen-lockfile \
185-
&& yarn cache clean
186-
187-
COPY ./admin/webpack* ./admin/
188-
COPY ./admin/static/ ./admin/static/
189-
RUN cd ./admin \
190-
&& yarn run webpack-prod
191-
# /Admin: Assets
137+
&& yarn run webpack-prod \
138+
&& cd ../ \
139+
# Cleanup
140+
&& yarn cache clean \
141+
&& npm cache clean --force
192142

193143
# Copy the rest of the code over
194144
COPY ./ ./
195145

196146
ARG GIT_COMMIT=
197147
ENV GIT_COMMIT ${GIT_COMMIT}
198148

149+
# TODO: Admin/API should fully specify their bower static deps, and not include ./website/static in their defaults.py.
150+
# (this adds an additional 300+mb to the build image)
199151
RUN for module in \
200152
api.base.settings \
201153
admin.base.settings \
@@ -211,4 +163,4 @@ RUN for module in \
211163
; done \
212164
&& rm ./website/settings/local.py ./api/base/settings/local.py
213165

214-
CMD ["gosu", "nobody", "invoke", "--list"]
166+
CMD ["su-exec", "nobody", "invoke", "--list"]

addons/base/views.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,9 @@ def get_auth(auth, **kwargs):
330330
# version index is 0 based
331331
version_index = version - 1
332332
if action == 'render':
333-
update_analytics(node, file_id, version_index, 'view')
333+
update_analytics(node, filenode, version_index, 'view')
334334
elif action == 'download' and not from_mfr:
335-
update_analytics(node, file_id, version_index, 'download')
335+
update_analytics(node, filenode, version_index, 'download')
336336
if waffle.switch_is_active(features.ELASTICSEARCH_METRICS):
337337
if isinstance(node, Preprint):
338338
metric_class = get_metric_class_for_action(action, from_mfr=from_mfr)
@@ -517,7 +517,6 @@ def create_waterbutler_log(payload, **kwargs):
517517
def addon_delete_file_node(self, target, user, event_type, payload):
518518
""" Get addon BaseFileNode(s), move it into the TrashedFileNode collection
519519
and remove it from StoredFileNode.
520-
521520
Required so that the guids of deleted addon files are not re-pointed when an
522521
addon file or folder is moved or renamed.
523522
"""

addons/osfstorage/tests/test_models.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,9 @@ def test_download_count_file(self, mock_session):
184184
mock_session.data = {}
185185
child = self.node_settings.get_root().append_file('Test')
186186

187-
utils.update_analytics(self.project, child._id, 0)
188-
utils.update_analytics(self.project, child._id, 1)
189-
utils.update_analytics(self.project, child._id, 2)
187+
utils.update_analytics(self.project, child, 0)
188+
utils.update_analytics(self.project, child, 1)
189+
utils.update_analytics(self.project, child, 2)
190190

191191
assert_equals(child.get_download_count(), 3)
192192
assert_equals(child.get_download_count(0), 1)

addons/osfstorage/tests/test_utils.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ def setUp(self):
3131

3232
def test_serialize_revision(self):
3333
sessions.sessions[request._get_current_object()] = Session()
34-
utils.update_analytics(self.project, self.record._id, 0)
35-
utils.update_analytics(self.project, self.record._id, 0)
36-
utils.update_analytics(self.project, self.record._id, 2)
34+
utils.update_analytics(self.project, self.record, 0)
35+
utils.update_analytics(self.project, self.record, 0)
36+
utils.update_analytics(self.project, self.record, 2)
3737
expected = {
3838
'index': 1,
3939
'user': {
@@ -58,9 +58,9 @@ def test_serialize_revision(self):
5858

5959
def test_anon_revisions(self):
6060
sessions.sessions[request._get_current_object()] = Session()
61-
utils.update_analytics(self.project, self.record._id, 0)
62-
utils.update_analytics(self.project, self.record._id, 0)
63-
utils.update_analytics(self.project, self.record._id, 2)
61+
utils.update_analytics(self.project, self.record, 0)
62+
utils.update_analytics(self.project, self.record, 0)
63+
utils.update_analytics(self.project, self.record, 2)
6464
expected = {
6565
'index': 2,
6666
'user': None,

addons/osfstorage/utils.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,28 @@
1616
LOCATION_KEYS = ['service', settings.WATERBUTLER_RESOURCE, 'object']
1717

1818

19-
def update_analytics(node, file_id, version_idx, action='download'):
19+
def update_analytics(node, file, version_idx, action='download'):
2020
"""
2121
:param Node node: Root node to update
2222
:param str file_id: The _id field of a filenode
2323
:param int version_idx: Zero-based version index
2424
:param str action: is this logged as download or a view
2525
"""
26-
# Pass in contributors to check that contributors' downloads
26+
# Pass in contributors and group members to check that their downloads
2727
# do not count towards total download count
2828
contributors = []
29-
if node.contributors:
29+
if getattr(node, 'contributors_and_group_members', None):
30+
contributors = node.contributors_and_group_members
31+
elif getattr(node, 'contributors', None):
3032
contributors = node.contributors
33+
3134
node_info = {
3235
'contributors': contributors
3336
}
37+
resource = node.guids.first()
3438

35-
update_counter('{0}:{1}:{2}'.format(action, node._id, file_id), node_info=node_info)
36-
update_counter('{0}:{1}:{2}:{3}'.format(action, node._id, file_id, version_idx), node_info=node_info)
39+
update_counter(resource, file, version=None, action=action, node_info=node_info)
40+
update_counter(resource, file, version_idx, action, node_info=node_info)
3741

3842

3943
def serialize_revision(node, record, version, index, anon=False):
@@ -44,7 +48,6 @@ def serialize_revision(node, record, version, index, anon=False):
4448
:param FileVersion version: The version to serialize
4549
:param int index: One-based index of version
4650
"""
47-
4851
if anon:
4952
user = None
5053
else:

addons/osfstorage/views.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,7 @@ def osfstorage_get_revisions(file_node, payload, target, **kwargs):
106106
counter_prefix = 'download:{}:{}:'.format(file_node.target._id, file_node._id)
107107

108108
version_count = file_node.versions.count()
109-
# Don't worry. The only % at the end of the LIKE clause, the index is still used
110-
counts = dict(PageCounter.objects.filter(_id__startswith=counter_prefix).values_list('_id', 'total'))
109+
counts = dict(PageCounter.objects.filter(resource=file_node.target.guids.first().id, file=file_node, action='download').values_list('_id', 'total'))
111110
qs = FileVersion.includable_objects.filter(basefilenode__id=file_node.id).include('creator__guids').order_by('-created')
112111

113112
for i, version in enumerate(qs):
@@ -233,7 +232,10 @@ def osfstorage_get_children(file_node, **kwargs):
233232
) CHECKOUT_GUID ON TRUE
234233
LEFT JOIN LATERAL (
235234
SELECT P.total AS DOWNLOAD_COUNT FROM osf_pagecounter AS P
236-
WHERE P._id = 'download:' || %s || ':' || F._id
235+
WHERE P.resource_id = %s
236+
AND P.file_id = F.id
237+
AND P.action = 'download'
238+
AND P.version ISNULL
237239
LIMIT 1
238240
) DOWNLOAD_COUNT ON TRUE
239241
LEFT JOIN LATERAL (
@@ -268,7 +270,7 @@ def osfstorage_get_children(file_node, **kwargs):
268270
AND (NOT F.type IN ('osf.trashedfilenode', 'osf.trashedfile', 'osf.trashedfolder'))
269271
""", [
270272
user_content_type_id,
271-
file_node.target._id,
273+
file_node.target.guids.first().id,
272274
user_pk,
273275
user_pk,
274276
user_id,

0 commit comments

Comments
 (0)