microsoft/teams.net

Public

mirrored from https://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
feature/launch-settings-samples

Branches

Tags

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

Clone

HTTPS

Download ZIP

Libraries/Microsoft.Teams.Plugins/Microsoft.Teams.Plugins.AspNetCore/Extensions/ApplicationBuilder.Functions.cs

198lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4using System.IdentityModel.Tokens.Jwt;
5
6using Microsoft.AspNetCore.Builder;
7using Microsoft.AspNetCore.Http;
8using Microsoft.AspNetCore.Routing;
9using Microsoft.Extensions.DependencyInjection;
10using Microsoft.Teams.Apps;
11
12namespace Microsoft.Teams.Plugins.AspNetCore.Extensions;
13
14public static partial class ApplicationBuilderExtensions
15{
16 /// <summary>
17 /// add/update a function that can be called remotely
18 /// </summary>
19 /// <param name="name">The unique function name</param>
20 /// <param name="handler">The callback to handle the function</param>
21 public static IApplicationBuilder AddFunction(this IApplicationBuilder builder, string name, Action<IFunctionContext<object?>> handler)
22 {
23 return builder.AddFunction<object?>(name, context =>
24 {
25 handler(context);
26 return Task.FromResult<object?>(null);
27 });
28 }
29
30 /// <summary>
31 /// add/update a function that can be called remotely
32 /// </summary>
33 /// <typeparam name="TBody">The body (data) type</typeparam>
34 /// <param name="name">The unique function name</param>
35 /// <param name="handler">The callback to handle the function</param>
36 public static IApplicationBuilder AddFunction<TBody>(this IApplicationBuilder builder, string name, Action<IFunctionContext<TBody>> handler)
37 {
38 return builder.AddFunction<TBody>(name, context =>
39 {
40 handler(context);
41 return Task.FromResult<object?>(null);
42 });
43 }
44
45 /// <summary>
46 /// add/update a function that can be called remotely
47 /// </summary>
48 /// <param name="name">The unique function name</param>
49 /// <param name="handler">The callback to handle the function</param>
50 public static IApplicationBuilder AddFunction(this IApplicationBuilder builder, string name, Func<IFunctionContext<object?>, Task> handler)
51 {
52 return builder.AddFunction<object?>(name, context =>
53 {
54 handler(context).ConfigureAwait(false).GetAwaiter();
55 return Task.FromResult<object?>(null);
56 });
57 }
58
59 /// <summary>
60 /// add/update a function that can be called remotely
61 /// </summary>
62 /// <typeparam name="TBody">The body (data) type</typeparam>
63 /// <param name="name">The unique function name</param>
64 /// <param name="handler">The callback to handle the function</param>
65 public static IApplicationBuilder AddFunction<TBody>(this IApplicationBuilder builder, string name, Func<IFunctionContext<TBody>, Task> handler)
66 {
67 return builder.AddFunction<TBody>(name, context =>
68 {
69 handler(context).ConfigureAwait(false).GetAwaiter();
70 return Task.FromResult<object?>(null);
71 });
72 }
73
74 /// <summary>
75 /// add/update a function that can be called remotely
76 /// </summary>
77 /// <param name="name">The unique function name</param>
78 /// <param name="handler">The callback to handle the function</param>
79 public static IApplicationBuilder AddFunction(this IApplicationBuilder builder, string name, Func<IFunctionContext<object?>, object?> handler)
80 {
81 return builder.AddFunction<object?>(name, context => handler(context));
82 }
83
84 /// <summary>
85 /// add/update a function that can be called remotely
86 /// </summary>
87 /// <param name="name">The unique function name</param>
88 /// <param name="handler">The callback to handle the function</param>
89 public static IApplicationBuilder AddFunction(this IApplicationBuilder builder, string name, Func<IFunctionContext<object?>, Task<object?>> handler)
90 {
91 return builder.AddFunction<object?>(name, context => handler(context));
92 }
93
94 /// <summary>
95 /// add/update a function that can be called remotely
96 /// </summary>
97 /// <typeparam name="TBody">The body (data) type</typeparam>
98 /// <param name="name">The unique function name</param>
99 /// <param name="handler">The callback to handle the function</param>
100 public static IApplicationBuilder AddFunction<TBody>(this IApplicationBuilder builder, string name, Func<IFunctionContext<TBody>, Task<object?>> handler)
101 {
102 return builder.AddFunction<TBody>(name, context => handler(context).ConfigureAwait(false).GetAwaiter().GetResult());
103 }
104
105 /// <summary>
106 /// add/update a function that can be called remotely
107 /// </summary>
108 /// <typeparam name="TBody">The body (data) type</typeparam>
109 /// <param name="name">The unique function name</param>
110 /// <param name="handler">The callback to handle the function</param>
111 public static IApplicationBuilder AddFunction<TBody>(this IApplicationBuilder builder, string name, Func<IFunctionContext<TBody>, object?> handler)
112 {
113 builder.UseEndpoints(endpoints =>
114 {
115 endpoints.MapPost($"/api/functions/{name}", async context =>
116 {
117 context.Request.EnableBuffering();
118 var app = context.RequestServices.GetRequiredService<App>();
119 var log = app.Logger.Child("functions").Child(name);
120
121 if (context.Request.Headers.Authorization.First() is null)
122 {
123 await Results.Unauthorized().ExecuteAsync(context);
124 return;
125 }
126
127 if (!context.Request.Headers.TryGetValue("X-Teams-App-Session-Id", out var appSessionId))
128 {
129 await Results.Unauthorized().ExecuteAsync(context);
130 return;
131 }
132
133 if (!context.Request.Headers.TryGetValue("X-Teams-Page-Id", out var pageId))
134 {
135 await Results.Unauthorized().ExecuteAsync(context);
136 return;
137 }
138
139 var token = new JwtSecurityTokenHandler().ReadJwtToken(
140 context.Request.Headers.Authorization
141 .FirstOrDefault()?
142 .Replace("bearer ", string.Empty)
143 .Replace("Bearer ", string.Empty)
144 );
145
146 var ctx = new FunctionContext<TBody>(app)
147 {
148 Api = new(app.Api),
149 Log = log,
150 AppSessionId = appSessionId,
151 TenantId = token.Claims.First(c => c.Type == "tid").Value,
152 UserId = token.Claims.First(c => c.Type == "oid").Value,
153 UserName = token.Claims.First(c => c.Type == "name").Value,
154 PageId = pageId,
155 AuthToken = token.ToString(),
156 Data = await context.Request.ReadFromJsonAsync<TBody>(),
157 };
158
159 if (context.Request.Headers.TryGetValue("X-Teams-Channel-Id", out var channelId))
160 {
161 ctx.ChannelId = channelId;
162 }
163
164 if (context.Request.Headers.TryGetValue("X-Teams-Chat-Id", out var chatId))
165 {
166 ctx.ChatId = chatId;
167 }
168
169 if (context.Request.Headers.TryGetValue("X-Teams-Meeting-Id", out var meetingId))
170 {
171 ctx.MeetingId = meetingId;
172 }
173
174 if (context.Request.Headers.TryGetValue("X-Teams-Message-Id", out var messageId))
175 {
176 ctx.MessageId = messageId;
177 }
178
179 if (context.Request.Headers.TryGetValue("X-Teams-Sub-Page-Id", out var subPageId))
180 {
181 ctx.SubPageId = subPageId;
182 }
183
184 if (context.Request.Headers.TryGetValue("X-Teams-Team-Id", out var teamId))
185 {
186 ctx.TeamId = teamId;
187 }
188
189 log.Debug(ctx.Data?.ToString());
190 var res = handler(ctx);
191 log.Debug(res?.ToString());
192 await Results.Json(res).ExecuteAsync(context);
193 });
194 });
195
196 return builder;
197 }
198}