Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
core
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to JiHu GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Chenhao Ma
core
Commits
540fd1cb
Commit
540fd1cb
authored
8 years ago
by
Megan Henning
Browse files
Options
Downloads
Patches
Plain Diff
Add replace functionality to api
parent
3d18253e
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
api/auth/containerauth.py
+1
-1
1 addition, 1 deletion
api/auth/containerauth.py
api/dao/containerstorage.py
+17
-5
17 additions, 5 deletions
api/dao/containerstorage.py
api/handlers/containerhandler.py
+14
-7
14 additions, 7 deletions
api/handlers/containerhandler.py
api/util.py
+20
-0
20 additions, 0 deletions
api/util.py
with
52 additions
and
13 deletions
api/auth/containerauth.py
+
1
−
1
View file @
540fd1cb
...
...
@@ -15,7 +15,7 @@ def default_container(handler, container=None, target_parent_container=None):
on the container before actually executing this method.
"""
def
g
(
exec_op
):
def
f
(
method
,
_id
=
None
,
payload
=
None
,
recursive
=
False
):
def
f
(
method
,
_id
=
None
,
payload
=
None
,
recursive
=
False
,
r_payload
=
None
,
replace_metadata
=
False
):
projection
=
None
if
method
==
'
GET
'
and
container
.
get
(
'
public
'
,
False
):
has_access
=
True
...
...
This diff is collapsed.
Click to expand it.
api/dao/containerstorage.py
+
17
−
5
View file @
540fd1cb
...
...
@@ -25,7 +25,8 @@ class ContainerStorage(object):
return
self
.
_get_el
(
_id
)
def
exec_op
(
self
,
action
,
_id
=
None
,
payload
=
None
,
query
=
None
,
user
=
None
,
public
=
False
,
projection
=
None
,
recursive
=
False
):
public
=
False
,
projection
=
None
,
recursive
=
False
,
r_payload
=
None
,
replace_metadata
=
True
):
"""
Generic method to exec an operation.
The request is dispatched to the corresponding private methods.
...
...
@@ -40,7 +41,7 @@ class ContainerStorage(object):
if
action
==
'
DELETE
'
:
return
self
.
_delete_el
(
_id
)
if
action
==
'
PUT
'
:
return
self
.
_update_el
(
_id
,
payload
,
recursive
)
return
self
.
_update_el
(
_id
,
payload
,
recursive
,
r_payload
,
replace_metadata
)
if
action
==
'
POST
'
:
return
self
.
_create_el
(
payload
)
raise
ValueError
(
'
action should be one of GET, POST, PUT, DELETE
'
)
...
...
@@ -49,17 +50,28 @@ class ContainerStorage(object):
log
.
debug
(
payload
)
return
self
.
dbc
.
insert_one
(
payload
)
def
_update_el
(
self
,
_id
,
payload
,
recursive
=
False
):
def
_update_el
(
self
,
_id
,
payload
,
recursive
=
False
,
r_payload
=
None
,
replace_metadata
=
False
):
replace
=
None
if
replace_metadata
:
replace
=
{}
if
payload
.
get
(
'
metadata
'
)
is
not
None
:
replace
[
'
metadata
'
]
=
util
.
mongo_sanitize_fields
(
payload
.
pop
(
'
metadata
'
))
if
payload
.
get
(
'
subject
'
)
is
not
None
and
payload
[
'
subject
'
].
get
(
'
metadata
'
)
is
not
None
:
replace
[
'
subject.metadata
'
]
=
util
.
mongo_sanitize_fields
(
payload
[
'
subject
'
].
pop
(
'
metadata
'
))
update
=
{
'
$set
'
:
util
.
mongo_dict
(
payload
)
}
if
replace
is
not
None
:
update
[
'
$set
'
].
update
(
replace
)
if
self
.
use_object_id
:
try
:
_id
=
bson
.
objectid
.
ObjectId
(
_id
)
except
bson
.
errors
.
InvalidId
as
e
:
raise
APIStorageException
(
e
.
message
)
if
recursive
:
self
.
_propagate_changes
(
_id
,
update
)
if
recursive
and
r_payload
is
not
None
:
self
.
_propagate_changes
(
_id
,
{
'
$set
'
:
util
.
mongo_dict
(
r_payload
)}
)
return
self
.
dbc
.
update_one
({
'
_id
'
:
_id
},
update
)
def
_propagate_changes
(
self
,
_id
,
update
):
...
...
This diff is collapsed.
Click to expand it.
api/handlers/containerhandler.py
+
14
−
7
View file @
540fd1cb
...
...
@@ -305,13 +305,16 @@ class ContainerHandler(base.RequestHandler):
payload
=
self
.
request
.
json_body
payload_validator
(
payload
,
'
PUT
'
)
# Check if any payload keys are a propogated property, ensure they all are
# Check if any payload keys are any propogated property, add to r_payload
rec
=
False
if
set
(
payload
.
keys
()).
intersection
(
set
(
self
.
config
.
get
(
'
propagated_properties
'
,
[]))):
if
not
set
(
payload
.
keys
()).
issubset
(
set
(
self
.
config
[
'
propagated_properties
'
])):
self
.
abort
(
400
,
'
Cannot update propagated properties together with unpropagated properties
'
)
else
:
rec
=
True
# Mark PUT request for propogation
r_payload
=
{}
prop_keys
=
set
(
payload
.
keys
()).
intersection
(
set
(
self
.
config
.
get
(
'
propagated_properties
'
,
[])))
if
prop_keys
:
rec
=
True
for
key
in
prop_keys
:
r_payload
[
key
]
=
payload
[
key
]
# Check if we are updating the parent container of the element (ie we are moving the container)
# In this case, we will check permissions on it.
target_parent_container
,
parent_id_property
=
self
.
_get_parent_container
(
payload
)
...
...
@@ -331,10 +334,14 @@ class ContainerHandler(base.RequestHandler):
# Ensure subject id is a bson object
payload
[
'
subject
'
][
'
_id
'
]
=
bson
.
ObjectId
(
str
(
payload
[
'
subject
'
][
'
_id
'
]))
permchecker
=
self
.
_get_permchecker
(
container
,
target_parent_container
)
# Specifies wether the metadata fields should be replaced or patched with payload value
replace_metadata
=
self
.
get_param
(
'
replace_metadata
'
,
default
=
False
)
try
:
# This line exec the actual request validating the payload that will update the container
# and checking permissions using respectively the two decorators, mongo_validator and permchecker
result
=
mongo_validator
(
permchecker
(
self
.
storage
.
exec_op
))(
'
PUT
'
,
_id
=
_id
,
payload
=
payload
,
recursive
=
rec
)
result
=
mongo_validator
(
permchecker
(
self
.
storage
.
exec_op
))(
'
PUT
'
,
_id
=
_id
,
payload
=
payload
,
recursive
=
rec
,
r_payload
=
r_payload
,
replace_metadata
=
replace_metadata
)
except
APIStorageException
as
e
:
self
.
abort
(
400
,
e
.
message
)
...
...
This diff is collapsed.
Click to expand it.
api/util.py
+
20
−
0
View file @
540fd1cb
...
...
@@ -48,6 +48,26 @@ def mongo_dict(d):
)
return
dict
(
_mongo_list
(
d
))
def
mongo_sanitize_fields
(
d
):
"""
Sanitize keys of arbitrarily structured map without flattening into dot notation
Adapted from http://stackoverflow.com/questions/8429318/how-to-use-dot-in-field-name
"""
if
isinstance
(
d
,
dict
):
return
{
mongo_sanitize_fields
(
str
(
key
)):
value
if
isinstance
(
value
,
str
)
else
mongo_sanitize_fields
(
value
)
for
key
,
value
in
d
.
iteritems
()}
elif
isinstance
(
d
,
list
):
return
[
mongo_sanitize_fields
(
element
)
for
element
in
i
]
elif
isinstance
(
d
,
str
):
# not allowing dots nor dollar signs in fieldnames
d
=
d
.
replace
(
'
.
'
,
'
_
'
)
d
=
d
.
replace
(
'
$
'
,
'
-
'
)
return
d
else
:
return
d
def
user_perm
(
permissions
,
_id
,
site
=
None
):
for
perm
in
permissions
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment