microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/core

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

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