Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
reflectometry
django-remote-submission
Commits
4a6c100b
Commit
4a6c100b
authored
Mar 15, 2022
by
Jose Borreguero
Browse files
switch from username to custodian/executor
Signed-off-by:
Jose Borreguero
<
borreguero@gmail.com
>
parent
c6c2fbdb
Pipeline
#196793
failed with stages
in 6 minutes and 11 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
django_remote_submission/models.py
View file @
4a6c100b
...
...
@@ -25,7 +25,6 @@ import ast
import
uuid
from
django.db
import
models
from
django.contrib.auth
import
get_user_model
from
django.utils.translation
import
gettext_lazy
as
_
from
django.conf
import
settings
from
django.core.exceptions
import
ValidationError
,
ObjectDoesNotExist
,
MultipleObjectsReturned
...
...
@@ -36,6 +35,7 @@ from model_utils.models import TimeStampedModel
# standard imports
from
pathlib
import
Path
from
typing
import
Optional
# Thanks http://stackoverflow.com/a/7394475
...
...
@@ -466,33 +466,34 @@ class Result(TimeStampedModel):
return
'{self.remote_filename} <{self.job}>'
.
format
(
self
=
self
)
class
IdentityFileModelError
(
Exception
):
pass
class
IdentityFileModelManager
(
models
.
Manager
):
class
MultipleIdentityFileError
(
MultipleObjectsReturned
):
pass
def
create_from_us
ername
(
self
,
us
ername
:
str
)
->
"IdentityFile"
:
def
create_from_
c
us
todian
(
self
,
c
us
todian
:
str
,
executor
:
Optional
[
str
]
=
None
)
->
"IdentityFile"
:
r
"""Instantiate an identity file object and save in the database by passing only a user name.
Avoids creation when a record for `username` is found in the database. In such case, returns the found record.
:param username: login user name
:param custodian: login user name, or Django session. Will be associated to a private/public SSH key pair.
:param executor: user name in charge of opening an SSH tunnel between the app and worker servers.
:raise MultipleObjectsReturned: when more than one identity-file is found in the database
:return: instance of model IdentityFileModel
"""
recipient
=
get_user_model
().
objects
.
get
(
username
=
username
)
cu
s
to
dian
=
str
(
username
)
if
not
executor
:
exe
cuto
r
=
custodian
try
:
idf_record
=
self
.
get
(
recipient
=
custodian
)
idf_record
=
self
.
get
(
custodian
=
custodian
)
except
ObjectDoesNotExist
:
id_file
=
IdentityFile
(
persistent
=
True
)
idf_record
=
super
().
create
(
recipient
=
custodian
,
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
),
custodian
=
custodian
,
executor
=
custodian
,
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
),
custodian
=
custodian
,
executor
=
executor
)
except
MultipleObjectsReturned
:
# this should not happen
raise
self
.
MultipleIdentityFileError
(
f
"More than one identity file stored for
{
recipient
}
"
)
raise
self
.
MultipleIdentityFileError
(
f
"More than one identity file stored for
{
custodian
}
"
)
return
idf_record
...
...
@@ -517,19 +518,13 @@ class IdentityFileModel(TimeStampedModel):
executor can store more than one public key, meaning one executor can execute jobs
for more than one custodian.
record = IdentityFile.objects.create_from_us
ername
(username)
record = IdentityFile.objects.create_from_
c
us
todian
(username)
"""
recipient
=
models
.
OneToOneField
(
settings
.
AUTH_USER_MODEL
,
models
.
PROTECT
,
related_name
=
"idfile"
,
verbose_name
=
_
(
"User"
),
help_text
=
_
(
"The user receiving the public file"
),
)
private
=
models
.
CharField
(
_
(
"private key file"
),
help_text
=
_
(
"The path to the private SSH key file"
),
max_length
=
250
)
public
=
models
.
CharField
(
_
(
"public key file"
),
help_text
=
_
(
"The path to the public SSH key file"
),
max_length
=
250
)
custodian
=
models
.
CharField
(
...
...
@@ -547,11 +542,12 @@ class IdentityFileModel(TimeStampedModel):
def
__str__
(
self
):
r
"""Convert model to string, e.g. ``"zzz IDF"``"""
return
f
"
{
self
.
recipient
}
IDF"
return
f
"
{
self
.
custodian
}
IDF"
def
save
(
self
,
*
args
,
**
kwargs
):
r
"""Override the save method to prevent updating the record, if extant"""
kwargs
[
"force_insert"
]
=
True
if
IdentityFileModel
.
objects
.
filter
(
custodian
=
self
.
custodian
):
raise
IdentityFileModelError
(
f
"An IdentityFile record for
{
self
.
custodian
}
already exists in the database"
)
kwargs
[
"force_insert"
]
=
True
# prevent updating the record, if extante
return
super
().
save
(
*
args
,
**
kwargs
)
def
delete
(
self
,
*
args
,
**
kwargs
):
...
...
tests/unit/test_models.py
View file @
4a6c100b
...
...
@@ -8,12 +8,19 @@ test_django-remote-submission
Tests for `django-remote-submission` models module.
"""
# package imports
from
django_remote_submission.models
import
ListField
,
IdentityFileModel
,
Interpreter
,
Log
,
Job
,
Result
,
Server
from
django_remote_submission.models
import
(
ListField
,
IdentityFileModel
,
IdentityFileModelError
,
Interpreter
,
Log
,
Job
,
Result
,
Server
,
)
from
django_remote_submission.wrapper.remote
import
IdentityFile
# third party imports
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.db.utils
import
IntegrityError
from
django.contrib.auth
import
get_user_model
import
pytest
...
...
@@ -125,70 +132,79 @@ class TestListField:
class
TestIdentityFileModel
:
r
'''
r
"""
@pytest.mark.django_db
def test_create(self, user):
with pytest.raises(ObjectDoesNotExist) as e:
record = IdentityFileModel.objects.create_by_us
ername
("non-existing-user")
'''
record = IdentityFileModel.objects.create_by_
c
us
todian
("non-existing-user")
"""
@
pytest
.
mark
.
django_db
def
test_instantiate
(
self
,
user
):
id_file
=
IdentityFile
(
sshdir
=
"/tmp"
)
record
=
IdentityFileModel
(
recipient
=
user
,
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
))
assert
record
.
recipient
==
user
username
=
user
.
username
record
=
IdentityFileModel
(
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
),
custodian
=
username
,
executor
=
username
)
assert
os
.
path
.
exists
(
record
.
private
)
assert
os
.
path
.
exists
(
record
.
public
)
assert
record
.
custodian
==
username
assert
record
.
executor
==
username
@
pytest
.
mark
.
django_db
def
test_create
(
self
,
user
):
id_file
=
IdentityFile
(
sshdir
=
"/tmp"
)
record
=
IdentityFileModel
.
objects
.
create
(
recipient
=
user
,
private
=
str
(
id_file
.
priv
ate
),
public
=
str
(
id_file
.
public
))
assert
record
.
recipient
==
user
username
=
user
.
username
record
=
IdentityFileModel
.
objects
.
cre
ate
(
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
),
custodian
=
username
,
executor
=
username
)
assert
os
.
path
.
exists
(
record
.
private
)
assert
os
.
path
.
exists
(
record
.
public
)
assert
record
.
custodian
==
username
assert
record
.
executor
==
username
record
.
delete
()
assert
os
.
path
.
exists
(
record
.
private
)
is
False
assert
os
.
path
.
exists
(
record
.
public
)
is
False
@
pytest
.
mark
.
django_db
(
transaction
=
True
)
def
test_create_from_username
(
self
,
user
):
# error if user does not exist
with
pytest
.
raises
(
ObjectDoesNotExist
)
as
e
:
IdentityFileModel
.
objects
.
create_from_username
(
"non-existing-user"
)
assert
str
(
e
.
value
)
==
"User matching query does not exist."
def
test_create_from_custodian
(
self
,
user
):
username
=
user
.
username
# create an IdentityFileModel record for `user`
record
=
IdentityFileModel
.
objects
.
create_from_username
(
user
.
username
)
assert
record
.
recipient
==
user
assert
Path
(
record
.
private
).
parent
==
Path
.
home
()
/
".ssh"
record_1
=
IdentityFileModel
.
objects
.
create_from_custodian
(
username
)
assert
record_1
.
custodian
==
username
assert
Path
(
record_1
.
private
).
parent
==
Path
.
home
()
/
".ssh"
[
os
.
remove
(
file
)
for
file
in
[
record_1
.
private
,
record_1
.
public
]]
# return the newly created IdentityFileModel record, do not instantiate another one
record_2
=
IdentityFileModel
.
objects
.
create_from_us
ername
(
user
.
username
)
assert
record_2
.
id
==
record
.
id
record_2
=
IdentityFileModel
.
objects
.
create_from_
c
us
todian
(
username
)
assert
record_2
.
id
==
record
_1
.
id
# we screw up if we try to
create & store two records for the same user
# we screw up if we try to
save in the database a record that already exists
id_file
=
IdentityFile
(
sshdir
=
"/tmp"
)
with
pytest
.
raises
(
IntegrityError
)
as
e
:
IdentityFileModel
.
objects
.
create
(
recipient
=
user
,
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
))
assert
str
(
e
.
value
)
==
"UNIQUE constraint failed: django_remote_submission_identityfilemodel.recipient_id"
record
=
IdentityFileModel
(
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
),
custodian
=
username
,
executor
=
username
)
with
pytest
.
raises
(
IdentityFileModelError
)
as
e
:
record
.
save
()
assert
str
(
e
.
value
)
==
f
"An IdentityFile record for
{
username
}
already exists in the database"
[
os
.
remove
(
file
)
for
file
in
[
id_file
.
private
,
id_file
.
public
]]
# same as before, but using
method IdentityFile
Model.save()
# same as before, but using
Model.objects.create(), which calls
Model.save()
id_file
=
IdentityFile
(
sshdir
=
"/tmp"
)
record
=
IdentityFileModel
(
recipient
=
user
,
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
))
with
pytest
.
raises
(
IntegrityError
)
as
e
:
record
.
save
()
assert
str
(
e
.
value
)
==
"UNIQUE constraint failed: django_remote_submission_identityfilemodel.recipient_id"
with
pytest
.
raises
(
IdentityFileModelError
)
as
e
:
IdentityFileModel
.
objects
.
create
(
private
=
str
(
id_file
.
private
),
public
=
str
(
id_file
.
public
),
custodian
=
username
,
executor
=
username
)
assert
str
(
e
.
value
)
==
f
"An IdentityFile record for
{
username
}
already exists in the database"
[
os
.
remove
(
file
)
for
file
in
[
id_file
.
private
,
id_file
.
public
]]
@
pytest
.
mark
.
django_db
(
transaction
=
True
)
def
test_delete
(
self
,
user
):
r
"""delete the record, along with the SSH key files"""
username
=
user
.
username
record
=
IdentityFileModel
.
objects
.
create_from_us
ername
(
user
.
username
)
record
=
IdentityFileModel
.
objects
.
create_from_
c
us
todian
(
user
.
username
)
record
.
delete
()
assert
os
.
path
.
exists
(
record
.
private
)
is
False
assert
os
.
path
.
exists
(
record
.
public
)
is
False
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment