microsoft/teams.net

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
mehak/logger

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

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