Browse Source

moving to gittea needs a push

funding-tag
Holger Frey 5 years ago
parent
commit
d4d45d12e4
  1. 2
      README.md
  2. 4
      ordr3/adapters.py
  3. 11
      ordr3/resources.py
  4. 14
      ordr3/schemas/account.py
  5. 2
      ordr3/schemas/orders.py
  6. 12
      ordr3/scripts/migrate_db.py
  7. 2
      ordr3/security.py
  8. 5
      ordr3/services.py
  9. 2
      ordr3/views/account.py
  10. 4
      ordr3/views/root.py
  11. 2
      ordr3/views/users.py
  12. 10
      ordr3/views/vendors.py
  13. 6
      tests/test_adapters.py
  14. 2
      tests/test_repo.py
  15. 12
      tests/test_services.py

2
README.md

@ -13,7 +13,7 @@ Decisions and goals in this project:
- have automatic unit test and functional tests, the coverage should be above 90% - have automatic unit test and functional tests, the coverage should be above 90%
- complete data migration from the old system - complete data migration from the old system
This new system is now online at https://ordr.cpi.imtek.uni-freiburg.de since late April 2020 The new system is now online at https://ordr.cpi.imtek.uni-freiburg.de since late April 2020
## Development ## Development

4
ordr3/adapters.py

@ -175,9 +175,7 @@ def includeme(config):
# make request.dbsession available for use in Pyramid # make request.dbsession available for use in Pyramid
config.add_request_method( config.add_request_method(
lambda r: get_repo_with_session(session_factory, r), lambda r: get_repo_with_session(session_factory, r), "repo", reify=True
"repo",
reify=True,
) )
start_mappers() start_mappers()

11
ordr3/resources.py

@ -34,10 +34,7 @@ class BaseResource(abc.ABC):
class User(BaseResource): class User(BaseResource):
def __acl__(self): def __acl__(self):
""" access controll list """ """ access controll list """
acl = [ acl = [(Allow, "role:admin", "view"), (Allow, "role:admin", "edit")]
(Allow, "role:admin", "view"),
(Allow, "role:admin", "edit"),
]
if not self.model.is_active: if not self.model.is_active:
acl.append((Allow, "role:admin", "delete")) acl.append((Allow, "role:admin", "delete"))
acl.append(DENY_ALL) acl.append(DENY_ALL)
@ -141,11 +138,7 @@ class Root(BaseResource):
__name__ = None __name__ = None
__parent__ = None __parent__ = None
nodes = { nodes = {"users": UserList, "orders": OrderList, "vendors": VendorList}
"users": UserList,
"orders": OrderList,
"vendors": VendorList,
}
def __init__(self, request): def __init__(self, request):
self.request = request self.request = request

14
ordr3/schemas/account.py

@ -67,7 +67,7 @@ class RegistrationSchema(CSRFSchema):
email = colander.SchemaNode( email = colander.SchemaNode(
colander.String(), colander.String(),
validator=deferred_unique_email_validator, validator=deferred_unique_email_validator,
widget=deform.widget.TextInputWidget(template="email.pt",), widget=deform.widget.TextInputWidget(template="email.pt"),
) )
password = colander.SchemaNode( password = colander.SchemaNode(
colander.String(), colander.String(),
@ -128,12 +128,12 @@ class MyAccountSchema(CSRFSchema):
template="textinput_disabled.pt", css_class="o3-reg-username" template="textinput_disabled.pt", css_class="o3-reg-username"
), ),
) )
first_name = colander.SchemaNode(colander.String(),) first_name = colander.SchemaNode(colander.String())
last_name = colander.SchemaNode(colander.String(),) last_name = colander.SchemaNode(colander.String())
email = colander.SchemaNode( email = colander.SchemaNode(
colander.String(), colander.String(),
validator=colander.Email(), validator=colander.Email(),
widget=deform.widget.TextInputWidget(template="email.pt",), widget=deform.widget.TextInputWidget(template="email.pt"),
) )
@classmethod @classmethod
@ -161,12 +161,12 @@ class EditAccountSchema(CSRFSchema):
values=ROLES, css_class="custom-select" values=ROLES, css_class="custom-select"
), ),
) )
first_name = colander.SchemaNode(colander.String(),) first_name = colander.SchemaNode(colander.String())
last_name = colander.SchemaNode(colander.String(),) last_name = colander.SchemaNode(colander.String())
email = colander.SchemaNode( email = colander.SchemaNode(
colander.String(), colander.String(),
validator=colander.Email(), validator=colander.Email(),
widget=deform.widget.TextInputWidget(template="email.pt",), widget=deform.widget.TextInputWidget(template="email.pt"),
) )
@classmethod @classmethod

2
ordr3/schemas/orders.py

@ -64,7 +64,7 @@ class OrderItem(colander.Schema):
item_css_class="row", item_css_class="row",
label_css_class="col-sm-3 col-form-label o3-form-copy", label_css_class="col-sm-3 col-form-label o3-form-copy",
css_class="col-sm-9 o3-vendor", css_class="col-sm-9 o3-vendor",
attributes={"data-url": "",}, # noqa: E231 attributes={"data-url": ""}, # noqa: E231
), ),
) )
package_size = colander.SchemaNode( package_size = colander.SchemaNode(

12
ordr3/scripts/migrate_db.py

@ -123,7 +123,7 @@ vendor_map = {
"Laborhandel Krumpholz": ["krumpholz"], "Laborhandel Krumpholz": ["krumpholz"],
"leuchtmittelmarkt.com": ["leuchtmittelmarkt"], "leuchtmittelmarkt.com": ["leuchtmittelmarkt"],
"Life Sciences Advanced Technologies": [ "Life Sciences Advanced Technologies": [
"life sciences advanced technologies inc", "life sciences advanced technologies inc"
], ],
"Life Technologies": ["lifetechnologies", "ife technologies"], "Life Technologies": ["lifetechnologies", "ife technologies"],
"Macherey Nagel": ["m-n", "mn", "macherey-nagel"], "Macherey Nagel": ["m-n", "mn", "macherey-nagel"],
@ -314,9 +314,7 @@ def migrate_orders(cursor, repo):
old_order[f"{old_field}_date"] old_order[f"{old_field}_date"]
) )
user = _case_insensitive_query_user_by_username(repo, field_by) user = _case_insensitive_query_user_by_username(repo, field_by)
log_entry = models.LogEntry( log_entry = models.LogEntry(order.id, status, user, field_date)
order.id, status, user, field_date,
)
order.add_to_log(log_entry) order.add_to_log(log_entry)
if order.created_on < datetime(2018, 1, 1): if order.created_on < datetime(2018, 1, 1):
@ -332,11 +330,9 @@ def migrate_orders(cursor, repo):
def parse_args(argv): def parse_args(argv):
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
"config_uri", help="Configuration file, e.g., development.ini", "config_uri", help="Configuration file, e.g., development.ini"
)
parser.add_argument(
"old_db", help="ordr2 sqlite database file",
) )
parser.add_argument("old_db", help="ordr2 sqlite database file")
return parser.parse_args(argv[1:]) return parser.parse_args(argv[1:])

2
ordr3/security.py

@ -56,7 +56,7 @@ def includeme(config):
""" """
settings = config.get_settings() settings = config.get_settings()
authn_policy = AuthenticationPolicy( authn_policy = AuthenticationPolicy(
settings["auth.secret"], hashalg="sha512", settings["auth.secret"], hashalg="sha512"
) )
config.set_authentication_policy(authn_policy) config.set_authentication_policy(authn_policy)
config.set_authorization_policy(ACLAuthorizationPolicy()) config.set_authorization_policy(ACLAuthorizationPolicy())

5
ordr3/services.py

@ -8,10 +8,7 @@ import requests
from . import events, models, security from . import events, models, security
CONSUMABLE_STATI = { CONSUMABLE_STATI = {models.OrderStatus.ORDERED, models.OrderStatus.COMPLETED}
models.OrderStatus.ORDERED,
models.OrderStatus.COMPLETED,
}
MSG_SHORT_PASSWORD = events.FlashMessage.warning( MSG_SHORT_PASSWORD = events.FlashMessage.warning(

2
ordr3/views/account.py

@ -272,7 +272,7 @@ def edit_myaccount(context, request):
@view_config( @view_config(
context="ordr3:resources.Root", name="mypassword", permission="account", context="ordr3:resources.Root", name="mypassword", permission="account"
) )
def myaccount_reset_link(context, request): def myaccount_reset_link(context, request):
token = services.create_token_for_user(request.repo, request.user) token = services.create_token_for_user(request.repo, request.user)

4
ordr3/views/root.py

@ -11,9 +11,7 @@ from pyramid.httpexceptions import HTTPFound
@forbidden_view_config() @forbidden_view_config()
@notfound_view_config() @notfound_view_config()
@view_config( @view_config(context="ordr3:resources.Root", permission="view")
context="ordr3:resources.Root", permission="view",
)
def root(context, request): def root(context, request):
if request.user: if request.user:
return HTTPFound(request.resource_path(request.root, "orders")) return HTTPFound(request.resource_path(request.root, "orders"))

2
ordr3/views/users.py

@ -99,7 +99,7 @@ def save_edits(context, request):
user.role = models.UserRole[appstruct["role"]] user.role = models.UserRole[appstruct["role"]]
if not was_active and user.is_active: if not was_active and user.is_active:
request.emit(events.AccountActivationEmail(user,)) request.emit(events.AccountActivationEmail(user))
request.emit(events.FlashMessage.info(f"User {user.username} updated.")) request.emit(events.FlashMessage.info(f"User {user.username} updated."))
return HTTPFound(request.resource_path(context.__parent__)) return HTTPFound(request.resource_path(context.__parent__))

10
ordr3/views/vendors.py

@ -31,10 +31,7 @@ def vendor_list(context, request):
renderer="ordr3:templates/vendors/edit.jinja2", renderer="ordr3:templates/vendors/edit.jinja2",
) )
def vendor_edit_form(context, request): def vendor_edit_form(context, request):
return { return {"form_error": False, "csrf_token": get_csrf_token(request)}
"form_error": False,
"csrf_token": get_csrf_token(request),
}
@view_config( @view_config(
@ -63,7 +60,4 @@ def vendor_edit(context, request):
) )
return HTTPFound(request.resource_url(context.__parent__)) return HTTPFound(request.resource_url(context.__parent__))
return { return {"form_error": True, "csrf_token": get_csrf_token(request)}
"form_error": True,
"csrf_token": get_csrf_token(request),
}

6
tests/test_adapters.py

@ -79,9 +79,9 @@ def test_log_mapper(session, order_sql):
""" """
) )
expected = [ expected = [
LogEntry(1, OrderStatus.OPEN, "ME", datetime(2020, 2, 5, 15, 14, 13),), LogEntry(1, OrderStatus.OPEN, "ME", datetime(2020, 2, 5, 15, 14, 13)),
LogEntry( LogEntry(
1, OrderStatus.COMPLETED, "YOU", datetime(2020, 2, 7, 15, 14, 13), 1, OrderStatus.COMPLETED, "YOU", datetime(2020, 2, 7, 15, 14, 13)
), ),
LogEntry( LogEntry(
1, OrderStatus.ORDERED, "ME", datetime(2020, 2, 6, 15, 14, 13) 1, OrderStatus.ORDERED, "ME", datetime(2020, 2, 6, 15, 14, 13)
@ -112,7 +112,7 @@ def test_user_mapper(session):
expected = [ expected = [
User(1, "Me", "Jane", "Doe", "jane.doe", "1234", UserRole.USER), User(1, "Me", "Jane", "Doe", "jane.doe", "1234", UserRole.USER),
User(2, "You", "Jim", "Smith", "jim.smith", "abcd", UserRole.ADMIN,), User(2, "You", "Jim", "Smith", "jim.smith", "abcd", UserRole.ADMIN),
] ]
assert session.query(User).all() == expected assert session.query(User).all() == expected

2
tests/test_repo.py

@ -70,7 +70,7 @@ def example_users():
from ordr3.models import User, UserRole from ordr3.models import User, UserRole
return [ return [
User(1, "You", "Jim", "Smith", "jim.smith", "abcd", UserRole.ADMIN,), User(1, "You", "Jim", "Smith", "jim.smith", "abcd", UserRole.ADMIN),
User(2, "Me", "Jane", "Doe", "jane.doe", "1234", UserRole.USER), User(2, "Me", "Jane", "Doe", "jane.doe", "1234", UserRole.USER),
] ]

12
tests/test_services.py

@ -119,13 +119,7 @@ def prefilled_repo():
from ordr3.models import OrderItem, OrderStatus, Vendor from ordr3.models import OrderItem, OrderStatus, Vendor
i = count() i = count()
catalog = { catalog = {1: "Ethanol", 2: "Aceton", 3: "NaOH", 4: "Coffee", 5: "Water"}
1: "Ethanol",
2: "Aceton",
3: "NaOH",
4: "Coffee",
5: "Water",
}
def _create_order(item, date, status): def _create_order(item, date, status):
order = OrderItem(next(i), catalog[item], item, "", "", "", "", "") order = OrderItem(next(i), catalog[item], item, "", "", "", "", "")
@ -221,7 +215,7 @@ def test_create_log_entry_not_noteworthy_same_status(prefilled_repo):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"update,new_hash", [(False, "1234"), (True, "4321"),], # noqa: E231 "update,new_hash", [(False, "1234"), (True, "4321")] # noqa: E231
) )
def test_verify_username_and_password_valid(update, new_hash): def test_verify_username_and_password_valid(update, new_hash):
from ordr3.models import User, UserRole from ordr3.models import User, UserRole
@ -238,7 +232,7 @@ def test_verify_username_and_password_valid(update, new_hash):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"name,pwd", [("You", "1234"), ("Me", "abcd"),], # noqa: E231 "name,pwd", [("You", "1234"), ("Me", "abcd")] # noqa: E231
) )
def test_verify_username_and_password_invalid(name, pwd): def test_verify_username_and_password_invalid(name, pwd):
from ordr3.models import User, UserRole from ordr3.models import User, UserRole

Loading…
Cancel
Save