Skip to content

Commit

Permalink
refactored to new project structure
Browse files Browse the repository at this point in the history
  • Loading branch information
acn-sbuad committed Apr 18, 2024
1 parent 91f7aef commit 39f7578
Show file tree
Hide file tree
Showing 38 changed files with 439 additions and 190 deletions.
13 changes: 13 additions & 0 deletions Altinn.Profile.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.Profile", "src\Altinn.Profile\Altinn.Profile.csproj", "{D32C4EE9-E827-467A-B116-8EF0BA08A11F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.Profile.Integrations", "src\Altinn.Profile.Integrations\Altinn.Profile.Integrations.csproj", "{46B6764A-0DCF-47E6-86B8-09A1CFC3CF80}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.Profile.Core", "src\Altinn.Profile.Core\Altinn.Profile.Core.csproj", "{8DF9A6F4-AF02-4B36-B199-78883FC51631}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Altinn.Profile.Tests", "test\Altinn.Profile.Tests\Altinn.Profile.Tests.csproj", "{85BF7FD9-90C1-4A4E-BDCC-F89F0BA65218}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution items", "{132B1657-0A2D-4047-8F3F-28C0004C011E}"
Expand All @@ -13,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution items", "Solution
README.md = README.md
EndProjectSection
EndProject

Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -27,6 +32,14 @@ Global
{85BF7FD9-90C1-4A4E-BDCC-F89F0BA65218}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85BF7FD9-90C1-4A4E-BDCC-F89F0BA65218}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85BF7FD9-90C1-4A4E-BDCC-F89F0BA65218}.Release|Any CPU.Build.0 = Release|Any CPU
{46B6764A-0DCF-47E6-86B8-09A1CFC3CF80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46B6764A-0DCF-47E6-86B8-09A1CFC3CF80}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46B6764A-0DCF-47E6-86B8-09A1CFC3CF80}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46B6764A-0DCF-47E6-86B8-09A1CFC3CF80}.Release|Any CPU.Build.0 = Release|Any CPU
{8DF9A6F4-AF02-4B36-B199-78883FC51631}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8DF9A6F4-AF02-4B36-B199-78883FC51631}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8DF9A6F4-AF02-4B36-B199-78883FC51631}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8DF9A6F4-AF02-4B36-B199-78883FC51631}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
11 changes: 7 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0.204-alpine3.18 AS build
WORKDIR Altinn.Profile/

COPY src/Altinn.Profile ./Altinn.Profile
WORKDIR Altinn.Profile/
COPY src/Altinn.Profile/*.csproj ./src/Altinn.Profile/
COPY src/Altinn.Profile.Core/*.csproj ./src/Altinn.Profile.Core/
COPY src/Altinn.Profile.Integrations/*.csproj ./src/Altinn.Profile.Integrations/
RUN dotnet restore ./src/Altinn.Profile/Altinn.Profile.csproj


RUN dotnet build Altinn.Profile.csproj -c Release -o /app_output
RUN dotnet publish Altinn.Profile.csproj -c Release -o /app_output
COPY src ./src
RUN dotnet publish -c Release -o out ./src/Altinn.Profile/Altinn.Profile.csproj

FROM mcr.microsoft.com/dotnet/aspnet:8.0.4-alpine3.18 AS final
EXPOSE 5030
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@
[![Profile build status](https://dev.azure.com/brreg/altinn-studio/_apis/build/status/altinn-platform/profile-master?label=platform/profile)](https://dev.azure.com/brreg/altinn-studio/_build/latest?definitionId=35)


## Project organization
This is a backend WebAPI solution written in .NET / C# following the clean architecture principles.

### Altinn.Profile
The API layer that consumes services provided by _Altinn.Profile.Core_

Relevant implementations:
- Controllers
- Program.cs


### Altinn.Profile.Core
The domain and application layer that implements the business logic of the system.

Relevant implementations:
- Interfaces for external dependencies implemented by infrastructure and repository layer
- Domain models
- Services

### Altinn.Profile.Integrations
The infrastructure layer that implements the interfaces defined in _Altinn.Profile.Core_ for integrations towards 3rd-party libraries and systems.

Relevant implementations:
- Clients for communicating with SBL Bridge in Altinn 2


## Getting Started

These instructions will get you a copy of the profile component up and running on your machine for development and testing purposes.
Expand Down
31 changes: 31 additions & 0 deletions src/Altinn.Profile.Core/Altinn.Profile.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<ProjectGuid>{7BA8E238-C930-45C0-BB5D-28AE4D89669B}</ProjectGuid>
</PropertyGroup>


<ItemGroup>
<PackageReference Include="Altinn.Platform.Models" Version="1.5.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
<PackageReference Include="Scrutor" Version="4.2.2" />
</ItemGroup>

<ItemGroup Condition="'$(Configuration)'=='Debug'">
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<AdditionalFiles Include="..\..\stylecop.json">
<Link>stylecop.json</Link>
</AdditionalFiles>
</ItemGroup>

</Project>
13 changes: 13 additions & 0 deletions src/Altinn.Profile.Core/CoreSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Altinn.Profile.Core
{
/// <summary>
/// General configuration settings for the core project
/// </summary>
public class CoreSettings
{
/// <summary>
/// The number of seconds the user profile will be kept in the cache
/// </summary>
public int ProfileCacheLifetimeSeconds { get; set; } = 600;
}
}
45 changes: 45 additions & 0 deletions src/Altinn.Profile.Core/Integrations/IUserProfileClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Altinn.Platform.Profile.Models;

namespace Altinn.Profile.Core.Integrations
{
/// <summary>
/// Interface describing a client for the user profile service
/// </summary>
public interface IUserProfileClient
{
/// <summary>
/// Method that fetches a user based on a user id
/// </summary>
/// <param name="userId">The user id</param>
/// <returns>User profile with given user id.</returns>
Task<UserProfile> GetUser(int userId);

/// <summary>
/// Method that fetches a user based on ssn.
/// </summary>
/// <param name="ssn">The user's ssn.</param>
/// <returns>User profile connected to given ssn.</returns>
Task<UserProfile> GetUser(string ssn);

/// <summary>
/// Method that fetches a user based on a user uuid
/// </summary>
/// <param name="userUuid">The user uuid</param>
/// <returns>User profile with given user uuid.</returns>
Task<UserProfile> GetUserByUuid(Guid userUuid);

/// <summary>
/// Method that fetches a list of users based on a list of user uuid
/// </summary>
/// <param name="userUuidList">The list of user uuids</param>
/// <returns>List of User profiles with given user uuids</returns>
Task<List<UserProfile>> GetUserListByUuid(List<Guid> userUuidList);

/// <summary>
/// Method that fetches a user based on username.
/// </summary>
/// <param name="username">The user's username.</param>
/// <returns>User profile connected to given username.</returns>
Task<UserProfile> GetUserByUsername(string username);
}
}
27 changes: 27 additions & 0 deletions src/Altinn.Profile.Core/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Altinn.Profile.Core;
using Altinn.Profile.Core.User;

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace Altinn.Notifications.Core.Extensions;

/// <summary>
/// Extension class for <see cref="IServiceCollection"/>
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// Adds core services and configurations to DI container.
/// </summary>
/// <param name="services">service collection.</param>
/// <param name="config">the configuration collection</param>
public static void AddCoreServices(this IServiceCollection services, IConfiguration config)
{
services
.Configure<CoreSettings>(config.GetSection(nameof(CoreSettings)))
.AddMemoryCache()
.AddSingleton<IUserProfileService, UserProfileService>()
.Decorate<IUserProfileService, UserProfileCachingDecorator>();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System.Collections.Generic;
using System.Threading.Tasks;

using Altinn.Profile.Models;

namespace Altinn.Profile.Services.Interfaces
namespace Altinn.Profile.Core.User.ContactPoints
{
/// <summary>
/// Class describing the methods required for user contact point service
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;

namespace Altinn.Profile.Models
namespace Altinn.Profile.Core.User.ContactPoints
{
/// <summary>
/// Class describing the contact points of a user
Expand All @@ -15,7 +15,7 @@ public class UserContactPointAvailability
/// <summary>
/// Gets or sets the national identityt number of the user
/// </summary>
public string NationalIdentityNumber { get; set; }
public string NationalIdentityNumber { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a boolean indicating whether the user has reserved themselves from electronic communication
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;

namespace Altinn.Profile.Models
namespace Altinn.Profile.Core.User.ContactPoints
{
/// <summary>
/// A class respresenting a user contact point lookup object
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
using System.Collections.Generic;
using System.Threading.Tasks;

using Altinn.Platform.Profile.Models;
using Altinn.Profile.Models;
using Altinn.Profile.Services.Interfaces;
using Altinn.Profile.Core.User;

namespace Altinn.Profile.Services.Implementation
namespace Altinn.Profile.Core.User.ContactPoints
{
/// <summary>
/// An implementation of <see cref="IUserContactPoints"/> that uses the <see cref="IUserProfiles"/> to obtain contact point information.
/// An implementation of <see cref="IUserContactPoints"/> that uses the <see cref="IUserProfileService"/> to obtain contact point information.
/// </summary>
public class UserContactPointService : IUserContactPoints
{
private readonly IUserProfiles _userProfiles;
private readonly IUserProfileService _userProfileService;

/// <summary>
/// Initializes a new instance of the <see cref="UserContactPointService"/> class.
/// </summary>
public UserContactPointService(IUserProfiles userProfiles)
public UserContactPointService(IUserProfileService userProfiles)
{
_userProfiles = userProfiles;
_userProfileService = userProfiles;
}

/// <inheritdoc/>
Expand All @@ -29,7 +27,7 @@ public async Task<UserContactPointAvailabilityList> GetContactPointAvailability(

foreach (var nationalIdentityNumber in nationalIdentityNumbers)
{
UserProfile profile = await _userProfiles.GetUser(nationalIdentityNumber);
UserProfile profile = await _userProfileService.GetUser(nationalIdentityNumber);

if (profile == null)
{
Expand All @@ -56,7 +54,7 @@ public async Task<UserContactPointsList> GetContactPoints(List<string> nationalI

foreach (var nationalIdentityNumber in nationalIdentityNumbers)
{
var profile = await _userProfiles.GetUser(nationalIdentityNumber);
var profile = await _userProfileService.GetUser(nationalIdentityNumber);

if (profile == null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;

namespace Altinn.Profile.Models
namespace Altinn.Profile.Core.User.ContactPoints
{
/// <summary>
/// Class describing the availability of contact points for a user
Expand All @@ -15,7 +15,7 @@ public class UserContactPoints
/// <summary>
/// Gets or sets the national identityt number of the user
/// </summary>
public string NationalIdentityNumber { get; set; }
public string NationalIdentityNumber { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a boolean indicating whether the user has reserved themselves from electronic communication
Expand All @@ -25,12 +25,12 @@ public class UserContactPoints
/// <summary>
/// Gets or sets the mobile number
/// </summary>
public string MobileNumber { get; set; }
public string MobileNumber { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the email address
/// </summary>
public string Email { get; set; }
public string Email { get; set; } = string.Empty;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Altinn.Platform.Profile.Models;

using Altinn.Platform.Profile.Models;

namespace Altinn.Profile.Services.Interfaces
namespace Altinn.Profile.Core.User
{
/// <summary>
/// Interface handling methods for operations related to users
/// Interface handling methods for operations related to user profiles
/// </summary>
public interface IUserProfiles
public interface IUserProfileService
{
/// <summary>
/// Method that fetches a user based on a user id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using Altinn.Platform.Profile.Models;
using Altinn.Profile.Configuration;
using Altinn.Profile.Services.Interfaces;

using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;

namespace Altinn.Profile.Services.Decorators
namespace Altinn.Profile.Core.User
{
/// <summary>.
/// Decorates an implementation of IUserProfiles by caching the userProfile object.
/// If available, object is retrieved from cache without calling the service
/// </summary>
public class UserProfileCachingDecorator : IUserProfiles
public class UserProfileCachingDecorator : IUserProfileService
{
private readonly IUserProfiles _decoratedService;
private readonly IUserProfileService _decoratedService;
private readonly IMemoryCache _memoryCache;
private readonly MemoryCacheEntryOptions _cacheOptions;

Expand All @@ -26,17 +20,17 @@ public class UserProfileCachingDecorator : IUserProfiles
/// </summary>
/// <param name="decoratedService">The decorated userProfiles service</param>
/// <param name="memoryCache">The memory cache</param>
/// <param name="generalSettings">The general settings</param>
/// <param name="settings">The core settings</param>
public UserProfileCachingDecorator(
IUserProfiles decoratedService,
IUserProfileService decoratedService,
IMemoryCache memoryCache,
IOptions<GeneralSettings> generalSettings)
IOptions<CoreSettings> settings)
{
_decoratedService = decoratedService;
_memoryCache = memoryCache;
_cacheOptions = new()
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(generalSettings.Value.ProfileCacheLifetimeSeconds)
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(settings.Value.ProfileCacheLifetimeSeconds)
};
}

Expand Down
Loading

0 comments on commit 39f7578

Please sign in to comment.