using OwnChar.Api.Packets; using OwnChar.Api.Packets.General; using OwnChar.Api.Packets.Groups; using OwnChar.Api.Updates; using OwnChar.Data; using OwnChar.Data.Model.Client; using OwnChar.Server.Data.Model; using OwnChar.Server.Extensions; namespace OwnChar.Server.Api.Endpoint.Implementations; internal class GroupsApi(IServer server) : IApiEndpoint { public void Initialize(IApiBuilder builder) { builder.Map("/groups/get/byid", GetById); builder.Map("/groups/get", Get); builder.Map("/groups/create", Create); builder.Map("/groups/update", Update); builder.Map("/groups/delete", Delete); builder.Map("/groups/members/get", GetMembers); builder.Map("/groups/members/add", AddMembers); builder.Map("/groups/members/update", UpdateMember); builder.Map("/groups/members/remove", RemoveMembers); } private IResult GetById(GetSinlgeObjectRequest request) { if (!server.CheckLogin(request, UserType.Guest, out UserAccountDb? user)) return TypedResults.Unauthorized(); if (server.Data?.Set().FirstOrDefault(n => n.Id == request.ObjectId && n.Members.Any(m => m.User != null && m.User.Id == user.Id)) is not GroupDb group) return TypedResults.Ok(new GetSingleObjectResponse(null).With(OwnCharResponseError.NotFound)); return TypedResults.Ok(new GetSingleObjectResponse(group.ToClient())); } private IResult Get(GetGroupsRequest request) { if (!server.CheckLogin(request, UserType.Guest, out UserAccountDb? user)) return TypedResults.Unauthorized(); IQueryable groups; if (request.UseProfileId && server.Data!.Set().FirstOrDefault(p => p.Id == request.ProfileId) is UserProfileDb profile) groups = server.Data!.Set().Where(group => group.Members.Any(m => m.User != null && m.User.Id == profile.Id)); else if (request.IncludeNonPublic && user.Is(UserType.Admin)) groups = server.Data!.Set(); else groups = Array.Empty().AsQueryable(); // Currently not supported. return TypedResults.Ok(new GetGroupsResponse([.. groups.Select(g => g.ToClient())])); } private IResult Create(CreateGroupRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user)) return TypedResults.Unauthorized(); var group = new GroupDb(); if (!string.IsNullOrWhiteSpace(request.Name)) group.Name = request.Name; group.Members.Add(new() { User = user.Profile, Level = MemberLevel.Owner, }); server.Data!.Update(group); server.Data.SaveChanges(); return TypedResults.Ok(new CreateGroupResponse(group.ToClient())); } private IResult Update(UpdateRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user) || server.Data?.Set().FirstOrDefault(n => n.Id == request.Update.Id) is not GroupDb group || !group.Members.Any(m => m.Id == user.Profile!.Id && m.Level >= MemberLevel.Admin || user.IsNot(UserType.Admin))) return TypedResults.Unauthorized(); if (request.Update is not GroupUpdate update) return TypedResults.Ok(new UpdateResponse().With(OwnCharResponseError.Default)); group.Name = update.Name; group.Fandom = update.Fandom; server.Data.Update(group); server.Data.SaveChanges(); return TypedResults.Ok(new UpdateResponse()); } private IResult Delete(DeleteObjectRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user) || server.Data?.Set().FirstOrDefault(n => n.Id == request.ObjectId) is not GroupDb group || !group.Members.Any(m => m.Id == user.Profile!.Id && m.Level >= MemberLevel.Owner) || user.IsNot(UserType.Admin)) return TypedResults.Unauthorized(); server.Data.Remove(group); server.Data.SaveChanges(); return TypedResults.Ok(new DeleteObjectResponse()); } private IResult GetMembers(GetGroupMembersRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user) || server.Data?.Set().FirstOrDefault(n => n.Id == request.GroupId) is not GroupDb group || !group.Members.Any(m => m.Id == user.Profile!.Id && m.Level >= MemberLevel.Member) || user.IsNot(UserType.Admin)) return TypedResults.Unauthorized(); var members = group.Members.Select(n => n.ToClient()); return TypedResults.Ok(new GetGroupMembersResponse(members.ToList())); } private IResult AddMembers(GroupMemberAddRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user) || server.Data?.Set().FirstOrDefault(n => n.Id == request.GroupId) is not GroupDb group || !group.Members.Any(m => m.Id == user.Profile!.Id && m.Level >= MemberLevel.Admin) || user.IsNot(UserType.Admin)) return TypedResults.Unauthorized(); var addedMembers = new List(); foreach (var kvp in request.Members) { if (group.Members.FirstOrDefault(m => m.User != null && m.User.Id == kvp.Key) is not MemberEntryDb member && server.Data.Set().FirstOrDefault(u => u.Id == kvp.Key) is UserProfileDb mu) { member = new() { User = mu, Level = kvp.Value, }; server.Data.Update(member); server.Data.Update(group); server.Data.SaveChanges(); } } return TypedResults.Ok(new GroupMemberAddResponse(addedMembers.Select(m => m.ToClient()).ToList())); } private IResult UpdateMember(UpdateRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user) || server.Data?.Set().FirstOrDefault(n => n.Id == request.Update.Id) is not GroupDb group || group.Members.FirstOrDefault(m => m.Id == request.Update.Id) is not MemberEntryDb member || !group.Members.Any(m => m.Id == user.Profile!.Id && m.Level >= MemberLevel.Admin || user.IsNot(UserType.Admin))) return TypedResults.Unauthorized(); if (request.Update is not MemberUpdate update) return TypedResults.Ok(new UpdateResponse().With(OwnCharResponseError.Default)); member.Level = update.Level; server.Data.Update(member); server.Data.SaveChanges(); return TypedResults.Ok(new UpdateResponse()); } private IResult RemoveMembers(DeleteObjectRequest request) { if (!server.CheckLogin(request, UserType.User, out UserAccountDb? user) || server.Data?.Set().FirstOrDefault(m => m.Id == request.ObjectId) is not MemberEntryDb member || server.Data?.Set().FirstOrDefault(n => n.Members.Contains(member)) is not GroupDb group || !group.Members.Any(m => m.Id == user.Profile!.Id && m.Level >= MemberLevel.Admin || user.IsNot(UserType.Admin))) return TypedResults.Unauthorized(); group.Members.Remove(member); server.Data.Remove(member); server.Data.Update(group); server.Data.SaveChanges(); return TypedResults.Ok(new DeleteObjectResponse()); } }