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
{
///
/// 医生基本信息 、工作信息 专业信息、审核状态
///
[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
{
///
/// 获取医生详情
///
///
///
///
///
///
///
///
///
[HttpPost, Route("doctor/getDetail")]
public async Task> 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)
{
//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 GetObjectStoreTokenAsync([FromServices] IOptionsMonitor options, [FromServices] IOSSService _oSSService)
{
var result = _oSSService.GetObjectStoreTempToken();
//result.AWS = await GetAWSTemToken(options.CurrentValue);
return ResponseOutput.Ok(result);
}
private async Task 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 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();
// 将设置为自定义的会话名称,例如oss-role-session。
assumeRoleRequest.RoleSessionName = $"session-name-{NewId.NextGuid()}";
// 将替换为拥有上传文件到指定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 UserRedirect([FromServices] IRepository _useRepository, string url, [FromServices] ILogger _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 对接修改
///
/// 回调到前端,前端调用后端的接口
/// 参考链接: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。
/// (像我们单体,这种方式最简单,我们用单点登录,无非就是不想记多个系统的密码,自动登录而已,其他不支持的项目改造成本也是最低的)
///
/// 回调的厂商类型 比如github, google, 我们用的logto ,不同的厂商回调到前端的地址可以不同的,但是请求后端的接口可以是同一个
/// 在第三方平台登录成功后,回调前端的时候会返回一个code
///
[HttpGet("User/OAuthCallBack")]
public async Task OAuthCallBack(string type, string code)
{
#region 获取AccessTo
//var headerDic = new Dictionary();
//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
}
}