public IActionResult AddReservation([FromServices] IEmailService emailservice, DateTime StartTime, DateTime EndTime, string Description, int RoomID, bool Force = false) { if (StartTime == null || EndTime == null || Description == null) { return(BadRequest("Fields missing")); } if (StartTime > EndTime) { return(BadRequest("StartTime is before EndTime")); } var rooms = _context.Rooms.Where(x => x.Id == RoomID); if (!rooms.Any()) { return(BadRequest("Room does not exist")); } var room = rooms.First(); var Owner = Models.User.FromClaims(User.Claims, _context); lock (_context.ReservationLock) //lock all intersection checking and reservation writing logic to prevent changes to the database during the checking phase { var intersections = FindIntersections(StartTime, EndTime, room); if (intersections.Count() == 0) //No intersections with other reservations, add it { return(Ok(createreservation(StartTime, EndTime, Description, Owner, room).ToString())); } if (!intersections.All(x => x.IsMutable == true)) //intersection with an immutable reservation { return(new ObjectResult("Conflict: Overlaps with an immutable reservation.") { StatusCode = 409 }); } if (!Force) { return(new ObjectResult("Conflict: There is overlap with existing reservations, please set 'Force' to true in your request if you wish to forcibly insert it.") { StatusCode = 409 }); } if (Authorization.AIsBOrHigher(Owner.Role, Role.ServiceDesk)) //service desk or higher can always forcibly add reservations { return(Ok(OverrideAddReservation(emailservice, intersections, StartTime, EndTime, Description, Owner, room).ToString())); } var _intersectionowners = (from x in intersections select x.Participants).SelectMany(x => x).Where(x => x.IsOwner).Select(x => x.UserID); var _intersectionownerLevels = (from x in _intersectionowners select _context.Users.Where(z => z.Id == x).First().Role); if (!_intersectionownerLevels.All(x => Authorization.AIsHigherThanB(Owner.Role, x))) //intersections with reservation from people of higher or equal level { return(new ObjectResult("Conflict: Overlaps with a reservation with owner of equal or higher level.") { StatusCode = 409 }); } return(Ok(OverrideAddReservation(emailservice, intersections, StartTime, EndTime, Description, Owner, room).ToString())); //intersections with reservations from people with lower level } }
public IActionResult ChangeReservation(int ReservationID, DateTime?StartTime, DateTime?EndTime, string Description, int?RoomID, bool?isactive, bool Force = false) { User actor = Models.User.FromClaims(User.Claims); Room room = null; if (RoomID.HasValue) { room = _context.Rooms.Find(RoomID.Value); if (room == null) { Response.StatusCode = 400; return(Content("RoomID could not be found")); } } lock (ReservationLock) { var _reservation = _context.Reservations.Where(x => x.Id == ReservationID).Include(x => x.Participants); Reservation reservation = null; if (_reservation.Count() != 0) { Response.StatusCode = 400; return(Content("Reservation could not be found")); } reservation = _reservation.First(); if (reservation.Participants.Where(x => x.IsOwner).Where(x => x.UserID == actor.Id).Count() != 1) { if (!Authorization.AIsBOrHigher(actor.Role, Role.ServiceDesk)) { Response.StatusCode = 401; return(Content("You are not an owner of this reservation, nor are you a service desk employee or higher.")); } } var reservationchange = reservation.GenerateChangeCopy(actor); DateTime start; if (StartTime.HasValue) { start = StartTime.Value; } else { start = reservation.StartDate; } DateTime end; if (EndTime.HasValue) { end = EndTime.Value; } else { end = reservation.EndDate; } if (start > end) { Response.StatusCode = 400; return(Content("Startdate cannot come before end date")); } var intersections = FindIntersections(start, end); if (intersections.Count() <= 1) { return(_ChangeReservation(isactive, reservation, start, end, room, Description, reservationchange)); } else { intersections = intersections.Where(x => x.Id != reservation.Id); //remove self if (!Force) { Response.StatusCode = 400; return(Content("There is overlap with existing reservations, please set 'Force' to true in your request if you wish to forcibly insert it.")); } if (Authorization.AIsBOrHigher(actor.Role, Role.ServiceDesk)) //service desk or higher can always forcibly change reservations { return(_ForceChangeReservation(isactive, reservation, start, end, room, Description, reservationchange, actor, intersections)); } var _intersectionowners = (from x in intersections select x.Participants).SelectMany(x => x).Where(x => x.IsOwner).Select(x => x.UserID); var _intersectionownerLevels = (from x in _intersectionowners select _context.Users.Find(x).Role); if (!_intersectionownerLevels.All(x => Authorization.AIsHigherThanB(actor.Role, x))) //intersections with reservation from people of higher or equal level { Response.StatusCode = 400; return(Content("Overlaps with a reservation with owner of equal or higher level.")); } return(_ForceChangeReservation(isactive, reservation, start, end, room, Description, reservationchange, actor, intersections)); //intersections with reservations from people with lower level } } }
public IActionResult ChangeReservation([FromServices] IEmailService emailservice, int ReservationID, DateTime?StartTime, DateTime?EndTime, string Description, int?RoomID, bool?isactive, bool Force = false) { User actor = Models.User.FromClaims(User.Claims, _context); Room room = null; if (RoomID.HasValue) { var rooms = _context.Rooms.Where(x => x.Id == RoomID.Value); if (!rooms.Any()) { return(BadRequest("RoomID could not be found")); } room = rooms.First(); } lock (_context.ReservationLock) { var _reservation = _context.Reservations.Where(x => x.Id == ReservationID).Include(x => x.Participants).Include(x => x.Room); Reservation reservation = null; if (_reservation.Count() == 0) { return(BadRequest("Reservation could not be found")); } reservation = _reservation.First(); if (room == null) { room = reservation.Room; } if (reservation.Participants.Where(x => x.IsOwner).Where(x => x.UserID == actor.Id).Count() != 1) { if (!Authorization.AIsBOrHigher(actor.Role, Role.ServiceDesk)) { return(Unauthorized()); } } var reservationchange = reservation.GenerateChangeCopy(actor); DateTime start; if (StartTime.HasValue) { start = StartTime.Value; } else { start = reservation.StartDate; } DateTime end; if (EndTime.HasValue) { end = EndTime.Value; } else { end = reservation.EndDate; } if (start > end) { return(BadRequest("Startdate cannot come before end date")); } var intersections = FindIntersections(start, end, room); if (intersections.Count() <= 0) { return(_ChangeReservation(emailservice, actor, isactive, reservation, start, end, room, Description, reservationchange)); } else if (intersections.Count() == 1 && intersections.First() == reservation) { return(_ChangeReservation(emailservice, actor, isactive, reservation, start, end, room, Description, reservationchange)); } else { intersections = intersections.Where(x => x.Id != reservation.Id); //remove self if (!Force) { return(new ObjectResult("Conflict: There is overlap with existing reservations, please set 'Force' to true in your request if you wish to forcibly insert it.") { StatusCode = 409 }); } if (Authorization.AIsBOrHigher(actor.Role, Role.ServiceDesk)) //service desk or higher can always forcibly change reservations { return(_ForceChangeReservation(emailservice, isactive, reservation, start, end, room, Description, reservationchange, actor, intersections)); } var isOwnerOfIntersections = intersections.Select(x => x.Participants.Select(z => z.UserID).Contains(actor.Id)).All(x => x); var _intersectionowners = (from x in intersections select x.Participants).SelectMany(x => x).Where(x => x.IsOwner).Select(x => x.UserID); var _intersectionownerLevels = (from x in _intersectionowners select _context.Users.Where(z => z.Id == x).First().Role); if (isOwnerOfIntersections || _intersectionownerLevels.All(x => Authorization.AIsHigherThanB(actor.Role, x))) //intersections with reservation from people of higher or equal level { return(_ForceChangeReservation(emailservice, isactive, reservation, start, end, room, Description, reservationchange, actor, intersections)); //intersections with reservations from people with lower level } return(Unauthorized()); } } }