summary refs log tree commit diff
path: root/ModAS.Server/Controllers/Debug/DebugController.cs
blob: 7bec3e5f6abc0545c1c96a2d031785e886f521cf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System.Collections.Frozen;
using ArcaneLibs.Extensions;
using Elastic.Apm;
using Elastic.Apm.Api;
using LibMatrix.Homeservers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ModAS.Server.Attributes;
using ModAS.Server.Services;
using MxApiExtensions.Services;

namespace ModAS.Server.Controllers.Debug;

/// <summary>
///   Provides debugging endpoints.
/// </summary>
/// <param name="config"><inheritdoc cref="ModASConfiguration"/></param>
/// <param name="authHsProvider"><inheritdoc cref="UserProviderService"/></param>
/// <param name="roomContextService"><inheritdoc cref="RoomContextService"/></param>
[ApiController]
[UserAuth(AnyRoles = AuthRoles.Developer | AuthRoles.Administrator)]
public class DebugController(ModASConfiguration config, UserProviderService authHsProvider, RoomContextService roomContextService) : ControllerBase {
    /// <summary>
    ///  Returns a JSON object containing the request and response headers.
    /// </summary>
    /// <returns>JSON object with request and partial response headers.</returns>
    [HttpGet("/_matrix/_modas/debug")]
    public IActionResult Index() {
        return Ok(new {
            Request = Request.Headers,
            Response = Response.Headers
        });
    }

    /// <summary>
    ///  Returns a JSON object containing the configuration.
    /// </summary>
    /// <returns></returns>
    [HttpGet("/_matrix/_modas/debug/config")]
    public IActionResult Config() {
        return Ok(config);
    }

    [HttpGet("/_matrix/_modas/debug/known_users")]
    public IActionResult KnownUsers() {
        return Ok(authHsProvider.KnownUsers.Keys);
    }

    [HttpGet("/_matrix/_modas/debug/test_locate_users")]
    public async IAsyncEnumerable<string> TestLocateUsers([FromQuery] string startUser) {
        List<AuthenticatedHomeserverGeneric> foundUsers = (await authHsProvider.GetValidUsers()).Select(x => x.Value).ToList();
        if (!foundUsers.Any(x => x.WhoAmI.UserId == startUser)) {
            foundUsers.Add(await authHsProvider.GetImpersonatedHomeserver(startUser));
        }

        List<string> processedRooms = [], processedUsers = [];
        var foundNew = true;
        while (foundNew) {
            var span1 = currentTransaction.StartSpan("iterateUsers", ApiConstants.TypeApp);
            foundNew = false;
            var usersToProcess = foundUsers.Where(x => !processedUsers.Any(y => x.WhoAmI.UserId == y)).ToFrozenSet();
            Console.WriteLine($"Got {usersToProcess.Count} users: {string.Join(", ", usersToProcess)}");

            var rooms = usersToProcess.Select(async x => await x.GetJoinedRooms());
            var roomLists = rooms.ToAsyncEnumerable();
            await foreach (var roomList in roomLists) {
                if (roomList is null) continue;
                foreach (var room in roomList) {
                    if (processedRooms.Contains(room.RoomId)) continue;
                    processedRooms.Add(room.RoomId);
                    var roomMembers = await room.GetMembersListAsync(false);
                    foreach (var roomMember in roomMembers) {
                        if (roomMember.StateKey.EndsWith(':' + config.ServerName) && !foundUsers.Any(x => x.WhoAmI.UserId == roomMember.StateKey)) {
                            foundUsers.Add(await authHsProvider.GetImpersonatedHomeserver(roomMember.StateKey));
                            foundNew = true;
                            yield return roomMember.StateKey;
                        }
                    }
                }
            }

            // await foreach (var task in tasks) {
            //     if (task is null) continue;
            //     foreach (var user in task) {
            //         if (foundUsers.Contains(user)) continue;
            //         foundUsers.Add(user);
            //         foundNew = true;
            //         yield return user;
            //     }
            // }

            span1.End();
        }
    }

    [HttpGet("/_matrix/_modas/debug/room_contexts")]
    public IActionResult RoomContexts() {
        return Ok(roomContextService.RoomContexts.Values);
    }

    [HttpGet("/_matrix/_modas/debug/room_contexts/{roomId}")]
    public async Task<IActionResult> RoomContext(string roomId) {
        var roomContext = await roomContextService.GetRoomContext(roomId);
        if (roomContext is null) return NotFound("Room not found");
        return Ok(roomContext);
    }

    [HttpGet("/_matrix/_modas/debug/room_contexts/by_user/{userId}")]
    public async IAsyncEnumerable<RoomContextService.RoomContext> RoomContextByUser(string userId) {
        var user = await authHsProvider.GetImpersonatedHomeserver(userId);
        var rooms = await user.GetJoinedRooms();
        var contexts = rooms.Select(x => roomContextService.GetRoomContext(x.RoomId)).ToAsyncEnumerable();
        await foreach (var context in contexts) {
            if (context is null) continue;
            yield return context;
        }
    }

    private static ITransaction currentTransaction => Agent.Tracer.CurrentTransaction;
}