Skip to content

Commit

Permalink
implement collaborators and permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
tschaume committed May 16, 2015
1 parent 620d083 commit 4b93f72
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 25 deletions.
52 changes: 35 additions & 17 deletions mpcontribs/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,19 @@ def flatten_dict(self, dd, separator='.', prefix=''):
for k, v in self.flatten_dict(vv, separator, kk).items()
} if isinstance(dd, dict) else { prefix : dd }

def plot(self, cid):
def plot(self, contributor_email, cid):
"""make all plots for contribution_id"""
plot_contrib = self.contrib_coll.find_one(
{'contribution_id': cid}, {
'content.data': 1, 'content.plots': 1,
'_id': 0, 'contributor_email': 1
'_id': 0, 'collaborators': 1, 'project': 1
}
)
if 'data' not in plot_contrib['content']:
return None
author = Author.parse_author(plot_contrib['contributor_email'])
project = str(author.name).translate(None, '.').replace(' ','_')
author = Author.parse_author(contributor_email)
project = str(author.name).translate(None, '.').replace(' ','_') \
if 'project' not in plot_contrib else plot_contrib['project']
subfld = 'contributed_data.%s.plotly_urls.%d' % (project, cid)
data = plot_contrib['content']['data']
df = pd.DataFrame.from_dict(data)
Expand Down Expand Up @@ -92,24 +93,33 @@ def _reset(self):
multi=True
))

def delete(self, cids, contributor):
"""remove contributions for requesting contributor"""
author = Author.parse_author(contributor)
project = str(author.name).translate(None, '.').replace(' ','_')
unset_dict = dict(
('contributed_data.%s.%s.%d' % (project, fld, cid), 1)
for fld in ['tables', 'tree_data', 'plotly_urls']
for cid in cids
)
def delete(self, cids):
"""remove contributions"""
unset_dict = {}
# TODO: FIX THIS
# using find during switch from contributor to project, project is known usually
# also fld and cid will be switching places when DBs are migrated
# TODO: remove `project` field when no contributions remaining
for doc in self.mat_coll.find(
{'contributed_data': {'$exists': 1}},
{'_id': 0, 'contributed_data': 1}
):
for project,d in doc['contributed_data'].iteritems():
for fld,dd in d.iteritems():
for cid in dd:
if int(cid) not in cids: continue
key = 'contributed_data.%s.%s.%s' % (project, fld, cid)
unset_dict[key] = 1
self.mat_coll.update(
{'contributed_data.%s' % project: {'$exists': 1}},
{'contributed_data': {'$exists': 1}},
{'$unset': unset_dict}, multi=True
)

def build(self, cids=None):
def build(self, contributor_email, cids=None):
"""update materials collection with contributed data"""
# NOTE: this build is only for contributions tagged with mp-id
# TODO: in general, distinguish mp cat's by format of mp_cat_id
# TODO check all DB calls, consolidate in aggregation call?
plot_cids = None
for doc in self.contrib_coll.aggregate(self.pipeline, cursor={}):
#if plot_cids is None and doc['num_contribs'] > 2:
Expand All @@ -118,7 +128,15 @@ def build(self, cids=None):
for cid in doc['contrib_ids']:
if cids is not None and cid not in cids: continue
contrib = self.contrib_coll.find_one({'contribution_id': cid})
author = Author.parse_author(contrib['contributor_email'])
if contributor_email not in contrib['collaborators']:
raise ValueError(
"Build stopped: building contribution {} not"
" allowed due to insufficient permissions of {}!"
" Ask someone of {} to make you a collaborator on"
" contribution {}.".format(
cid, contributor_email, contrib['collaborators'], cid
))
author = Author.parse_author(contributor_email)
project = str(author.name).translate(None, '.').replace(' ','_') \
if 'project' not in contrib else contrib['project']
logging.info(doc['_id'])
Expand Down Expand Up @@ -153,7 +171,7 @@ def build(self, cids=None):
{'task_id': doc['_id']}, { '$set': all_data }
))
if plot_cids is not None and cid in plot_cids:
plotly_urls = self.plot(cid)
plotly_urls = self.plot(contributor_email, cid)
if plotly_urls is not None:
for plotly_url in plotly_urls:
logging.info(self.mat_coll.update(
Expand Down
19 changes: 11 additions & 8 deletions mpcontribs/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def _get_next_contribution_id(self):
)['next_contribution_id']

def query_contributions(self, crit):
props = [ '_id', 'contributor_email', 'mp_cat_id', 'contribution_id' ]
props = [ '_id', 'collaborators', 'mp_cat_id', 'contribution_id' ]
proj = dict((p, int(p!='_id')) for p in props)
return self.contributions.find(crit, proj)

Expand Down Expand Up @@ -107,19 +107,22 @@ def submit_contribution(self, mpfile, contributor_email, cids=None,
# new submission vs update
cid = self._get_next_contribution_id() if cids is None else cids[idx]
# check contributor permissions if update mode
collaborators = [contributor_email]
if cids is not None:
doc = self.contributions.find_one(
{'contribution_id': cid}, {'_id': 0, 'contributor_email': 1}
)
if doc['contributor_email'] != contributor_email:
collaborators = self.contributions.find_one(
{'contribution_id': cid}, {'_id': 0, 'collaborators': 1}
)['collaborators']
if contributor_email not in collaborators:
raise ValueError(
"Submission stopped: update of contribution {} not"
" allowed due to insufficient permissions of {}!"
" Consider making {} a collaborator on contribution"
" {}.".format(cid, contributor_email, contributor_email, cid))
" Ask someone of {} to make you a collaborator on"
" contribution {}.".format(
cid, contributor_email, collaborators, cid
))
# prepare document
doc = {
'contributor_email': contributor_email,
'collaborators': collaborators,
'contribution_id': cid,
'contributed_at': datetime.datetime.utcnow().isoformat(),
'mp_cat_id': mp_cat_id, 'content': v
Expand Down

0 comments on commit 4b93f72

Please sign in to comment.