microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/fix-user-input-log-forging

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Libraries/Microsoft.Teams.Plugins/Microsoft.Teams.Plugins.AspNetCore.DevTools/DevToolsPlugin.cs

166lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4using System.Diagnostics.CodeAnalysis;
5using System.Reflection;
6using System.Text;
7
8using Microsoft.AspNetCore.Builder;
9using Microsoft.AspNetCore.Hosting.Server;
10using Microsoft.AspNetCore.Hosting.Server.Features;
11using Microsoft.AspNetCore.Http.Features;
12using Microsoft.Extensions.DependencyInjection;
13using Microsoft.Extensions.FileProviders;
14using Microsoft.Teams.Apps;
15using Microsoft.Teams.Apps.Events;
16using Microsoft.Teams.Apps.Plugins;
17using Microsoft.Teams.Common.Logging;
18using Microsoft.Teams.Common.Text;
19using Microsoft.Teams.Plugins.AspNetCore.DevTools.Extensions;
20using Microsoft.Teams.Plugins.AspNetCore.DevTools.Models;
21
22namespace Microsoft.Teams.Plugins.AspNetCore.DevTools;
23
24[Plugin]
25public class DevToolsPlugin : IAspNetCorePlugin
26{
27 [AllowNull]
28 [Dependency]
29 public ILogger Logger { get; set; }
30
31 [Dependency("AppId", optional: true)]
32 public string? AppId { get; set; }
33
34 [Dependency("AppName", optional: true)]
35 public string? AppName { get; set; }
36
37 public event EventFunction Events;
38
39 internal MetaData MetaData => new() { Id = AppId, Name = AppName, Pages = _pages };
40 internal readonly WebSocketCollection Sockets = [];
41
42 private readonly ISenderPlugin _sender;
43 private readonly IServiceProvider _services;
44 private readonly IList<Page> _pages = [];
45 private readonly TeamsDevToolsSettings _settings;
46
47 public DevToolsPlugin(AspNetCorePlugin sender, IServiceProvider provider)
48 {
49 _sender = sender;
50 _services = provider;
51 _settings = provider.GetRequiredService<TeamsDevToolsSettings>();
52 }
53
54 public IApplicationBuilder Configure(IApplicationBuilder builder)
55 {
56 builder.UseWebSockets(new WebSocketOptions()
57 {
58 AllowedOrigins = { "*" }
59 });
60
61 builder.UseStaticFiles(new StaticFileOptions()
62 {
63 FileProvider = new ManifestEmbeddedFileProvider(Assembly.GetExecutingAssembly(), "web"),
64 ServeUnknownFileTypes = true,
65 RequestPath = "/devtools"
66 });
67
68 builder.Use(async (context, next) =>
69 {
70 try
71 {
72 await next(context);
73 }
74 catch (Exception ex)
75 {
76 Logger.Error(ex, "http error");
77 throw new Exception(ex.Message, innerException: ex);
78 }
79 });
80
81 return builder;
82 }
83
84 public DevToolsPlugin AddPage(Page page)
85 {
86 _pages.Add(page);
87 Logger.Debug($"page '{page.Name}' added at '{page.Url}'");
88 return this;
89 }
90
91 public Task OnInit(App app, CancellationToken cancellationToken = default)
92 {
93 foreach (var page in _settings.Pages)
94 {
95 AddPage(page);
96 }
97
98 Logger.Warn(
99 new StringBuilder()
100 .Bold(
101 new StringBuilder()
102 .Yellow("⚠️ Devtools are not secure and should not be used production environments ⚠️")
103 .ToString()
104 )
105 );
106
107 return Task.CompletedTask;
108 }
109
110 public Task OnStart(App app, CancellationToken cancellationToken = default)
111 {
112 var server = _services.GetRequiredService<IServer>();
113 var addresses = server.Features.GetRequiredFeature<IServerAddressesFeature>().Addresses;
114
115 foreach (var address in addresses)
116 {
117 Logger.Info($"Available at {address}/devtools");
118 }
119
120 Logger.Debug("OnStart");
121 return Task.CompletedTask;
122 }
123
124 public Task OnError(App app, IPlugin plugin, ErrorEvent @event, CancellationToken cancellationToken = default)
125 {
126 Logger.Debug("OnError");
127 return Task.CompletedTask;
128 }
129
130 public async Task OnActivity(App app, ISenderPlugin sender, ActivityEvent @event, CancellationToken cancellationToken = default)
131 {
132 Logger.Debug("OnActivity");
133
134 await Sockets.Emit(
135 DevTools.Events.ActivityEvent.Received(
136 @event.Activity,
137 @event.Activity.Conversation
138 ),
139 cancellationToken
140 );
141 }
142
143 public async Task OnActivitySent(App app, ISenderPlugin sender, ActivitySentEvent @event, CancellationToken cancellationToken = default)
144 {
145 Logger.Debug("OnActivitySent");
146
147 await Sockets.Emit(
148 DevTools.Events.ActivityEvent.Sent(
149 @event.Activity,
150 @event.Activity.Conversation
151 ),
152 cancellationToken
153 );
154 }
155
156 public Task OnActivityResponse(App app, ISenderPlugin sender, ActivityResponseEvent @event, CancellationToken cancellationToken = default)
157 {
158 Logger.Debug("OnActivityResponse");
159 return Task.CompletedTask;
160 }
161
162 public Task<Response> Do(ActivityEvent @event, CancellationToken cancellationToken = default)
163 {
164 return _sender.Do(@event, cancellationToken);
165 }
166}