Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions PrismaApi/PrismaApi.Api/Controllers/StuctureController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public async Task<ActionResult<ApiResponseDto>> GetDecisionTreeAsync([FromRoute]
var fastApiResponse = await _fastApiService.SendInfluenceDiagramToFastApiAsync(projectId, $"/structure/{projectId}/decision_tree/v2", user);
if (fastApiResponse.StatusCode == HttpStatusCode.OK)
{
return Ok(!string.IsNullOrEmpty(fastApiResponse.Content) ? fastApiResponse.Content.SanitizeString() : null);
return Ok(!string.IsNullOrEmpty(fastApiResponse.Content) ? fastApiResponse.Content.SanitizeLogString() : null);
}

return StatusCode((int)fastApiResponse.StatusCode, fastApiResponse.Content);
Expand All @@ -39,7 +39,7 @@ public async Task<ActionResult<ApiResponseDto>> GetInfluenceDiagramAsync([FromRo
var fastApiResponse = await _fastApiService.SendInfluenceDiagramToFastApiAsync(projectId, $"/structure/{projectId}/influence_diagram", user);
if (fastApiResponse.StatusCode == HttpStatusCode.OK)
{
return Ok(!string.IsNullOrEmpty(fastApiResponse.Content) ? fastApiResponse.Content.SanitizeString() : null);
return Ok(!string.IsNullOrEmpty(fastApiResponse.Content) ? fastApiResponse.Content.SanitizeLogString() : null);
}

return StatusCode((int)fastApiResponse.StatusCode, fastApiResponse.Content);
Expand All @@ -53,7 +53,7 @@ public async Task<ActionResult<ApiResponseDto>> GetPartialOrderAsync([FromRoute]

if (fastApiResponse.StatusCode == HttpStatusCode.OK)
{
return Ok(!string.IsNullOrEmpty(fastApiResponse.Content) ? fastApiResponse.Content.SanitizeString() : null);
return Ok(!string.IsNullOrEmpty(fastApiResponse.Content) ? fastApiResponse.Content.SanitizeLogString() : null);
}

return StatusCode((int)fastApiResponse.StatusCode, fastApiResponse.Content);
Expand Down
22 changes: 18 additions & 4 deletions PrismaApi/PrismaApi.Api/Controllers/UsersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,25 @@ public async Task<ActionResult<List<UserOutgoingDto>>> GetUsers()
return Ok(result);
}

[HttpGet("users/{id:int}")]
public async Task<ActionResult<UserOutgoingDto>> GetUser(string id)

[HttpPost("users/userIds")]
public async Task<ActionResult<List<UserOutgoingDto>>> GetUsersByIds([FromBody] List<string> ids)
{
if (ids == null || ids.Count == 0)
return BadRequest("At least one user ID is required.");

var result = await _userService.GetByIdsAsync(ids);
return result.Count > 0 ? Ok(result) : NotFound();
}

[HttpGet("users/search")]
public async Task<ActionResult<List<UserOutgoingDto>>> SearchUsers([FromQuery] string query)
{
var result = await _userService.GetAsync(new List<string> { id });
return result.Count > 0 ? Ok(result[0]) : NotFound();
if (string.IsNullOrWhiteSpace(query))
return BadRequest("Query parameter is required.");

var result = await _userService.SearchUsersFromGraphAsync(query);
return result.Count > 0 ? Ok(result) : NotFound();
}

[HttpGet("auth")]
Expand Down
4 changes: 4 additions & 0 deletions PrismaApi/PrismaApi.Api/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"BaseUrl": "http://fastapi:8000",
"Scope": "api://4251833c-b9c3-4013-afda-cbfd2cc50f3f/.default"
},
"GraphApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "User.ReadBasic.All"
},
"AllowedOrigins": [
"http://localhost:5004",
"https://frontend-prisma-decision-web-dev.radix.equinor.com"
Expand Down
4 changes: 4 additions & 0 deletions PrismaApi/PrismaApi.Api/appsettings.Production.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"BaseUrl": "http://fastapi:8000",
"Scope": "api://706ace43-0266-478e-a047-942162b6e1ff/.default"
},
"GraphApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "User.ReadBasic.All"
},
"AllowedOrigins": [
"http://localhost:5004",
"https://frontend-prisma-decision-web-prod.radix.equinor.com/"
Expand Down
4 changes: 4 additions & 0 deletions PrismaApi/PrismaApi.Api/appsettings.Test.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"BaseUrl": "http://localhost:8000",
"Scope": "api://945882c1-69f4-41cd-a42a-22516ca01868/.default"
},
"GraphApi": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "User.ReadBasic.All"
},
"AllowedOrigins": [
"http://localhost:5004",
"https://frontend-prisma-decision-web-test.radix.equinor.com/"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ namespace PrismaApi.Application.Interfaces.Services;

public interface IUserService
{
Task<List<UserOutgoingDto>> GetAsync(List<string> ids);
Task<List<UserOutgoingDto>> GetAllAsync();
Task<UserOutgoingDto> GetOrCreateUserByIdAsync(UserIncomingDto dto);
Task<UserOutgoingDto> GetOrCreateUserFromGraphMeAsync(string? cacheKey);
Task<List<UserOutgoingDto>> SearchUsersFromGraphAsync(string query);

Task<UserOutgoingDto> GetOrCreateUserFromContextAsync(HttpContext context);
Task<List<UserOutgoingDto>> GetByIdsAsync(IEnumerable<string> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ public static UserOutgoingDto ToOutgoingDto(this User entity)
{
Id = entity.Id,
Name = entity.Name,
ProjectRoles = entity.ProjectRoles.ToOutgoingDtos()
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public async Task UpdateRangeAsync(IEnumerable<Issue> incommingEntities, Express

if (incomingEntity.Decision != null && entity.Decision != null)
entity.Decision = await entity.Decision.Update(incomingEntity.Decision, DbContext, _ruleTrigger);

if (incomingEntity.Uncertainty != null && entity.Uncertainty != null)
entity.Uncertainty = await entity.Uncertainty.Update(incomingEntity.Uncertainty, DbContext, _ruleTrigger);

Expand Down Expand Up @@ -98,6 +98,7 @@ private static bool IsDecisionMovedOutOfStrategyTable(Issue entity, Issue incomm
protected override IQueryable<Issue> Query()
{
return DbContext.Issues
.AsSplitQuery()
.Include(i => i.Node!)
.ThenInclude(n => n.NodeStyle)
.Include(i => i.Node!)
Expand Down
37 changes: 28 additions & 9 deletions PrismaApi/PrismaApi.Application/Services/UserService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
using PrismaApi.Application.Interfaces.Services;
using PrismaApi.Application.Mapping;
using PrismaApi.Domain.Dtos;
using PrismaApi.Domain.Constants;
using PrismaApi.Infrastructure.Caching;
using Scampi.Domain.Extensions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace PrismaApi.Application.Services;

public class UserService: IUserService
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly GraphServiceClient _graphServiceClient;
Expand All @@ -24,13 +26,6 @@ public UserService(IUserRepository userRepository, GraphServiceClient graphServi
_graphServiceClient = graphServiceClient;
_memoryCache = memoryCache;
}

public async Task<List<UserOutgoingDto>> GetAsync(List<string> ids)
{
var users = await _userRepository.GetByIdsAsync(ids, withTracking: false);
return users.ToOutgoingDtos();
}

public async Task<List<UserOutgoingDto>> GetAllAsync()
{
var users = await _userRepository.GetAllAsync(withTracking: false);
Expand All @@ -57,7 +52,7 @@ public async Task<UserOutgoingDto> GetOrCreateUserFromGraphMeAsync(string? cache
Name = graphUser.DisplayName ?? "",
};
var user = (await _userRepository.GetOrAddByIdAsync(userDto)).ToOutgoingDto();

if (cacheKey != null)
_memoryCache.AddCacheItem(new CacheItem { CacheKey = cacheKey }, TimeSpan.FromMinutes(30), user);

Expand All @@ -76,4 +71,28 @@ public async Task<UserOutgoingDto> GetOrCreateUserFromContextAsync(HttpContext c
var user = await GetOrCreateUserFromGraphMeAsync(oid);
return user;
}
public async Task<List<UserOutgoingDto>> GetByIdsAsync(IEnumerable<string> ids)
{
var users = await _userRepository.GetByIdsAsync(ids, withTracking: false);
return users.ToOutgoingDtos();
}

public async Task<List<UserOutgoingDto>> SearchUsersFromGraphAsync(string query)
{
string sanitizedQuery = query.SanitizeQuery();
var users = await _graphServiceClient.Users
.GetAsync(config =>
{
config.QueryParameters.Search = $"\"displayName:{sanitizedQuery}\" OR \"mail:{sanitizedQuery}\"";
config.QueryParameters.Select = GraphApiConstants.UserSearchSelectFields;
config.QueryParameters.Top = GraphApiConstants.DefaultSearchTop;
config.Headers.Add(GraphApiConstants.ConsistencyLevelHeader, GraphApiConstants.ConsistencyLevelEventual);
});

return users?.Value?.Select(u => new UserOutgoingDto
{
Id = u.Id ?? "",
Name = u.DisplayName ?? u.UserPrincipalName ?? "",
}).ToList() ?? new List<UserOutgoingDto>();
}
}
8 changes: 8 additions & 0 deletions PrismaApi/PrismaApi.Domain/Constants/DomainConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ public static class AppConstants
public const string CurrentUserKey = "CurrentUser";
}

public static class GraphApiConstants
{
public const string ConsistencyLevelHeader = "ConsistencyLevel";
public const string ConsistencyLevelEventual = "eventual";
public const int DefaultSearchTop = 100;
public static readonly string[] UserSearchSelectFields = ["id", "displayName", "mail", "userPrincipalName"];
}

public static class AppRoles
{
public const string PrismaDecisionUser = "PrismaDecisionUser";
Expand Down
3 changes: 1 addition & 2 deletions PrismaApi/PrismaApi.Domain/Dtos/UserDtos.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@ public class UserIncomingDto : UserDto

public class UserOutgoingDto : UserDto
{
[JsonPropertyName("project_roles")]
public List<ProjectRoleOutgoingDto> ProjectRoles { get; set; } = new();

}
16 changes: 13 additions & 3 deletions PrismaApi/PrismaApi.Domain/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
namespace Scampi.Domain.Extensions;
using System.Text.RegularExpressions;

namespace Scampi.Domain.Extensions;

public static class StringExtensions
{
public static string SanitizeString(this string arg)
public static string SanitizeLogString(this string arg)
{
return arg.Replace("\r", "").Replace("\n", "");
}
}

public static string SanitizeQuery(this string query)
{
var sanitized = query.Trim();
sanitized = Regex.Replace(sanitized, @"\s+", " ");
sanitized = Regex.Replace(sanitized, @"[""'\\(){}[\];:*~+\-!&|]", string.Empty);
return sanitized;
}
}