BizUsersController.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. using Azure.Cosmos;
  2. using Azure.Storage.Sas;
  3. using DocumentFormat.OpenXml.Office2010.Excel;
  4. using DocumentFormat.OpenXml.Wordprocessing;
  5. using Microsoft.AspNetCore.Authorization;
  6. using Microsoft.AspNetCore.Http;
  7. using Microsoft.AspNetCore.Mvc;
  8. using Microsoft.Extensions.Configuration;
  9. using Microsoft.Extensions.Options;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Net;
  13. using System.Net.Http;
  14. using System.Security.Policy;
  15. using System.Text;
  16. using System.Text.Json;
  17. using System.Threading.Tasks;
  18. using TEAMModelOS.Filter;
  19. using TEAMModelOS.Models;
  20. using TEAMModelOS.SDK;
  21. using TEAMModelOS.SDK.Context.BI;
  22. using TEAMModelOS.SDK.Context.Constant;
  23. using TEAMModelOS.SDK.DI;
  24. using TEAMModelOS.SDK.Extension;
  25. using TEAMModelOS.SDK.Models;
  26. using TEAMModelOS.SDK.Models.Cosmos.BI.BINormal;
  27. using TEAMModelOS.SDK.Models.Service;
  28. using TEAMModelOS.SDK.Models.Table;
  29. namespace TEAMModelOS.Controllers
  30. {
  31. [Route("biz")]
  32. [ApiController]
  33. public class BizUsersController : ControllerBase
  34. {
  35. private readonly IConfiguration _configuration;
  36. //数据容器
  37. private readonly AzureCosmosFactory _azureCosmos;
  38. //文件容器
  39. private readonly AzureStorageFactory _azureStorage;
  40. //钉钉提示信息
  41. private readonly DingDing _dingDing;
  42. private readonly Option _option;
  43. //隐式登录
  44. private readonly CoreAPIHttpService _coreAPIHttpService;
  45. private readonly IHttpClientFactory _httpClient;
  46. public BizUsersController(IHttpClientFactory httpClient, IConfiguration configuration, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, CoreAPIHttpService coreAPIHttpService)
  47. {
  48. _configuration = configuration;
  49. _azureCosmos = azureCosmos;
  50. _azureStorage = azureStorage;
  51. _dingDing = dingDing;
  52. _option = option?.Value;
  53. _coreAPIHttpService = coreAPIHttpService;
  54. _httpClient = httpClient;
  55. }
  56. /// <summary>
  57. /// 登录 第三方用户数据在CosmosDB
  58. /// </summary>
  59. /// <param name="jsonElement"></param>
  60. /// <returns></returns>
  61. [ProducesDefaultResponseType]
  62. [HttpPost("get-loginuser")]
  63. public async Task<IActionResult> GetBizUserLogin(JsonElement jsonElement)
  64. {
  65. try
  66. {
  67. jsonElement.TryGetProperty("mobile", out JsonElement mobile);
  68. jsonElement.TryGetProperty("mail", out JsonElement mail);
  69. if (!jsonElement.TryGetProperty("pwd", out JsonElement password)) return BadRequest();
  70. var cosmosClient = _azureCosmos.GetCosmosClient();
  71. var tableClient = _azureStorage.GetCloudTableClient();
  72. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  73. string loginSql = null;
  74. if (!string.IsNullOrEmpty($"{mobile}"))
  75. loginSql = $"select value(c) from c where c.mobile ={mobile}";
  76. else if (!string.IsNullOrEmpty($"{mail}"))
  77. loginSql = $"select value(c) from c where c.mail ={mail}";
  78. else return Ok(new { state = RespondCode.ParamsError, msg = "手机号/和邮箱为空" });
  79. List<BizUsers> bizUsers = new();
  80. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BizUsers>(queryText: loginSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
  81. {
  82. bizUsers.Add(item);
  83. }
  84. BusinessUsers businessUsers = new(); string openid_token = null;
  85. if (bizUsers.Count > 0)
  86. {
  87. foreach (var item in bizUsers)
  88. {
  89. var hashedPw = Utils.HashedPassword(password.ToString(), item.salt.ToString());
  90. if (hashedPw.Equals(item.pwd))
  91. {
  92. //businessUsers = item;
  93. businessUsers = new()
  94. {
  95. id = item.id,
  96. code = item.code,
  97. name = item.name,
  98. picture = item.picture,
  99. mobile = item.mobile,
  100. mail = item.mail,
  101. relation = item.relation,
  102. };
  103. //string id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, bizUser.RowKey?.ToString(), bizUser.name?.ToString(), bizUser.picture?.ToString(), _option.JwtSecretKey, scope: "company", webSite: Website, expire: 3);
  104. openid_token = JwtAuthExtension.CreateBizLoginAuthToken(_option.HostName, businessUsers.id?.ToString(), businessUsers.name?.ToString(), businessUsers.picture?.ToString(), $"{_option.Location}-Open", _option.JwtSecretKey, expire: 3);
  105. await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "tabledd-update", $"{businessUsers.name}【{businessUsers.id}】登录开放平台", _dingDing, tid: businessUsers.id, tname: businessUsers.name, twebsite: "Open", httpContext: HttpContext);
  106. };
  107. }
  108. }
  109. else return Ok(new { state = RespondCode.NotFound, msg = "未找到该用户!" });
  110. int timezone = 8;
  111. if (HttpContext.Request.Headers.TryGetValue("Time-Zone", out var Time_Zone) && int.TryParse(Time_Zone, out int tz))
  112. {
  113. timezone=tz;
  114. }
  115. if (businessUsers.id != null)
  116. {
  117. var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, businessUsers.id, businessUsers.name, businessUsers.picture, _option.JwtSecretKey, scope: "business", Website: "IES", timezone: timezone, roles: new[] { "business" }, expire: 1);
  118. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  119. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  120. var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, _option.Location.Replace("-Dep", "").Replace("-Test", ""));
  121. return Ok(new { state = RespondCode.Ok, openid_token, auth_token, token = new { access_token = token.AccessToken, expires_in = token.ExpiresOn, id_token = auth_token, token_type = token.TokenType }, businessUsers });
  122. //return Ok(new { state = RespondCode.Ok, openid_token, auth_token, token, businessUsers });
  123. }
  124. else
  125. { return Ok(new { state = RespondCode.ForbiddenPwd, msg = "密码错误" }); }
  126. }
  127. catch (Exception ex)
  128. {
  129. return Ok(new { state = RespondCode.ForbiddenPwd, msg = $"服务器错误{ex.Message}\n{ex.StackTrace}" });
  130. }
  131. }
  132. /// <summary>
  133. /// 注册 第三方用户数据在CosmosDB
  134. /// </summary>
  135. /// <param name="jsonElement"></param>
  136. /// <returns></returns>
  137. [HttpPost("set-bizuser")]
  138. public async Task<IActionResult> SetBizUserLogin(JsonElement jsonElement)
  139. {
  140. jsonElement.TryGetProperty("name", out JsonElement name);
  141. if (!jsonElement.TryGetProperty("mobile", out JsonElement mobile)) return BadRequest();
  142. jsonElement.TryGetProperty("mail", out JsonElement mail);
  143. jsonElement.TryGetProperty("pwd", out JsonElement pwd);
  144. var cosmosClient = _azureCosmos.GetCosmosClient();
  145. var tableClient = _azureStorage.GetCloudTableClient();
  146. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  147. string loginSql = null;
  148. string osblob_uri = null, osblob_sas = null;
  149. if (!string.IsNullOrEmpty($"{mobile}"))
  150. loginSql = $"select value(c) from c where c.mobile ={mobile}";
  151. else if (!string.IsNullOrEmpty($"{mail}"))
  152. loginSql = $"select value(c) from c where c.mail ={mail}";
  153. else return Ok(new { state = RespondCode.ParamsError, msg = "手机号/和邮箱为空" });
  154. List<BizUsers> tempBizUsers = new();
  155. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BizUsers>(queryText: loginSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
  156. {
  157. tempBizUsers.Add(item);
  158. }
  159. if (tempBizUsers.Count > 0)
  160. return Ok(new { state = RespondCode.Conflict, msg = "已存在" });
  161. else
  162. {
  163. string salt = Utils.CreatSaltString(8);
  164. BizUsers bizUsers = new()
  165. {
  166. id = Guid.NewGuid().ToString(),
  167. code = "BizUsers",
  168. name = string.IsNullOrEmpty($"{name}") ? $"{mobile}" : $"{name}",
  169. mobile = long.Parse($"{mobile}"),
  170. salt = salt,
  171. pwd = string.IsNullOrEmpty($"{pwd}") ? Utils.HashedPassword($"{mobile}", salt) : Utils.HashedPassword($"{pwd}", salt),
  172. };
  173. bizUsers = await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BizUsers>(bizUsers, new PartitionKey("BizUsers"));
  174. string log = $"{bizUsers.name}【{bizUsers.id}】注册第三方用户信息基础信息。";
  175. //保存操作记录
  176. await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "login-login", log, _dingDing, httpContext: HttpContext);
  177. var openid_token = JwtAuthExtension.CreateBizLoginAuthToken(_option.HostName, bizUsers.id?.ToString(), bizUsers.name?.ToString(), bizUsers.picture?.ToString(), $"{_option.Location}-Open", _option.JwtSecretKey, expire: 3);
  178. (osblob_uri, osblob_sas) = _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
  179. return Ok(new { state = RespondCode.Ok, openid_token, bizUsers, osblob_uri, osblob_sas });
  180. }
  181. }
  182. /// <summary>
  183. /// 查询企业详细信息
  184. /// </summary>
  185. /// <param name="jsonElenent"></param>
  186. /// <returns></returns>
  187. [ProducesDefaultResponseType]
  188. [HttpPost("get-info")]
  189. [Authorize(Roles = "IES")]
  190. [AuthToken(Roles = "business")]
  191. public async Task<IActionResult> GetInfo(JsonElement jsonElenent)
  192. {
  193. try
  194. {
  195. if (!jsonElenent.TryGetProperty("id", out JsonElement id)) return BadRequest();
  196. var cosmosClient = _azureCosmos.GetCosmosClient();
  197. var tableClient = _azureStorage.GetCloudTableClient();
  198. var table = tableClient.GetTableReference("IESOpenApi");
  199. Dictionary<string, object> keyValue = new() { { "PartitionKey", "BusinessConfig" } };
  200. if (!string.IsNullOrEmpty($"{id}"))
  201. {
  202. keyValue.Add("RowKey", $"{id}");
  203. }
  204. Business business = new();
  205. var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{id}", new PartitionKey("BizConfig"));
  206. if (response.Status == RespondCode.Ok)
  207. {
  208. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  209. business = json.ToObject<Business>();
  210. }
  211. else return Ok(new { state = RespondCode.NotFound, msg = "该企业信息" });
  212. return Ok(new { state = RespondCode.Ok, business });
  213. }
  214. catch (Exception e)
  215. {
  216. await _dingDing.SendBotMsg($"openApi,{_option.Location} , /biz/GetInfo() \n {e.Message}\n{e.StackTrace} \n ", GroupNames.成都开发測試群組);
  217. return BadRequest();
  218. }
  219. }
  220. /// <summary>
  221. /// 重置秘钥
  222. /// </summary>
  223. /// <param name="jsonElement"></param>
  224. /// <returns></returns>
  225. [ProducesDefaultResponseType]
  226. [HttpPost("reset-secretkey")]
  227. [Authorize(Roles = "IES")]
  228. [AuthToken(Roles = "business")]
  229. public async Task<IActionResult> ResetSecretKey(JsonElement jsonElement)
  230. {
  231. try
  232. {
  233. if (!jsonElement.TryGetProperty("id", out JsonElement id)) return BadRequest();
  234. var cosmosClient = _azureCosmos.GetCosmosClient();
  235. var tableClient = _azureStorage.GetCloudTableClient();
  236. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  237. BizConfig bizConfig = new();
  238. var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{id}", new PartitionKey("BizConfig"));
  239. if (response.Status == 200)
  240. {
  241. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  242. bizConfig = json.ToObject<BizConfig>();
  243. var auth_token = JwtAuthExtension.CreateBusinessApiToken(_option.Location, bizConfig.id, _option.JwtSecretKey, bizConfig.isCustomize);
  244. bizConfig.jti = auth_token.jti;
  245. bizConfig.token = auth_token.jwt;
  246. bizConfig = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BizConfig>(bizConfig, bizConfig.id, new PartitionKey("BizConfig"));
  247. }
  248. return Ok(new { state = RespondCode.Ok, bizConfig });
  249. }
  250. catch (Exception e)
  251. {
  252. await _dingDing.SendBotMsg($"openApi,{_option.Location} , /biz/ResetSecretKey() \n {e.Message}\n{e.StackTrace} \n ", GroupNames.成都开发測試群組);
  253. return BadRequest();
  254. }
  255. }
  256. /// <summary>
  257. /// 通过企业Id查询用户信息
  258. /// </summary>
  259. /// <param name="jsonElement"></param>
  260. /// <returns></returns>
  261. [ProducesDefaultResponseType]
  262. [HttpPost("get-bizid")]
  263. [Authorize(Roles = "IES")]
  264. [AuthToken(Roles = "business")]
  265. public async Task<IActionResult> GetBizIdUsers(JsonElement jsonElement)
  266. {
  267. try
  268. {
  269. if (!jsonElement.TryGetProperty("id", out JsonElement id)) return BadRequest();
  270. var cosmosClient = _azureCosmos.GetCosmosClient();
  271. List<BusinessUsers> businessUsers = new();
  272. string sql = $"select value(c) from c join s in c.relation where c.code='BizUsers' and s.bizId = '{id}'";
  273. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BusinessUsers>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
  274. {
  275. businessUsers.Add(item);
  276. }
  277. return Ok(new { state = RespondCode.Ok, businessUsers });
  278. }
  279. catch (Exception e)
  280. {
  281. await _dingDing.SendBotMsg($"openApi,{_option.Location} , /biz/GetBizIdUsers() \n {e.Message}\n{e.StackTrace} \n ", GroupNames.成都开发測試群組);
  282. return BadRequest();
  283. }
  284. }
  285. /// <summary>
  286. /// 获取企业开放接口列表
  287. /// </summary>
  288. /// <param name="jsonElement"></param>
  289. /// <returns></returns>
  290. [ProducesDefaultResponseType]
  291. [HttpPost("get-openapi")]
  292. [Authorize(Roles = "IES")]
  293. [AuthToken(Roles = "business")]
  294. public async Task<IActionResult> GetOpenApi(JsonElement jsonElement)
  295. {
  296. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESOpenApi");
  297. List<OpenApi> apis = await table.FindListByDict<OpenApi>(new Dictionary<string, object>() { { "PartitionKey", "IES5-API-business" } });
  298. return Ok(new { state = RespondCode.Ok, apis });
  299. }
  300. /// <summary>
  301. /// 修改和新增企业信息
  302. /// </summary>
  303. /// <param name="bizConfig"></param>
  304. /// <returns></returns>
  305. [ProducesDefaultResponseType]
  306. [HttpPost("set-info")]
  307. [Authorize(Roles = "IES")]
  308. [AuthToken(Roles = "business")]
  309. public async Task<IActionResult> SetInfo(BizConfig bizConfig)
  310. {
  311. try
  312. {
  313. StringBuilder strMsg = new();
  314. var cosmosClient = _azureCosmos.GetCosmosClient();
  315. var tableClient = _azureStorage.GetCloudTableClient();
  316. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  317. string salt = Utils.CreatSaltString(8);
  318. List<BizUsers> bizUsers = new();
  319. string type = "";
  320. //新增企业信息
  321. if (string.IsNullOrEmpty(bizConfig.id))
  322. {
  323. bizConfig.id = Guid.NewGuid().ToString();
  324. bizConfig.code = "BizConfig";
  325. bizConfig.pk = "BizConfig";
  326. bizConfig.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  327. var auth_token = JwtAuthExtension.CreateBusinessApiToken(_option.Location, bizConfig.id, _option.JwtSecretKey, bizConfig.isCustomize);
  328. bizConfig.jti = auth_token.jti;
  329. bizConfig.token = auth_token.jwt;
  330. await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BizConfig>(bizConfig, new PartitionKey("BizConfig"));
  331. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<BizUsers>(queryText: $"select value(c) from c where c.mobile ={bizConfig.mobile}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BizUsers") }))
  332. {
  333. bizUsers.Add(item);
  334. }
  335. BizRel bizRel = new() { bizId = bizConfig.id, role = new List<string>() { "admin" } };
  336. if (bizUsers.Count > 0)
  337. {
  338. foreach (var item in bizUsers)
  339. {
  340. BizRel temp = item.relation.Find(f => f.bizId.Equals(bizConfig.id));
  341. if (temp == null)
  342. {
  343. item.relation.Add(bizRel);
  344. await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BizUsers>(item, item.id, new PartitionKey("BizUsers"));
  345. }
  346. }
  347. }
  348. else
  349. {
  350. BizUsers tBizUsers = new() { id = Guid.NewGuid().ToString(), code = "BizUsers", name = bizConfig.mobile.ToString(), mobile = bizConfig.mobile, salt = salt, pwd = Utils.HashedPassword($"{bizConfig.mobile}", salt), relation = new List<BizRel>() { { bizRel } } };
  351. await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BizUsers>(tBizUsers, new PartitionKey("BizUsers"));
  352. }
  353. strMsg.Append($"{bizConfig.name}【{bizConfig.id}】新增企业基础信息。");
  354. type = "bizconfig-add";
  355. }
  356. //修改企业信息
  357. else
  358. {
  359. var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(bizConfig.id, new PartitionKey("BizConfig"));
  360. if (response.Status == 200)
  361. {
  362. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  363. BizConfig tempBizConfig = json.ToObject<BizConfig>();
  364. bizConfig.pk = "BizConfig";
  365. bizConfig.code = "BizConfig";
  366. bizConfig.ttl = -1;
  367. bizConfig.createTime = tempBizConfig.createTime;
  368. bizConfig.jti = tempBizConfig.jti;
  369. bizConfig.token = tempBizConfig.token;
  370. bizConfig = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BizConfig>(bizConfig, bizConfig.id, new PartitionKey("BizConfig"));
  371. strMsg.Append($"{bizConfig.name}【{bizConfig.id}】修改企业基础信息。");
  372. type = "bizconfig-update";
  373. }
  374. }
  375. //保存操作记录
  376. await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, type, strMsg.ToString(), _dingDing, httpContext: HttpContext);
  377. return Ok(new { state = RespondCode.Ok, bizConfig });
  378. }
  379. catch (Exception e)
  380. {
  381. await _dingDing.SendBotMsg($"openApi,{_option.Location} , /biz/SetInfo() \n {e.Message}\n{e.StackTrace} \n ", GroupNames.成都开发測試群組);
  382. return BadRequest();
  383. }
  384. }
  385. [ProducesDefaultResponseType]
  386. [AuthToken(Roles = "business")]
  387. [HttpPost("check-webhook")]
  388. [Authorize(Roles = "IES")]
  389. public async Task<IActionResult> CheckWebhook(JsonElement json ) {
  390. var (userid, name, picture, _) = HttpContext.GetAuthTokenInfo();
  391. string bizCode = json.GetProperty("bizCode").GetString();
  392. //检查是否与bizCode 有关联。
  393. BizConfig config = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<BizConfig>(bizCode, new PartitionKey("BizConfig"));
  394. List<dynamic> results = new List<dynamic>();
  395. if (!string.IsNullOrWhiteSpace(config?.webhook))
  396. {
  397. var urls = config?.webhook.Trim().Split(",");
  398. foreach (var url in urls)
  399. {
  400. HttpStatusCode httpStatus = await WebHookService.Send(new { data= "check-webhook" }, (url,config.webhookHead,config.webhookToken,config), "check-webhook", _httpClient, _dingDing, 2);
  401. results.Add(new { url = url, status = httpStatus });
  402. }
  403. return Ok(results);
  404. }
  405. else {
  406. return BadRequest(new { code=1,msg="未配置Webhook通知回调"});
  407. }
  408. }
  409. }
  410. }