public async Task <IActionResult> PostSwitch([FromBody] PostSwitchParams param) { if (param.Members.Distinct().Count() != param.Members.Count) { return(BadRequest("Duplicate members in member list.")); } await using var conn = await _db.Obtain(); // We get the current switch, if it exists var latestSwitch = await _repo.GetLatestSwitch(User.CurrentSystem()); if (latestSwitch != null) { var latestSwitchMembers = _repo.GetSwitchMembers(conn, latestSwitch.Id); // Bail if this switch is identical to the latest one if (await latestSwitchMembers.Select(m => m.Hid).SequenceEqualAsync(param.Members.ToAsyncEnumerable())) { return(BadRequest("New members identical to existing fronters.")); } } // Resolve member objects for all given IDs var membersList = (await conn.QueryAsync <PKMember>("select * from members where hid = any(@Hids)", new { Hids = param.Members })).ToList(); foreach (var member in membersList) { if (member.System != User.CurrentSystem()) { return(BadRequest($"Cannot switch to member '{member.Hid}' not in system.")); } } // membersList is in DB order, and we want it in actual input order // so we go through a dict and map the original input appropriately var membersDict = membersList.ToDictionary(m => m.Hid); var membersInOrder = new List <PKMember>(); // We do this without .Select() since we want to have the early return bail if it doesn't find the member foreach (var givenMemberId in param.Members) { if (!membersDict.TryGetValue(givenMemberId, out var member)) { return(BadRequest($"Member '{givenMemberId}' not found.")); } membersInOrder.Add(member); } // Finally, log the switch (yay!) await _repo.AddSwitch(conn, User.CurrentSystem(), membersInOrder.Select(m => m.Id).ToList()); return(NoContent()); }
public async Task <IActionResult> SwitchCreate(string systemRef, [FromBody] PostSwitchParams data) { var system = await ResolveSystem(systemRef); if (system == null) { throw Errors.SystemNotFound; } if (ContextFor(system) != LookupContext.ByOwner) { throw Errors.GenericMissingPermissions; } if (data.Members.Distinct().Count() != data.Members.Count) { throw Errors.DuplicateMembersInList; } if (data.Timestamp != null && await _repo.GetSwitches(system.Id).Select(x => x.Timestamp) .ContainsAsync(data.Timestamp.Value)) { throw Errors.SameSwitchTimestampError; } var members = new List <PKMember>(); foreach (var memberRef in data.Members) { var member = await ResolveMember(memberRef); if (member == null) { throw Errors.MemberNotFoundWithRef(memberRef); } if (member.System != system.Id) { throw Errors.NotOwnMemberErrorWithRef(memberRef); } members.Add(member); } // We get the current switch, if it exists var latestSwitch = await _repo.GetLatestSwitch(system.Id); if (latestSwitch != null && (data.Timestamp == null || data.Timestamp > latestSwitch.Timestamp)) { var latestSwitchMembers = _db.Execute(conn => _repo.GetSwitchMembers(conn, latestSwitch.Id)); // Bail if this switch is identical to the latest one if (await latestSwitchMembers.Select(m => m.Hid) .SequenceEqualAsync(members.Select(m => m.Hid).ToAsyncEnumerable())) { throw Errors.SameSwitchMembersError; } } var newSwitch = await _db.Execute(conn => _repo.AddSwitch(conn, system.Id, members.Select(m => m.Id).ToList())); if (data.Timestamp != null) { await _repo.MoveSwitch(newSwitch.Id, data.Timestamp.Value); } return(Ok(new FrontersReturnNew { Uuid = newSwitch.Uuid, Timestamp = data.Timestamp != null ? data.Timestamp.Value : newSwitch.Timestamp, Members = members.Select(x => x.ToJson(LookupContext.ByOwner, v: APIVersion.V2)), })); }