BizUsersController.cs 23 KB

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