irc-netcore-api/IRaCIS.Core.API/Controllers/ExtraController.cs

380 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using AlibabaCloud.SDK.Sts20150401;
using Amazon.Auth.AccessControlPolicy;
using Amazon.SecurityToken;
using AutoMapper;
using Azure.Core;
using IdentityModel.Client;
using IdentityModel.OidcClient;
using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Contracts;
using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Service;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention;
using MassTransit;
using MassTransit.Futures.Contracts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Org.BouncyCastle.Tls;
using RestSharp;
using RestSharp.Authenticators;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using ZiggyCreatures.Caching.Fusion;
using AssumeRoleRequest = Amazon.SecurityToken.Model.AssumeRoleRequest;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
namespace IRaCIS.Api.Controllers
{
/// <summary>
/// 医生基本信息 、工作信息 专业信息、审核状态
/// </summary>
[ApiController, ApiExplorerSettings(GroupName = "Reviewer")]
public class ExtraController([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
[FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService,
[FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService) : ControllerBase
{
/// <summary>
/// 获取医生详情
/// </summary>
/// <param name="attachmentService"></param>
/// <param name="_doctorService"></param>
/// <param name="_educationService"></param>
/// <param name="_trialExperienceService"></param>
/// <param name="_researchPublicationService"></param>
/// <param name="_vacationService"></param>
/// <param name="doctorId"></param>
/// <returns></returns>
[HttpPost, Route("doctor/getDetail")]
public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail(GetDoctorDetailInDto inDto)
{
var education = await _educationService.GetEducation(inDto.doctorId);
var sowList = _doctorService.GetDoctorSowList(inDto.doctorId);
var ackSowList = _doctorService.GetDoctorAckSowList(inDto.doctorId);
var doctorDetail = new DoctorDetailDTO
{
AuditView = await _doctorService.GetAuditState(inDto.doctorId),
BasicInfoView = await _doctorService.GetBasicInfo(inDto.doctorId),
EmploymentView = await _doctorService.GetEmploymentInfo(inDto.doctorId),
AttachmentList = await attachmentService.GetAttachments(inDto.doctorId),
SummarizeInfo = await _doctorService.GetSummarizeInfo(new GetSummarizeInfoInDto()
{
DoctorId = inDto.doctorId,
TrialId = inDto.TrialId
}),
PaymentModeInfo = await _doctorService.GetPaymentMode(inDto.doctorId),
EducationList = education.EducationList,
PostgraduateList = education.PostgraduateList,
TrialExperienceView = await _trialExperienceService.GetTrialExperience(new TrialExperienceModelIndto()
{
DoctorId = inDto.doctorId,
TrialId = inDto.TrialId
}),
ResearchPublicationView = await _researchPublicationService.GetResearchPublication(inDto.doctorId),
SpecialtyView = await _doctorService.GetSpecialtyInfo(inDto.doctorId),
InHoliday = (await _vacationService.OnVacation(inDto.doctorId)).IsSuccess,
IntoGroupInfo = _doctorService.GetDoctorIntoGroupInfo(inDto.doctorId),
SowList = sowList,
AckSowList = ackSowList
};
return ResponseOutput.Ok(doctorDetail);
}
[AllowAnonymous]
[HttpGet, Route("user/getPublicKey")]
public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption)
{
//var pemPublicKey = Encoding.UTF8.GetString(Convert.FromBase64String(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey));
return ResponseOutput.Ok(_IRCEncreptOption.CurrentValue.Base64RSAPublicKey);
}
[HttpGet, Route("imageShare/ShareImage")]
[AllowAnonymous]
public IResponseOutput ShareImage([FromServices] ITokenService _tokenService)
{
var token = _tokenService.GetToken(new UserTokenInfo()
{
IdentityUserId = Guid.NewGuid(),
UserName = "Share001",
UserTypeEnum = UserTypeEnum.ShareImage,
});
return ResponseOutput.Ok("/showdicom?studyId=f7b67793-8155-0223-2f15-118f2642efb8&type=Share&token=" + token);
}
[HttpGet("user/GetObjectStoreToken")]
public async Task<IResponseOutput> GetObjectStoreTokenAsync([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options, [FromServices] IOSSService _oSSService)
{
var result = _oSSService.GetObjectStoreTempToken();
//result.AWS = await GetAWSTemToken(options.CurrentValue);
return ResponseOutput.Ok(result);
}
private async Task<AWSTempToken> GetAWSTemToken(ObjectStoreServiceOptions serviceOption)
{
var awsOptions = serviceOption.AWS;
//aws 临时凭证
// 创建 STS 客户端
var stsClient = new AmazonSecurityTokenServiceClient(awsOptions.AccessKeyId, awsOptions.SecretAccessKey);
// 使用 AssumeRole 请求临时凭证
var assumeRoleRequest = new AssumeRoleRequest
{
RoleArn = awsOptions.RoleArn, // 角色 ARN
RoleSessionName = $"session-name-{NewId.NextGuid()}",
DurationSeconds = awsOptions.DurationSeconds // 临时凭证有效期
};
var assumeRoleResponse = await stsClient.AssumeRoleAsync(assumeRoleRequest);
var credentials = assumeRoleResponse.Credentials;
var tempToken = new AWSTempToken()
{
AccessKeyId = credentials.AccessKeyId,
SecretAccessKey = credentials.SecretAccessKey,
SessionToken = credentials.SessionToken,
Expiration = credentials.Expiration,
Region = awsOptions.Region,
BucketName = awsOptions.BucketName,
EndPoint = awsOptions.EndPoint,
ViewEndpoint = awsOptions.ViewEndpoint,
};
return tempToken;
}
#region 老项目依赖
[HttpGet("user/GenerateSTS")]
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<ObjectStoreServiceOptions> options)
{
var ossOptions = options.CurrentValue.AliyunOSS;
var client = new Client(new AlibabaCloud.OpenApiClient.Models.Config()
{
AccessKeyId = ossOptions.AccessKeyId,
AccessKeySecret = ossOptions.AccessKeySecret,
Endpoint = "sts.cn-hangzhou.aliyuncs.com"
});
var assumeRoleRequest = new AlibabaCloud.SDK.Sts20150401.Models.AssumeRoleRequest();
// 将<YOUR_ROLE_SESSION_NAME>设置为自定义的会话名称例如oss-role-session。
assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
// 将<YOUR_ROLE_ARN>替换为拥有上传文件到指定OSS Bucket权限的RAM角色的ARN。
assumeRoleRequest.RoleArn = ossOptions.RoleArn;
//assumeRoleRequest.RoleArn = "acs:ram::1899121822495495:role/webdirect";
assumeRoleRequest.DurationSeconds = ossOptions.DurationSeconds;
var runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
var response = client.AssumeRoleWithOptions(assumeRoleRequest, runtime);
var credentials = response.Body.Credentials;
var tempToken = new AliyunOSSTempToken()
{
AccessKeyId = credentials.AccessKeyId,
AccessKeySecret = credentials.AccessKeySecret,
//转为服务器时区,最后统一转为客户端时区
Expiration = TimeZoneInfo.ConvertTimeFromUtc(DateTime.Parse(credentials.Expiration), TimeZoneInfo.Local),
SecurityToken = credentials.SecurityToken,
Region = ossOptions.Region,
BucketName = ossOptions.BucketName,
EndPoint = ossOptions.EndPoint,
ViewEndpoint = ossOptions.ViewEndpoint,
PreviewEndpoint = ossOptions.PreviewEndpoint
};
// 返回STS令牌信息给前端
var stsToken = new
{
AccessKeyId = credentials.AccessKeyId,
AccessKeySecret = credentials.AccessKeySecret,
SecurityToken = credentials.SecurityToken,
Expiration = credentials.Expiration,
Region = ossOptions.Region,
BucketName = ossOptions.BucketName,
ViewEndpoint = ossOptions.ViewEndpoint,
};
return ResponseOutput.Ok(stsToken);
}
#endregion
[HttpGet("User/UserRedirect")]
[AllowAnonymous]
public async Task<IActionResult> UserRedirect([FromServices] IRepository<IdentityUser> _useRepository, string url, [FromServices] ILogger<ExtraController> _logger, [FromServices] ITokenService _tokenService)
{
var decodeUrl = System.Web.HttpUtility.UrlDecode(url);
var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length, 36);
var token = decodeUrl.Substring(decodeUrl.IndexOf("access_token=") + "access_token=".Length);
var lang = decodeUrl.Substring(decodeUrl.IndexOf("lang=") + "lang=".Length, 2);
var domainStrList = decodeUrl.Split("/").ToList().Take(3).ToList();
var errorUrl = domainStrList[0] + "//" + domainStrList[2] + "/error";
if (lang == "zh")
{
CultureInfo.CurrentCulture = new CultureInfo(StaticData.CultureInfo.zh_CN);
CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.zh_CN);
}
else
{
CultureInfo.CurrentCulture = new CultureInfo(StaticData.CultureInfo.en_US);
CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.en_US);
}
var isExpire = _tokenService.IsTokenExpired(token);
if (!await _useRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd) || isExpire)
{
decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(I18n.T("UserRedirect_InitializationLinkExpire"))} ";
}
return Redirect(decodeUrl);
}
#region 项目支持Oauth 对接修改
/// <summary>
/// 回调到前端,前端调用后端的接口
/// 参考链接https://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html
/// 后端通过这个code ,带上客户端信息,和授权类型 可以向单点登录提供商获取厂商token
///
/// 但是单点登录提供商提供的token 和我们系统的token 是有区别的我们的token里面有我们业务系统的UserId涉及到很多业务操作所以在此出现了两种方案
/// 1、前端使用厂商的Token。 后端通过code 获取厂商的Token 返回前端的同时返回我们系统的UserId前段在http 请求头加上一个自定义参数带上UserId 后端取用户Id的地方变动下
/// 但是除了UserId外后端还有其他信息也是从Token取的所以在请求头也需要带上此外后端认证Token的方式也需要变化改造成本稍大如果是微服务做这种处理还是可以的
/// 2、前端还是使用我们后台自己的Token。后端通过code 获取厂商Token的同时后端做一个隐藏登录返回厂商的Token的同时也返回我们系统的Token。
/// (像我们单体,这种方式最简单,我们用单点登录,无非就是不想记多个系统的密码,自动登录而已,其他不支持的项目改造成本也是最低的)
/// </summary>
/// <param name="type">回调的厂商类型 比如github, google, 我们用的logto ,不同的厂商回调到前端的地址可以不同的,但是请求后端的接口可以是同一个 </param>
/// <param name="code">在第三方平台登录成功后回调前端的时候会返回一个code </param>
/// <returns></returns>
[HttpGet("User/OAuthCallBack")]
public async Task<IResponseOutput> OAuthCallBack(string type, string code)
{
#region 获取AccessTo
//var headerDic = new Dictionary<string, string>();
//headerDic.Add("code", code);
//headerDic.Add("grant_type", "authorization_code");
//headerDic.Add("redirect_uri", "http://localhost:6100");
//headerDic.Add("scope", "all");
#endregion
return ResponseOutput.Ok();
}
#endregion
#region 测试获取用户 ip
[HttpGet, Route("ip")]
[AllowAnonymous]
public IResponseOutput Get([FromServices] IHttpContextAccessor _context)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"RemoteIpAddress{_context.HttpContext.Connection.RemoteIpAddress}");
if (Request.Headers.ContainsKey("X-Real-IP"))
{
sb.AppendLine($"X-Real-IP{Request.Headers["X-Real-IP"].ToString()}");
}
if (Request.Headers.ContainsKey("X-Forwarded-For"))
{
sb.AppendLine($"X-Forwarded-For{Request.Headers["X-Forwarded-For"].ToString()}");
}
return ResponseOutput.Ok(sb.ToString());
}
[HttpGet, Route("ip2")]
[AllowAnonymous]
public IResponseOutput Get2([FromServices] IHttpContextAccessor _context)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"RemoteIpAddress{_context.HttpContext.Connection.RemoteIpAddress}");
if (Request.Headers.ContainsKey("X-Real-IP"))
{
sb.AppendLine($"X-Real-IP{Request.Headers["X-Real-IP"].ToString()}");
}
if (Request.Headers.ContainsKey("X-Forwarded-For"))
{
sb.AppendLine($"X-Forwarded-For{Request.Headers["X-Forwarded-For"].ToString()}");
}
return ResponseOutput.Ok(sb.ToString());
}
#endregion
}
}