Compare commits
No commits in common. "079fbafb97ec6ee14deb1924c832f2ae80c7e852" and "41f625aabc2f5c445918ba8be72ff5866aaf6f9b" have entirely different histories.
079fbafb97
...
41f625aabc
|
@ -114,7 +114,7 @@ class AuthLDAP(AuthPlugin):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if user.display_name:
|
if user.display_name:
|
||||||
attributes.update({"displayName": user.display_name})
|
attributes.update( {"displayName": user.display_name})
|
||||||
ldap_conn.add(dn, self.object_classes, attributes)
|
ldap_conn.add(dn, self.object_classes, attributes)
|
||||||
self._set_roles(user)
|
self._set_roles(user)
|
||||||
self.update_user(user)
|
self.update_user(user)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
from enum import IntEnum
|
from enum import IntEnum
|
||||||
from typing import Optional, Tuple
|
from typing import Optional
|
||||||
|
|
||||||
from werkzeug.exceptions import BadRequest, Conflict, NotFound
|
from werkzeug.exceptions import BadRequest, Conflict, NotFound
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
|
@ -147,7 +147,7 @@ def get_events(
|
||||||
offset: Optional[int] = None,
|
offset: Optional[int] = None,
|
||||||
descending: Optional[bool] = False,
|
descending: Optional[bool] = False,
|
||||||
with_backup=False,
|
with_backup=False,
|
||||||
) -> Tuple[int, list[Event]]:
|
):
|
||||||
"""Query events which start from begin until end
|
"""Query events which start from begin until end
|
||||||
Args:
|
Args:
|
||||||
start (datetime): Earliest start
|
start (datetime): Earliest start
|
||||||
|
@ -161,14 +161,10 @@ def get_events(
|
||||||
query = query.filter(start <= Event.start)
|
query = query.filter(start <= Event.start)
|
||||||
if end is not None:
|
if end is not None:
|
||||||
query = query.filter(Event.start < end)
|
query = query.filter(Event.start < end)
|
||||||
elif start is None:
|
|
||||||
# Neither start nor end was given
|
|
||||||
query = query.filter(datetime.now() <= Event.start)
|
|
||||||
if descending:
|
if descending:
|
||||||
query = query.order_by(Event.start.desc())
|
query = query.order_by(Event.start.desc())
|
||||||
else:
|
else:
|
||||||
query = query.order_by(Event.start)
|
query = query.order_by(Event.start)
|
||||||
count = query.count()
|
|
||||||
if limit is not None:
|
if limit is not None:
|
||||||
query = query.limit(limit)
|
query = query.limit(limit)
|
||||||
if offset is not None and offset > 0:
|
if offset is not None and offset > 0:
|
||||||
|
@ -177,7 +173,7 @@ def get_events(
|
||||||
if not with_backup:
|
if not with_backup:
|
||||||
for event in events:
|
for event in events:
|
||||||
clear_backup(event)
|
clear_backup(event)
|
||||||
return count, events
|
return events
|
||||||
|
|
||||||
|
|
||||||
def delete_event(event_id):
|
def delete_event(event_id):
|
||||||
|
@ -225,24 +221,6 @@ def get_job(job_id, event_id=None) -> Job:
|
||||||
return job
|
return job
|
||||||
|
|
||||||
|
|
||||||
def get_jobs(user, start=None, end=None, limit=None, offset=None, descending=None) -> Tuple[int, list[Job]]:
|
|
||||||
query = Job.query.join(Service).filter(Service.user_ == user)
|
|
||||||
if start is not None:
|
|
||||||
query = query.filter(start <= Job.end)
|
|
||||||
if end is not None:
|
|
||||||
query = query.filter(end >= Job.start)
|
|
||||||
if descending is not None:
|
|
||||||
query = query.order_by(Job.start.desc(), Job.type_id_)
|
|
||||||
else:
|
|
||||||
query = query.order_by(Job.start, Job.type_id_)
|
|
||||||
count = query.count()
|
|
||||||
if limit is not None:
|
|
||||||
query = query.limit(limit)
|
|
||||||
if offset is not None:
|
|
||||||
query = query.offset(offset)
|
|
||||||
return count, query.all()
|
|
||||||
|
|
||||||
|
|
||||||
def add_job(event, job_type, required_services, start, end=None, comment=None):
|
def add_job(event, job_type, required_services, start, end=None, comment=None):
|
||||||
job = Job(
|
job = Job(
|
||||||
required_services=required_services,
|
required_services=required_services,
|
||||||
|
@ -336,16 +314,7 @@ def respond_invitation(invite: Invitation, accepted=True):
|
||||||
raise Conflict
|
raise Conflict
|
||||||
|
|
||||||
if not accepted:
|
if not accepted:
|
||||||
EventPlugin.plugin.notify(
|
EventPlugin.plugin.notify(inviter, _("Invitation rejected"), {"type": NotifyType.INVITATION_REJECTED, "event": job.event_id_, "job": invite.job_id, "invitee": invite.invitee_id})
|
||||||
inviter,
|
|
||||||
_("Invitation rejected"),
|
|
||||||
{
|
|
||||||
"type": NotifyType.INVITATION_REJECTED,
|
|
||||||
"event": job.event_id_,
|
|
||||||
"job": invite.job_id,
|
|
||||||
"invitee": invite.invitee_id,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if invite.transferee_id is None:
|
if invite.transferee_id is None:
|
||||||
assign_job(job, invite.invitee_, 1)
|
assign_job(job, invite.invitee_, 1)
|
||||||
|
@ -355,16 +324,7 @@ def respond_invitation(invite: Invitation, accepted=True):
|
||||||
raise Conflict
|
raise Conflict
|
||||||
unassign_job(job, invite.transferee_, service[0], True)
|
unassign_job(job, invite.transferee_, service[0], True)
|
||||||
assign_job(job, invite.invitee_, service[0].value)
|
assign_job(job, invite.invitee_, service[0].value)
|
||||||
EventPlugin.plugin.notify(
|
EventPlugin.plugin.notify(inviter, _("Invitation accepted"), {"type": NotifyType.INVITATION_ACCEPTED, "event": job.event_id_, "job": invite.job_id, "invitee": invite.invitee_id})
|
||||||
inviter,
|
|
||||||
_("Invitation accepted"),
|
|
||||||
{
|
|
||||||
"type": NotifyType.INVITATION_ACCEPTED,
|
|
||||||
"event": job.event_id_,
|
|
||||||
"job": invite.job_id,
|
|
||||||
"invitee": invite.invitee_id,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@scheduled
|
@scheduled
|
||||||
|
|
|
@ -58,6 +58,7 @@ class Service(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
class Job(db.Model, ModelSerializeMixin):
|
class Job(db.Model, ModelSerializeMixin):
|
||||||
__tablename__ = _table_prefix_ + "job"
|
__tablename__ = _table_prefix_ + "job"
|
||||||
|
_type_id = db.Column("type_id", Serial, db.ForeignKey(f"{_table_prefix_}job_type.id"), nullable=False)
|
||||||
|
|
||||||
id: int = db.Column(Serial, primary_key=True)
|
id: int = db.Column(Serial, primary_key=True)
|
||||||
start: datetime = db.Column(UtcDateTime, nullable=False)
|
start: datetime = db.Column(UtcDateTime, nullable=False)
|
||||||
|
@ -72,8 +73,6 @@ class Job(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
event_ = db.relationship("Event", back_populates="jobs")
|
event_ = db.relationship("Event", back_populates="jobs")
|
||||||
event_id_ = db.Column("event_id", Serial, db.ForeignKey(f"{_table_prefix_}event.id"), nullable=False)
|
event_id_ = db.Column("event_id", Serial, db.ForeignKey(f"{_table_prefix_}event.id"), nullable=False)
|
||||||
type_id_ = db.Column("type_id", Serial, db.ForeignKey(f"{_table_prefix_}job_type.id"), nullable=False)
|
|
||||||
|
|
||||||
invitations_ = db.relationship("Invitation", cascade="all,delete,delete-orphan", back_populates="job_")
|
invitations_ = db.relationship("Invitation", cascade="all,delete,delete-orphan", back_populates="job_")
|
||||||
|
|
||||||
__table_args__ = (UniqueConstraint("type_id", "start", "event_id", name="_type_start_uc"),)
|
__table_args__ = (UniqueConstraint("type_id", "start", "event_id", name="_type_start_uc"),)
|
||||||
|
|
|
@ -1,14 +1,18 @@
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
from http.client import NO_CONTENT
|
from http.client import NO_CONTENT
|
||||||
|
from re import template
|
||||||
from flask import request, jsonify
|
from flask import request, jsonify
|
||||||
|
from sqlalchemy import exc
|
||||||
from werkzeug.exceptions import BadRequest, NotFound, Forbidden
|
from werkzeug.exceptions import BadRequest, NotFound, Forbidden
|
||||||
|
|
||||||
from flaschengeist.models.session import Session
|
from flaschengeist.models.session import Session
|
||||||
|
from flaschengeist.plugins.events.models import Job
|
||||||
from flaschengeist.utils.decorators import login_required
|
from flaschengeist.utils.decorators import login_required
|
||||||
from flaschengeist.utils.datetime import from_iso_format
|
from flaschengeist.utils.datetime import from_iso_format
|
||||||
from flaschengeist.controller import userController
|
from flaschengeist.controller import userController
|
||||||
|
|
||||||
from . import event_controller, permissions, EventPlugin
|
from . import event_controller, permissions, EventPlugin
|
||||||
from ...utils.HTTP import get_filter_args, no_content
|
from ...utils.HTTP import no_content
|
||||||
|
|
||||||
|
|
||||||
def dict_get(self, key, default=None, type=None):
|
def dict_get(self, key, default=None, type=None):
|
||||||
|
@ -190,12 +194,63 @@ def get_event(event_id, current_session):
|
||||||
|
|
||||||
@EventPlugin.blueprint.route("/events", methods=["GET"])
|
@EventPlugin.blueprint.route("/events", methods=["GET"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def get_events(current_session):
|
def get_filtered_events(current_session):
|
||||||
count, result = event_controller.get_events(
|
begin = request.args.get("from", type=from_iso_format)
|
||||||
*get_filter_args(),
|
end = request.args.get("to", type=from_iso_format)
|
||||||
with_backup=current_session.user_.has_permission(permissions.SEE_BACKUP),
|
limit = request.args.get("limit", type=int)
|
||||||
|
offset = request.args.get("offset", type=int)
|
||||||
|
descending = "descending" in request.args
|
||||||
|
if begin is None and end is None:
|
||||||
|
begin = datetime.now()
|
||||||
|
return jsonify(
|
||||||
|
event_controller.get_events(
|
||||||
|
start=begin,
|
||||||
|
end=end,
|
||||||
|
limit=limit,
|
||||||
|
offset=offset,
|
||||||
|
descending=descending,
|
||||||
|
with_backup=current_session.user_.has_permission(permissions.SEE_BACKUP),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return jsonify({"count": count, "result": result})
|
|
||||||
|
|
||||||
|
@EventPlugin.blueprint.route("/events/<int:year>/<int:month>", methods=["GET"])
|
||||||
|
@EventPlugin.blueprint.route("/events/<int:year>/<int:month>/<int:day>", methods=["GET"])
|
||||||
|
@login_required()
|
||||||
|
def get_events(current_session, year=datetime.now().year, month=datetime.now().month, day=None):
|
||||||
|
"""Get Event objects for specified date (or month or year),
|
||||||
|
if nothing set then events for current month are returned
|
||||||
|
|
||||||
|
Route: ``/events[/<year>/<month>[/<int:day>]]`` | Method: ``GET``
|
||||||
|
|
||||||
|
Args:
|
||||||
|
year (int, optional): year to query, defaults to current year
|
||||||
|
month (int, optional): month to query (if set), defaults to current month
|
||||||
|
day (int, optional): day to query events for (if set)
|
||||||
|
current_session: Session sent with Authorization Header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
JSON encoded list containing events found or HTTP-error
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
begin = datetime(year=year, month=month, day=1, tzinfo=timezone.utc)
|
||||||
|
if day:
|
||||||
|
begin += timedelta(days=day - 1)
|
||||||
|
end = begin + timedelta(days=1)
|
||||||
|
else:
|
||||||
|
if month == 12:
|
||||||
|
end = datetime(year=year + 1, month=1, day=1, tzinfo=timezone.utc)
|
||||||
|
else:
|
||||||
|
end = datetime(year=year, month=month + 1, day=1, tzinfo=timezone.utc)
|
||||||
|
|
||||||
|
events = event_controller.get_events(
|
||||||
|
begin,
|
||||||
|
end,
|
||||||
|
with_backup=current_session.user_.has_permission(permissions.SEE_BACKUP),
|
||||||
|
)
|
||||||
|
return jsonify(events)
|
||||||
|
except ValueError:
|
||||||
|
raise BadRequest("Invalid date given")
|
||||||
|
|
||||||
|
|
||||||
def _add_job(event, data):
|
def _add_job(event, data):
|
||||||
|
@ -394,13 +449,6 @@ def update_job(event_id, job_id, current_session: Session):
|
||||||
return jsonify(job)
|
return jsonify(job)
|
||||||
|
|
||||||
|
|
||||||
@EventPlugin.blueprint.route("/events/jobs", methods=["GET"])
|
|
||||||
@login_required()
|
|
||||||
def get_jobs(current_session: Session):
|
|
||||||
count, result = event_controller.get_jobs(current_session.user_, *get_filter_args())
|
|
||||||
return jsonify({"count": count, "result": result})
|
|
||||||
|
|
||||||
|
|
||||||
@EventPlugin.blueprint.route("/events/jobs/<int:job_id>/assign", methods=["POST"])
|
@EventPlugin.blueprint.route("/events/jobs/<int:job_id>/assign", methods=["POST"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def assign_job(job_id, current_session: Session):
|
def assign_job(job_id, current_session: Session):
|
||||||
|
|
|
@ -2,24 +2,6 @@ from http.client import NO_CONTENT, CREATED
|
||||||
|
|
||||||
from flask import make_response, jsonify
|
from flask import make_response, jsonify
|
||||||
|
|
||||||
from flaschengeist.utils.datetime import from_iso_format
|
|
||||||
|
|
||||||
|
|
||||||
def get_filter_args():
|
|
||||||
"""
|
|
||||||
Get filter parameter from request
|
|
||||||
returns: FROM, TO, LIMIT, OFFSET, DESCENDING
|
|
||||||
"""
|
|
||||||
from flask import request
|
|
||||||
|
|
||||||
return (
|
|
||||||
request.args.get("from", type=from_iso_format),
|
|
||||||
request.args.get("to", type=from_iso_format),
|
|
||||||
request.args.get("limit", type=int),
|
|
||||||
request.args.get("offset", type=int),
|
|
||||||
"descending" in request.args,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def no_content():
|
def no_content():
|
||||||
return make_response(jsonify(""), NO_CONTENT)
|
return make_response(jsonify(""), NO_CONTENT)
|
||||||
|
|
Loading…
Reference in New Issue