feat/authorization (#39)
move client merge add Gut authentication and authorization merge dummy Co-authored-by: MaxchilKH <m.w.bohdanowicz@gmail.com>
This commit is contained in:
parent
5884a444a9
commit
54dfcaa7e7
@ -7,8 +7,13 @@ services:
|
||||
CONNECTIONSTRINGS__INTERNSHIPDATABASE: "Host=db.postgres;Port=5432;Database=postgres;Username=postgres;Password=szwoniu"
|
||||
ASPNETCORE_ENVIRONMENT: Development
|
||||
ASPNETCORE_URLS: http://+:80
|
||||
SECURITYOPTIONS__SECRET: PDv7DrqznYL6nv7DrqzjnQYO9JxIsWdcjnQYL6nu0f
|
||||
SECURITYOPTIONS__SECRET: iewaiwie3aig9wi3chieBai9eephai
|
||||
SECURITYOPTIONS__EXPIRATION: 20
|
||||
SECURITYOPTIONS__BASEURL: https://logowanie.pg.edu.pl
|
||||
SECURITYOPTIONS__TOKENPATH: /oauth2.0/accessToken
|
||||
SECURITYOPTIONS__PROFILEPATH: /oauth2.0/profile
|
||||
SECURITYOPTIONS__CLIENTID: PraktykiClientId
|
||||
SECURITYOPTIONS__REDIRECTURL: https://system-praktyk.stg.kadet.net/user/login/check/pg
|
||||
depends_on:
|
||||
- db.postgres
|
||||
ports:
|
||||
|
@ -1,11 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OAuth" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,20 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace AspNet.Security.OAuth.MyGut
|
||||
{
|
||||
public static class AuthenticationBuilderExtension
|
||||
{
|
||||
public static AuthenticationBuilder AddMyGut(this AuthenticationBuilder builder) =>
|
||||
builder.AddMyGut(MyGutAuthenticationDefaults.AuthenticationScheme, MyGutAuthenticationDefaults.DisplayName, options => { });
|
||||
|
||||
public static AuthenticationBuilder AddMyGut(
|
||||
this AuthenticationBuilder builder,
|
||||
string scheme,
|
||||
string caption,
|
||||
Action<MyGutAuthenticationOptions> configuration
|
||||
) =>
|
||||
builder.AddOAuth<MyGutAuthenticationOptions, MyGutAuthenticationHandler>(scheme, caption, configuration);
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
namespace AspNet.Security.OAuth.MyGut
|
||||
{
|
||||
public static class MyGutAuthenticationConstants
|
||||
{
|
||||
public static class Urls
|
||||
{
|
||||
}
|
||||
|
||||
public static class Claims
|
||||
{
|
||||
public const string AlbumNumber = "urn:mygut:albumnumber";
|
||||
}
|
||||
|
||||
public static class UrlQueryParameterValues
|
||||
{
|
||||
public const string Consent = "consent";
|
||||
public const string None = "none";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
namespace AspNet.Security.OAuth.MyGut
|
||||
{
|
||||
public static class MyGutAuthenticationDefaults
|
||||
{
|
||||
public const string AuthenticationScheme = "MyGut";
|
||||
|
||||
public const string DisplayName = "MyGut";
|
||||
|
||||
public const string Issuer = "MyGut";
|
||||
|
||||
public const string CallbackPath = "/signin-mygut";
|
||||
|
||||
public const string AuthorizationEndpoint = "https://logowanie.pg.edu.pl/login";
|
||||
|
||||
public const string TokenEndpoint = "https://logowanie.pg.edu.pl/login";
|
||||
|
||||
public const string UserInformationEndpoint = "https://logowanie.pg.edu.pl/login";
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace AspNet.Security.OAuth.MyGut
|
||||
{
|
||||
public class MyGutAuthenticationHandler : OAuthHandler<MyGutAuthenticationOptions>
|
||||
{
|
||||
public MyGutAuthenticationHandler(
|
||||
IOptionsMonitor<MyGutAuthenticationOptions> options,
|
||||
ILoggerFactory logger,
|
||||
UrlEncoder encoder,
|
||||
ISystemClock clock) : base(options, logger, encoder, clock)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authentication.OAuth;
|
||||
|
||||
namespace AspNet.Security.OAuth.MyGut
|
||||
{
|
||||
public class MyGutAuthenticationOptions : OAuthOptions
|
||||
{
|
||||
public MyGutAuthenticationOptions()
|
||||
{
|
||||
ClaimsIssuer = MyGutAuthenticationDefaults.Issuer;
|
||||
CallbackPath = MyGutAuthenticationDefaults.CallbackPath;
|
||||
AuthorizationEndpoint = MyGutAuthenticationDefaults.AuthorizationEndpoint;
|
||||
TokenEndpoint = MyGutAuthenticationDefaults.TokenEndpoint;
|
||||
UserInformationEndpoint = MyGutAuthenticationDefaults.UserInformationEndpoint;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,18 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using InternshipSystem.Api.Options;
|
||||
using InternshipSystem.Api.Security;
|
||||
using InternshipSystem.Core;
|
||||
using InternshipSystem.Repository;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Serilog;
|
||||
|
||||
namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
@ -19,12 +22,18 @@ namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
private readonly InternshipDbContext _context;
|
||||
private readonly JwtTokenService _tokenService;
|
||||
private readonly GutCasClient _loginClient;
|
||||
private readonly SecurityOptions _securityOptions;
|
||||
|
||||
public AccessController(IOptions<SecurityOptions> options, InternshipDbContext context, JwtTokenService tokenService)
|
||||
public AccessController(
|
||||
IOptions<SecurityOptions> options,
|
||||
InternshipDbContext context,
|
||||
JwtTokenService tokenService,
|
||||
GutCasClient loginClient)
|
||||
{
|
||||
_context = context;
|
||||
_tokenService = tokenService;
|
||||
_loginClient = loginClient;
|
||||
_securityOptions = options.Value;
|
||||
}
|
||||
|
||||
@ -32,16 +41,47 @@ namespace InternshipSystem.Api.Controllers
|
||||
[HttpGet("login")]
|
||||
public async Task<ActionResult> Authenticate(string code, CancellationToken cancellationToken)
|
||||
{
|
||||
var token = await _loginClient.GetCasTokenAsync(code, cancellationToken);
|
||||
|
||||
var casData = await _loginClient.GetProfileAsync(token, cancellationToken);
|
||||
|
||||
if (!long.TryParse(casData.PersonNumber, out var id))
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
var student = await _context.Students.FirstOrDefaultAsync(s => s.Id == id);
|
||||
|
||||
if (student == null)
|
||||
{
|
||||
student = CreateStudentWithCasData(casData);
|
||||
await _context.Students.AddAsync(student, cancellationToken);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
var identity = new ClaimsIdentity(new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, "Jan"),
|
||||
new Claim(ClaimTypes.Surname, "Kowalski"),
|
||||
new Claim(InternshipClaims.PersonNumber, "1")
|
||||
new Claim(ClaimTypes.Name, student.FirstName),
|
||||
new Claim(ClaimTypes.Surname, student.LastName),
|
||||
new Claim(InternshipClaims.PersonNumber, student.Id.ToString())
|
||||
});
|
||||
|
||||
return Ok(_tokenService.generateToken(identity));
|
||||
}
|
||||
|
||||
[HttpGet("/dev/login")]
|
||||
public async Task<ActionResult> Authenticate(CancellationToken cancellationToken)
|
||||
{
|
||||
var identity = new ClaimsIdentity(new[]
|
||||
{
|
||||
new Claim(ClaimTypes.Name, "firstname"),
|
||||
new Claim(ClaimTypes.Surname, "lastname"),
|
||||
new Claim(InternshipClaims.PersonNumber, "1")
|
||||
});
|
||||
|
||||
return Ok(_tokenService.generateToken(identity));
|
||||
}
|
||||
|
||||
[HttpGet("loginEdition")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult> LoginIntoEdition(Guid editionId, [FromServices] User user, CancellationToken token)
|
||||
@ -64,5 +104,16 @@ namespace InternshipSystem.Api.Controllers
|
||||
|
||||
return Ok(_tokenService.generateToken(newIdentity));
|
||||
}
|
||||
|
||||
private Student CreateStudentWithCasData(CasUserData casData)
|
||||
{
|
||||
var id = long.Parse(casData.PersonNumber);
|
||||
var firstName = casData.FirstName;
|
||||
var lastName = casData.LastName;
|
||||
var email = casData.Mail.First(s => s.EndsWith("@student.pg.edu.pl"));
|
||||
var albumNumber = int.Parse(casData.AlbumNumber);
|
||||
|
||||
return Student.CreateStudent(id, firstName, lastName, email, albumNumber);
|
||||
}
|
||||
}
|
||||
}
|
75
src/InternshipSystem.Api/Controllers/GutCasClient.cs
Normal file
75
src/InternshipSystem.Api/Controllers/GutCasClient.cs
Normal file
@ -0,0 +1,75 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using InternshipSystem.Api.Options;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
public class GutCasClient
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
private readonly SecurityOptions _securityOptions;
|
||||
|
||||
public GutCasClient(HttpClient client, IOptions<SecurityOptions> options)
|
||||
{
|
||||
_securityOptions = options.Value;
|
||||
|
||||
client.BaseAddress = _securityOptions.BaseUrl;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
public async Task<string> GetCasTokenAsync(string code, CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new HttpRequestMessage
|
||||
{
|
||||
Method = HttpMethod.Post,
|
||||
Content = new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "grant_type", "authorization_code" },
|
||||
{ "client_id", _securityOptions.ClientId },
|
||||
{ "client_secret", _securityOptions.Secret },
|
||||
{ "redirect_uri", _securityOptions.RedirectUrl.ToString() },
|
||||
{ "code", code }
|
||||
}),
|
||||
RequestUri = _securityOptions.TokenPath
|
||||
};
|
||||
|
||||
var response = await _client.SendAsync(request, cancellationToken);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync();
|
||||
|
||||
var value = await JsonSerializer.DeserializeAsync<Dictionary<string, object>>(stream);
|
||||
|
||||
return value["access_token"].ToString();
|
||||
}
|
||||
|
||||
|
||||
public async Task<CasUserData> GetProfileAsync(string token, CancellationToken cancellationToken)
|
||||
{
|
||||
var request = new HttpRequestMessage
|
||||
{
|
||||
Method = HttpMethod.Get,
|
||||
Content = new StringContent(string.Empty),
|
||||
RequestUri = _securityOptions.ProfilePath
|
||||
};
|
||||
|
||||
request.Headers.Authorization = AuthenticationHeaderValue.Parse($"Bearer {token}");
|
||||
request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
|
||||
|
||||
var response = await _client.SendAsync(request, cancellationToken);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync();
|
||||
|
||||
var result = await JsonSerializer.DeserializeAsync<CasUserProfile>(
|
||||
stream,
|
||||
new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
});
|
||||
|
||||
return result.Attributes;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,10 +2,15 @@
|
||||
using System.Threading.Tasks;
|
||||
using InternshipSystem.Api.Queries;
|
||||
using InternshipSystem.Api.Security;
|
||||
using InternshipSystem.Core.Commands;
|
||||
using InternshipSystem.Repository;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using InternshipSystem.Api.Security;
|
||||
using InternshipSystem.Api.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
@ -22,7 +27,7 @@ namespace InternshipSystem.Api.Controllers
|
||||
/// <summary>
|
||||
/// Validate and add filled internship registration form
|
||||
/// </summary>
|
||||
/// <param name="registrationQuery">Internship registration data</param>
|
||||
/// <param name="updateRegistration">Internship registration data</param>
|
||||
/// <response code="200">If registration form was successfully added</response>
|
||||
/// <response code="400">If the provided registration query was malformed</response>
|
||||
/// <response code="401">This action is only available for authorized student registered for current edition</response>
|
||||
|
@ -23,7 +23,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../InternshipSystem.Core/InternshipSystem.Core.csproj" />
|
||||
<ProjectReference Include="../InternshipSystem.Repository/InternshipSystem.Repository.csproj" />
|
||||
<ProjectReference Include="..\AspNet.Security.OAuth.MyGut\AspNet.Security.OAuth.MyGut.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,8 +1,21 @@
|
||||
namespace InternshipSystem.Api.Options
|
||||
using System;
|
||||
using System.Security.Policy;
|
||||
|
||||
namespace InternshipSystem.Api.Options
|
||||
{
|
||||
public class SecurityOptions
|
||||
{
|
||||
public string Secret { get; set; }
|
||||
public double Expiration { get; set; }
|
||||
|
||||
public Uri BaseUrl { get; set; }
|
||||
|
||||
public Uri TokenPath { get; set; }
|
||||
|
||||
public Uri ProfilePath { get; set; }
|
||||
|
||||
public Uri RedirectUrl { get; set; }
|
||||
|
||||
public string ClientId { get; set; }
|
||||
}
|
||||
}
|
14
src/InternshipSystem.Api/Result/CasUserData.cs
Normal file
14
src/InternshipSystem.Api/Result/CasUserData.cs
Normal file
@ -0,0 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
public class CasUserData
|
||||
{
|
||||
public string AlbumNumber { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public List<string> Mail { get; set; }
|
||||
public string PersonNumber { get; set; }
|
||||
public List<string> Pg_Cui_Portalroles { get; set; }
|
||||
}
|
||||
}
|
10
src/InternshipSystem.Api/Result/CasUserProfile.cs
Normal file
10
src/InternshipSystem.Api/Result/CasUserProfile.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace InternshipSystem.Api.Controllers
|
||||
{
|
||||
public class CasUserProfile
|
||||
{
|
||||
public string Service { get; set; }
|
||||
public CasUserData Attributes { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Client_Id { get; set; }
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using AutoMapper;
|
||||
using InternshipSystem.Api.Controllers;
|
||||
using InternshipSystem.Api.Extensions;
|
||||
using InternshipSystem.Api.ModelBinders;
|
||||
using InternshipSystem.Api.Options;
|
||||
@ -26,32 +27,38 @@ namespace InternshipSystem.Api
|
||||
public Startup(IConfiguration configuration) =>
|
||||
Configuration = configuration;
|
||||
|
||||
public void ConfigureServices(IServiceCollection services) =>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services
|
||||
.Configure<SecurityOptions>(Configuration.GetSection("SecurityOptions"))
|
||||
.AddDbContext<InternshipDbContext>(o => o.UseNpgsql(Configuration.GetConnectionString("InternshipDatabase")))
|
||||
.AddSwaggerGen(options =>
|
||||
.Configure<SecurityOptions>(Configuration.GetSection("SecurityOptions"));
|
||||
|
||||
services
|
||||
.AddStudentAuthentication()
|
||||
.AddAuthorization(o =>
|
||||
{
|
||||
o.AddPolicy(Policies.RegisteredOnly, policy => policy.RequireClaim("Edition"));
|
||||
})
|
||||
.AddHttpClient<GutCasClient>();
|
||||
|
||||
services
|
||||
.AddDbContext<InternshipDbContext>(o =>
|
||||
o.UseNpgsql(Configuration.GetConnectionString("InternshipDatabase")))
|
||||
.AddScoped<DatabaseFiller>()
|
||||
.AddScoped<IInternshipService, InternshipService>()
|
||||
.AddScoped<JwtTokenService>()
|
||||
.AddAutoMapper(cfg => cfg.AddProfile<ApiProfile>());
|
||||
|
||||
services
|
||||
.AddSwaggerGen(options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new OpenApiInfo {Title = "InternshipSystem Api - TEST", Version = "v1"});
|
||||
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
|
||||
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
|
||||
options.IncludeXmlComments(xmlPath);
|
||||
})
|
||||
.AddScoped<DatabaseFiller>()
|
||||
.AddScoped<IInternshipService, InternshipService>()
|
||||
.AddScoped<JwtTokenService>()
|
||||
.AddAutoMapper(cfg => cfg.AddProfile<ApiProfile>())
|
||||
.AddStudentAuthentication()
|
||||
.AddAuthorization(o =>
|
||||
{
|
||||
o.AddPolicy(Policies.RegisteredOnly, policy => policy.RequireClaim("Edition"));
|
||||
})
|
||||
.AddControllers(o =>
|
||||
{
|
||||
o.ModelBinderProviders.Insert(0, new UserBinderProvider());
|
||||
})
|
||||
;
|
||||
|
||||
.AddControllers(o => { o.ModelBinderProviders.Insert(0, new UserBinderProvider()); });
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
|
33
src/InternshipSystem.Core/Commands/UpdateRegistrationForm.cs
Normal file
33
src/InternshipSystem.Core/Commands/UpdateRegistrationForm.cs
Normal file
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using InternshipSystem.Core.Entity.Internship;
|
||||
|
||||
namespace InternshipSystem.Core.Commands
|
||||
{
|
||||
public class UpdateRegistrationForm
|
||||
{
|
||||
public UpdateCompany? Company { get; set; }
|
||||
public DateTime? Start { get; set; }
|
||||
public DateTime? End { get; set; }
|
||||
public InternshipType? Type { get; set; }
|
||||
}
|
||||
|
||||
public struct UpdateCompany
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
public string Nip { get; set; }
|
||||
public string Name { get; set; }
|
||||
public UpdateBranchOffice? BranchOffice { get; set; }
|
||||
|
||||
public bool IsUpdate => Id.HasValue;
|
||||
}
|
||||
|
||||
public struct UpdateBranchOffice
|
||||
{
|
||||
public long? Id { get; set; }
|
||||
public string Street { get; set; }
|
||||
public string Building { get; set; }
|
||||
public string City { get; set; }
|
||||
public string PostalCode { get; set; }
|
||||
public string Country { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using InternshipSystem.Core.Commands;
|
||||
|
||||
namespace InternshipSystem.Core
|
||||
{
|
||||
@ -24,5 +26,10 @@ namespace InternshipSystem.Core
|
||||
{
|
||||
Branches.Add(createBranch);
|
||||
}
|
||||
|
||||
public static Company CreateCompany(UpdateCompany updateCompany)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ namespace InternshipSystem.Core
|
||||
public DateTime ReportingStart { get; set; }
|
||||
public Course Course { get; set; }
|
||||
public List<Internship> Internships { get; set; }
|
||||
|
||||
public InternshipType AllowedInternshipTypes { get; set; }
|
||||
|
||||
public List<EditionSubject> AvailableSubjects { get; set; }
|
||||
public List<InternshipType> AvailableInternshipTypes { get; set; }
|
||||
|
||||
@ -40,5 +43,15 @@ namespace InternshipSystem.Core
|
||||
|
||||
Internships.Add(internship);
|
||||
}
|
||||
|
||||
public bool IsDateDuringEdition(DateTime start, DateTime end)
|
||||
{
|
||||
return start >= EditionStart && end <= EditionFinish;
|
||||
}
|
||||
|
||||
public bool IsInternshiptypeAllowed(InternshipType internshipType)
|
||||
{
|
||||
return AllowedInternshipTypes.HasFlag(internshipType);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using InternshipSystem.Core.Commands;
|
||||
using InternshipSystem.Core.ValueObject;
|
||||
|
||||
namespace InternshipSystem.Core
|
||||
{
|
||||
@ -12,9 +15,10 @@ namespace InternshipSystem.Core
|
||||
public Report Report { get; set; }
|
||||
public List<Document> Approvals { get; set; }
|
||||
public List<Document> Documentation { get; set; }
|
||||
public float? Grade { get; set; }
|
||||
|
||||
public Edition Edition { get; set; }
|
||||
|
||||
public float? Grade { get; set; }
|
||||
|
||||
public void UpdateDocument(Document document)
|
||||
{
|
||||
@ -47,5 +51,38 @@ namespace InternshipSystem.Core
|
||||
|
||||
return internship;
|
||||
}
|
||||
|
||||
public void UpdateInternshipRegistration(UpdateRegistrationForm updateRegistration)
|
||||
{
|
||||
var start = updateRegistration.Start ?? InternshipRegistration.Start;
|
||||
var end = updateRegistration.End ?? InternshipRegistration.End;
|
||||
|
||||
if (!Edition.IsDateDuringEdition(start, end))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(InternshipRegistration.Start) + nameof(InternshipRegistration.End),"Date outside of edition boundaries");
|
||||
}
|
||||
|
||||
var internshipType = updateRegistration.Type ?? InternshipRegistration.Type;
|
||||
|
||||
if (!Edition.IsInternshiptypeAllowed(internshipType))
|
||||
{
|
||||
throw new ArgumentException("Internship type not allowed for this edition", nameof(updateRegistration.Type));
|
||||
}
|
||||
|
||||
var company = InternshipRegistration.Company;
|
||||
if (company == null)
|
||||
{
|
||||
if (!updateRegistration.Company.HasValue)
|
||||
{
|
||||
throw new ArgumentException("Company");
|
||||
}
|
||||
|
||||
company = Company.CreateCompany(updateRegistration.Company.Value);
|
||||
|
||||
|
||||
}
|
||||
|
||||
InternshipRegistration.Update(start, end, internshipType);
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,13 @@ namespace InternshipSystem.Core
|
||||
{
|
||||
return new InternshipRegistration();
|
||||
}
|
||||
|
||||
public void Update(DateTime start, DateTime end, InternshipType internshipType)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
Type = internshipType;
|
||||
}
|
||||
|
||||
public void UpdateCompany(Company newCompany)
|
||||
{
|
||||
|
@ -9,6 +9,17 @@ namespace InternshipSystem.Core
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public int Semester { get; set; }
|
||||
|
||||
public static Student CreateStudent(long id, string firstName, string lastName, string email, in int albumNumber)
|
||||
{
|
||||
return new Student
|
||||
{
|
||||
Id = id,
|
||||
AlbumNumber = albumNumber,
|
||||
FirstName = firstName,
|
||||
LastName = lastName,
|
||||
Email = email
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -223,7 +223,6 @@ namespace InternshipSystem.Repository
|
||||
LastName = "Kowalski",
|
||||
AlbumNumber = 123456,
|
||||
Email = "s123456@student.pg.edu.pl",
|
||||
Semester = 4,
|
||||
},
|
||||
InternshipRegistration = new InternshipRegistration
|
||||
{
|
||||
@ -273,7 +272,6 @@ namespace InternshipSystem.Repository
|
||||
LastName = "Kołek",
|
||||
AlbumNumber = 102137,
|
||||
Email = "s102137@student.pg.edu.pl",
|
||||
Semester = 6,
|
||||
},
|
||||
InternshipRegistration = new InternshipRegistration
|
||||
{
|
||||
|
@ -6,6 +6,10 @@
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\InternshipSystem.Api\InternshipSystem.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="../../props/Directory.Tests.Build.props" />
|
||||
|
||||
</Project>
|
||||
|
@ -1,6 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using InternshipSystem.Api.Controllers;
|
||||
using Machine.Specifications;
|
||||
|
||||
namespace InternshipSystem.Api.Test
|
||||
{
|
||||
[Subject(typeof(JsonSerializer))]
|
||||
class When_deserializing_cas
|
||||
{
|
||||
private static string json;
|
||||
|
||||
|
||||
private Establish context = () =>
|
||||
{
|
||||
// {
|
||||
// "service": "https://system-praktyk.stg.kadet.net/user/login/code",
|
||||
// "attributes": {
|
||||
// "albumNumber": "165581",
|
||||
// "firstName": "Kacper",
|
||||
// "lastName": "Donat",
|
||||
// "mail": [
|
||||
// "kacdonat@pg.edu.pl",
|
||||
// "kacper.donat@pg.edu.pl",
|
||||
// "s165581@student.pg.edu.pl"
|
||||
// ],
|
||||
// "personNumber": "1101074",
|
||||
// "PG_CUI_PORTALROLES": [
|
||||
// "ROLE_EKONTAKT_PROD",
|
||||
// "RP_STUDENT",
|
||||
// "RP_USER",
|
||||
// "ROLE_TRAC",
|
||||
// "ROLE_HUDSON",
|
||||
// "ROLE_WWW_ADMIN",
|
||||
// "RP_PRACOWNIK"
|
||||
// ]
|
||||
// },
|
||||
// "id": "1101074",
|
||||
// "client_id": "PraktykiClientId"
|
||||
// }
|
||||
|
||||
json =
|
||||
" {\r\n \"service\": \"https://system-praktyk.stg.kadet.net/user/login/code\",\r\n \"attributes\": {\r\n \"albumNumber\": \"165581\",\r\n \"firstName\": \"Kacper\",\r\n \"lastName\": \"Donat\",\r\n \"mail\": [\r\n \"kacdonat@pg.edu.pl\",\r\n \"kacper.donat@pg.edu.pl\",\r\n \"s165581@student.pg.edu.pl\"\r\n ],\r\n \"personNumber\": \"1101074\",\r\n \"PG_CUI_PORTALROLES\": [\r\n \"ROLE_EKONTAKT_PROD\",\r\n \"RP_STUDENT\",\r\n \"RP_USER\",\r\n \"ROLE_TRAC\",\r\n \"ROLE_HUDSON\",\r\n \"ROLE_WWW_ADMIN\",\r\n \"RP_PRACOWNIK\"\r\n ]\r\n },\r\n \"id\": \"1101074\",\r\n \"client_id\": \"PraktykiClientId\"\r\n }";
|
||||
|
||||
options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
};
|
||||
|
||||
private Because of = () => result = JsonSerializer.Deserialize<CasUserProfile>(json, options);
|
||||
|
||||
private It should_nop = () => true.ShouldBeTrue();
|
||||
|
||||
private static JsonSerializerOptions options;
|
||||
private static CasUserProfile result;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user