Skip to content

Commit

Permalink
Merge branch 'main' into feat/13686-support-access-packages-in-policy…
Browse files Browse the repository at this point in the history
…-editor-v1
  • Loading branch information
mgunnerud authored Nov 26, 2024
2 parents 99838b4 + fa38b1b commit 28867e0
Show file tree
Hide file tree
Showing 399 changed files with 8,402 additions and 4,760 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v4

- name: Install dotnet ef # Version should be the same as Migrations docker file and project
run: dotnet tool install --version 8.0.7 --global dotnet-ef
run: dotnet tool install --version 9.0.0 --global dotnet-ef

- name: Check if migrations script can be generated
run: |
Expand Down
725 changes: 367 additions & 358 deletions .yarn/releases/yarn-4.5.0.cjs → .yarn/releases/yarn-4.5.1.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ enableTelemetry: false

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.5.0.cjs
yarnPath: .yarn/releases/yarn-4.5.1.cjs
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ COPY ./frontend/dashboard/package.json ./frontend/dashboard/
COPY ./frontend/language/package.json ./frontend/language/
COPY ./frontend/libs/studio-components/package.json ./frontend/libs/studio-components/
COPY ./frontend/libs/studio-content-library/package.json ./frontend/libs/studio-content-library/
COPY ./frontend/libs/studio-feedback-form/package.json ./frontend/libs/studio-feedback-form/
COPY ./frontend/libs/studio-hooks/package.json ./frontend/libs/studio-hooks/
COPY ./frontend/libs/studio-icons/package.json ./frontend/libs/studio-icons/
COPY ./frontend/libs/studio-pure-functions/package.json ./frontend/libs/studio-pure-functions/
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ The development environment consist of several services defined in [compose.yaml
- `studio-repos` which is [gitea][14] with some custom config. More [here](gitea/README.md).
- `studio-db` which is a postgres database used by both `studio-designer` and `studio-repos`.
- `database_migrations` which is a one-time task container designed to perform and complete database migrations before exiting.
- `redis` which is a redis cache used by designer.
- `redis-commander` which is a ui for redis cache.

Run all parts of the solution in containers (Make sure docker is running), with docker compose as follows:

Expand Down
2 changes: 1 addition & 1 deletion backend/Migrations.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ WORKDIR /app

COPY . .

RUN dotnet tool install --version 8.0.7 --global dotnet-ef
RUN dotnet tool install --version 9.0.0 --global dotnet-ef
ENV PATH="$PATH:/root/.dotnet/tools"

ENV OidcLoginSettings__FetchClientIdAndSecretFromRootEnvFile=false
Expand Down
7 changes: 4 additions & 3 deletions backend/packagegroups/NuGet.props
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@
<PackageReference Update="Microsoft.Azure.Security.KeyVault.Secrets" Version="4.5.0" />
<PackageReference Update="Microsoft.Azure.Services.AppAuthentication" Version="1.6.2" />
<PackageReference Update="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.24" />
<PackageReference Update="Microsoft.Extensions.Caching.StackExchangeRedis" Version="9.0.0" />
<PackageReference Update="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.0" />
<PackageReference Update="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.0" />
<PackageReference Update="Microsoft.VisualStudio.Web.BrowserLink" Version="2.2.0" />
<PackageReference Update="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageReference Update="HtmlAgilityPack" Version="1.11.67" />
<PackageReference Update="Microsoft.DiaSymReader.Native" Version="1.7.0" />
<PackageReference Update="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Tools" Version="8.0.10" />
<PackageReference Update="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.1" />
<PackageReference Update="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0" />
<PackageReference Update="Microsoft.FeatureManagement.AspNetCore" Version="3.5.0" />
<PackageReference Update="Scrutor" Version="4.2.2" />
<PackageReference Update="Polly" Version="8.4.2" />
Expand All @@ -40,7 +42,6 @@
<PackageReference Update="DotNetEnv" Version="3.1.1" />
<PackageReference Update="NuGet.Versioning" Version="6.11.1" />
<PackageReference Update="DistributedLock.Postgres" Version="1.2.0" />
<PackageReference Update="Community.Microsoft.Extensions.Caching.PostgreSql" Version="4.0.6" />
</ItemGroup>

<ItemGroup Label="Packages used for testing">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private void ParseFieldProperty(ElementMetadata element, StringBuilder classBuil
else
{
elementOrder += 1;
AddXmlElementAnnotation(element, classBuilder, elementOrder);
AddXmlElementAnnotation(element, classBuilder, elementOrder, !isValueType && (element.Nillable ?? false));

// Temporary fix - as long as we use System.Text.Json for serialization and Newtonsoft.Json for
// deserialization, we need both JsonProperty and JsonPropertyName annotations.
Expand Down Expand Up @@ -265,16 +265,21 @@ private void ParseGroupProperty(ElementMetadata element, StringBuilder classBuil
}
}

private void AddXmlElementAnnotation(ElementMetadata element, StringBuilder classBuilder, int elementOrder)
private void AddXmlElementAnnotation(ElementMetadata element, StringBuilder classBuilder, int elementOrder, bool addNillableAttribute = false)
{
if (element.OrderOblivious)
string additionalAttributeParams = string.Empty;
if (!element.OrderOblivious)
{
classBuilder.AppendLine($"""{Indent(2)}[XmlElement("{element.XName}")]""");
additionalAttributeParams += $", Order = {elementOrder}";
}
else

if (addNillableAttribute)
{
classBuilder.AppendLine($"""{Indent(2)}[XmlElement("{element.XName}", Order = {elementOrder})]""");
additionalAttributeParams += ", IsNullable = true";
}


classBuilder.AppendLine($"""{Indent(2)}[XmlElement("{element.XName}"{additionalAttributeParams})]""");
}

private void AddShouldSerializeForTagContent(ElementMetadata element, StringBuilder classBuilder, ModelMetadata modelMetadata)
Expand Down
23 changes: 23 additions & 0 deletions backend/src/Designer/Configuration/FeedbackFormSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Altinn.Studio.Designer.Configuration.Marker;

namespace Altinn.Studio.Designer.Configuration
{
/// <summary>
/// Class representation for basic FeedbackForm configuration
/// </summary>
public class FeedbackFormSettings : ISettingsMarker
{
/// <summary>
/// Gets or sets the Slack settings
/// </summary>
public SlackSettings SlackSettings { get; set; }
}

public class SlackSettings
{
/// <summary>
/// Gets or sets the WebhookUrl
/// </summary>
public string WebhookUrl { get; set; }
}
}
10 changes: 10 additions & 0 deletions backend/src/Designer/Configuration/RedisCacheSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Altinn.Studio.Designer.Configuration.Marker;

namespace Altinn.Studio.Designer.Configuration;

public class RedisCacheSettings : ISettingsMarker
{
public bool UseRedisCache { get; set; } = false;
public string ConnectionString { get; set; }
public string InstanceName { get; set; }
}
45 changes: 45 additions & 0 deletions backend/src/Designer/Controllers/AnsattPortenController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Threading.Tasks;
using Altinn.Studio.Designer.Constants;
using Altinn.Studio.Designer.Models.Dto;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.FeatureManagement.Mvc;

namespace Altinn.Studio.Designer.Controllers;

[FeatureGate(StudioFeatureFlags.AnsattPorten)]
[Route("designer/api/[controller]")]
[ApiController]
public class AnsattPortenController : ControllerBase
{
[Authorize(AnsattPortenConstants.AnsattportenAuthorizationPolicy)]
[HttpGet("login")]
public async Task<IActionResult> Login([FromQuery(Name = "redirect_to")] string redirectTo)
{
await Task.CompletedTask;
if (!Url.IsLocalUrl(redirectTo))
{
return Forbid();
}

return LocalRedirect(redirectTo);
}

[AllowAnonymous]
[HttpGet("auth-status")]
public async Task<IActionResult> AuthStatus()
{
await Task.CompletedTask;
var authenticateResult =
await HttpContext.AuthenticateAsync(AnsattPortenConstants.AnsattportenAuthenticationScheme);

var authStatus = new AuthStatus
{
IsLoggedIn = authenticateResult.Succeeded
};

return Ok(authStatus);
}

}
9 changes: 3 additions & 6 deletions backend/src/Designer/Controllers/AppScopesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

namespace Altinn.Studio.Designer.Controllers;

[ApiController]
[FeatureGate(StudioFeatureFlags.AnsattPorten)]
[Route("designer/api/{org}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/app-scopes")]

public class AppScopesController(IMaskinPortenHttpClient maskinPortenHttpClient,
IAppScopesService appScopesService) : ControllerBase
{
Expand All @@ -27,7 +27,7 @@ public async Task<IActionResult> GetScopesFromMaskinPorten(string org, string ap
{
var scopes = await maskinPortenHttpClient.GetAvailableScopes(cancellationToken);

var reponse = new AppScopesResponse()
var response = new AppScopesResponse()
{
Scopes = scopes.Select(x => new MaskinPortenScopeDto()
{
Expand All @@ -36,10 +36,9 @@ public async Task<IActionResult> GetScopesFromMaskinPorten(string org, string ap
}).ToHashSet()
};

return Ok(reponse);
return Ok(response);
}


[Authorize]
[HttpPut]
public async Task UpsertAppScopes(string org, string app, [FromBody] AppScopesUpsertRequest appScopesUpsertRequest,
Expand All @@ -55,7 +54,6 @@ public async Task UpsertAppScopes(string org, string app, [FromBody] AppScopesUp
await appScopesService.UpsertScopesAsync(AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer), scopes, cancellationToken);
}


[Authorize]
[HttpGet]
public async Task<IActionResult> GetAppScopes(string org, string app, CancellationToken cancellationToken)
Expand All @@ -73,5 +71,4 @@ public async Task<IActionResult> GetAppScopes(string org, string app, Cancellati

return Ok(reponse);
}

}
75 changes: 75 additions & 0 deletions backend/src/Designer/Controllers/FeedbackFormController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Altinn.Studio.Designer.Configuration;
using Altinn.Studio.Designer.Models.Dto;
using Altinn.Studio.Designer.TypedHttpClients.Slack;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;

namespace Altinn.Studio.Designer.Controllers;

/// <summary>
/// Controller containing actions related to feedback form
/// </summary>
[Authorize]
[ApiController]
[ValidateAntiForgeryToken]
[Route("designer/api/{org}/{app:regex(^(?!datamodels$)[[a-z]][[a-z0-9-]]{{1,28}}[[a-z0-9]]$)}/feedbackform")]
public class FeedbackFormController : ControllerBase
{
private readonly ISlackClient _slackClient;
private readonly GeneralSettings _generalSettings;

/// <summary>
/// Initializes a new instance of the <see cref="FeedbackFormController"/> class.
/// </summary>
/// <param name="slackClient">A http client to send messages to slack</param>
/// <param name="generalSettings">the general settings</param>
public FeedbackFormController(ISlackClient slackClient, GeneralSettings generalSettings)
{
_slackClient = slackClient;
_generalSettings = generalSettings;
}

/// <summary>
/// Endpoint for submitting feedback
/// </summary>
[HttpPost]
[Route("submit")]
public async Task<IActionResult> SubmitFeedback([FromRoute] string org, [FromRoute] string app, [FromBody] FeedbackForm feedback, CancellationToken cancellationToken)
{
if (feedback == null)
{
return BadRequest("Feedback object is null");
}

if (feedback.Answers == null || feedback.Answers.Count == 0)
{
return BadRequest("Feedback answers are null or empty");
}

if (!feedback.Answers.ContainsKey("org"))
{
feedback.Answers.Add("org", org);
}

if (!feedback.Answers.ContainsKey("app"))
{
feedback.Answers.Add("app", app);
}

if (!feedback.Answers.ContainsKey("env"))
{
feedback.Answers.Add("env", _generalSettings.HostName);
}

await _slackClient.SendMessage(new SlackRequest
{
Text = JsonSerializer.Serialize(feedback.Answers, new JsonSerializerOptions { WriteIndented = true })
}, cancellationToken);

return Ok();
}
}
22 changes: 20 additions & 2 deletions backend/src/Designer/Controllers/ResourceAdminController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ public async Task<ActionResult> ImportResource(string org, string serviceCode, i
public async Task<ActionResult> GetDelegationCount(string org, string serviceCode, int serviceEdition, string env)
{
ServiceResource resource = await _resourceRegistry.GetServiceResourceFromService(serviceCode, serviceEdition, env.ToLower());
if (resource?.HasCompetentAuthority == null || !resource.HasCompetentAuthority.Orgcode.Equals(org, StringComparison.InvariantCultureIgnoreCase))
if (!IsServiceOwner(resource, org))
{
return new UnauthorizedResult();
}
Expand All @@ -348,7 +348,7 @@ public async Task<ActionResult> GetDelegationCount(string org, string serviceCod
public async Task<ActionResult> MigrateDelegations([FromBody] ExportDelegationsRequestBE delegationRequest, string org, string env)
{
ServiceResource resource = await _resourceRegistry.GetServiceResourceFromService(delegationRequest.ServiceCode, delegationRequest.ServiceEditionCode, env.ToLower());
if (resource?.HasCompetentAuthority == null || !resource.HasCompetentAuthority.Orgcode.Equals(org, StringComparison.InvariantCultureIgnoreCase))
if (!IsServiceOwner(resource, org))
{
return new UnauthorizedResult();
}
Expand Down Expand Up @@ -1168,6 +1168,24 @@ private async Task<OrgList> GetOrgList()
return orgList;
}

private static bool IsServiceOwner(ServiceResource? resource, string loggedInOrg)

Check warning on line 1171 in backend/src/Designer/Controllers/ResourceAdminController.cs

View workflow job for this annotation

GitHub Actions / Analyze

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1171 in backend/src/Designer/Controllers/ResourceAdminController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (ubuntu-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1171 in backend/src/Designer/Controllers/ResourceAdminController.cs

View workflow job for this annotation

GitHub Actions / Run integration tests against actual gitea and db

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1171 in backend/src/Designer/Controllers/ResourceAdminController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (windows-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 1171 in backend/src/Designer/Controllers/ResourceAdminController.cs

View workflow job for this annotation

GitHub Actions / Run dotnet build and test (macos-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
{
if (resource?.HasCompetentAuthority == null)
{
return false;
}

bool isOwnedByOrg = resource.HasCompetentAuthority.Orgcode.Equals(loggedInOrg, StringComparison.InvariantCultureIgnoreCase);

if (OrgUtil.IsTestEnv(loggedInOrg))
{
return isOwnedByOrg || resource.HasCompetentAuthority.Orgcode.Equals("acn", StringComparison.InvariantCultureIgnoreCase);
}

return isOwnedByOrg;

}

private async Task<ResourceVersionInfo> AddEnvironmentResourceStatus(string env, string id)
{
ServiceResource resource = await _resourceRegistry.GetResource(id, env);
Expand Down
9 changes: 2 additions & 7 deletions backend/src/Designer/Designer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
<Configurations>Release;Debug</Configurations>
</PropertyGroup>

<PropertyGroup>
<CodeAnalisysCompatibleVersion>4.5.0</CodeAnalisysCompatibleVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Altinn.App.Core" />
<PackageReference Include="Altinn.Authorization.ABAC" />
Expand All @@ -26,7 +22,6 @@
<PackageReference Include="Altinn.Common.AccessTokenClient" />
<PackageReference Include="Altinn.Platform.Storage.Interface" />
<PackageReference Include="Azure.Security.KeyVault.Secrets" />
<PackageReference Include="Community.Microsoft.Extensions.Caching.PostgreSql" />
<PackageReference Include="CompilerAttributes" />
<PackageReference Include="DistributedLock.Postgres" />
<PackageReference Include="DotNetEnv" />
Expand All @@ -42,6 +37,7 @@
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" />
<PackageReference Include="Microsoft.Azure.KeyVault" />
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
Expand All @@ -50,6 +46,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" />
<PackageReference Include="Microsoft.FeatureManagement.AspNetCore" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" />
Expand All @@ -59,8 +56,6 @@
<PackageReference Include="NuGet.Versioning" />
<PackageReference Include="Polly" />
<PackageReference Include="Scrutor" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="$(CodeAnalisysCompatibleVersion)" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="$(CodeAnalisysCompatibleVersion)" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit 28867e0

Please sign in to comment.