microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
aamirj/StackOverflowTest

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

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