Archived
Private
Public Access
1
0

Reworked login system + added substitution page

This commit is contained in:
2023-04-23 20:38:12 +02:00
parent c15df303f0
commit 45a7457ef3
26 changed files with 412 additions and 79 deletions

View File

@@ -9,7 +9,9 @@
<ItemGroup>
<PackageReference Include="Aspose.Email" Version="23.3.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.3" />
<PackageReference Include="PuppeteerSharp" Version="9.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="WebDav.Client" Version="2.8.0" />
</ItemGroup>

View File

@@ -0,0 +1,50 @@
using BetterIServ.Backend.Entities;
using Microsoft.AspNetCore.Mvc;
using PuppeteerSharp;
using Credentials = BetterIServ.Backend.Entities.Credentials;
namespace BetterIServ.Backend.Controllers;
[ApiController]
[Route("auth")]
public class AuthController : ControllerBase {
[HttpPost("login")]
public async Task<ActionResult<AuthKeys>> GetAuthKeysV2([FromBody] Credentials credentials) {
await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
await using var page = await browser.NewPageAsync();
await page.GoToAsync($"https://{credentials.Domain}/iserv/auth/login");
await page.WaitForSelectorAsync("#form-username > input");
await page.Keyboard.TypeAsync(credentials.Username);
await page.Keyboard.PressAsync("Tab");
await page.Keyboard.TypeAsync(credentials.Password);
await page.ClickAsync("body > div > main > div > div.panel-body > form > div.row > div:nth-child(1) > button");
await Task.Delay(500);
var authKeys = new AuthKeys();
var cookies = await page.GetCookiesAsync();
foreach (var cookie in cookies) {
switch (cookie.Name) {
case "IServSession":
authKeys.Session = cookie.Value;
break;
case "IServSAT":
authKeys.Sat = cookie.Value;
break;
case "IServAuthSID":
authKeys.AuthSid = cookie.Value;
break;
case "IServSATId":
authKeys.SatId = cookie.Value;
break;
case "IServAuthSession":
authKeys.AuthSession = cookie.Value;
break;
}
}
return authKeys;
}
}

View File

@@ -1,42 +0,0 @@
using System.Net;
using Microsoft.AspNetCore.Mvc;
namespace BetterIServ.Backend.Controllers;
[ApiController]
public class HelperController : ControllerBase {
[HttpPost("/login")]
public async Task<ActionResult<string>> Login([FromForm] string email, [FromForm] string password) {
try {
using var client = new HttpClient(new HttpClientHandler { AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip, AllowAutoRedirect = false }) { Timeout = TimeSpan.FromSeconds(5) };
var split = email.Split("@");
var username = split[0];
var domain = split[1];
var form = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("_username", username),
new KeyValuePair<string, string>("_password", password)
});
var request = new HttpRequestMessage {
RequestUri = new Uri($"https://{domain}/iserv/auth/login"),
Method = HttpMethod.Post,
Content = form
};
var response = await client.SendAsync(request);
var header = response.Headers.GetValues("Set-Cookie").First();
var part = header.Split(";")[0];
if (!part.Contains("IServAuthSession")) throw new Exception();
return Ok(part.Replace("IServAuthSession=", ""));
}
catch (Exception) {
return Unauthorized();
}
}
}

View File

@@ -0,0 +1,61 @@
using System.Text;
using BetterIServ.Backend.Entities;
using HtmlAgilityPack;
using Microsoft.AspNetCore.Mvc;
namespace BetterIServ.Backend.Controllers;
[ApiController]
[Route("units")]
public class UnitsController : ControllerBase {
[HttpGet("substitution")]
public async Task<ActionResult<UnitsData>> GetToday([FromQuery] string url) {
var client = new HttpClient();
var buffer = await client.GetByteArrayAsync(url);
var raw = Encoding.GetEncoding("ISO-8859-1").GetString(buffer);
var html = new HtmlDocument();
html.LoadHtml(raw);
var data = new UnitsData {
Notifications = new List<string>(),
Substitutions = new List<Substitution>()
};
var info = html.DocumentNode.SelectSingleNode("//body/center[1]/table");
for (int i = 2; i < info.ChildNodes.Count; i++) {
var notification = info.ChildNodes[i];
if (notification.ChildNodes.Count == 2) {
data.Notifications.Add(
notification.ChildNodes[0].InnerText +
notification.ChildNodes[1].InnerText
);
}
else if (notification.ChildNodes.Count == 1) {
data.Notifications.Add(notification.ChildNodes[0].InnerText);
}
}
var substitutions = html.DocumentNode.SelectNodes("//body/center[1]")[0].ChildNodes[6];
for (int i = 4; i < substitutions.ChildNodes.Count; i++) {
var node = substitutions.ChildNodes[i];
if (node.ChildNodes.Count < 9) continue;
var substitution = new Substitution {
Class = node.ChildNodes[0].InnerText,
Times = node.ChildNodes[1].InnerText.Split(" - ").Select(int.Parse).ToArray(),
Type = node.ChildNodes[2].InnerText,
Representative = node.ChildNodes[3].InnerText,
Lesson = node.ChildNodes[4].InnerText,
Room = node.ChildNodes[6].InnerText,
Teacher = node.ChildNodes[7].InnerText,
Description = node.ChildNodes[9].InnerText
};
data.Substitutions.Add(substitution);
}
return data;
}
}

View File

@@ -0,0 +1,9 @@
namespace BetterIServ.Backend.Entities;
public struct AuthKeys {
public string Session { get; set; }
public string Sat { get; set; }
public string AuthSid { get; set; }
public string SatId { get; set; }
public string AuthSession { get; set; }
}

View File

@@ -1,8 +1,7 @@
namespace BetterIServ.Backend.Entities;
public class Credentials {
public string? Domain { get; set; }
public string? Username { get; set; }
public string? Password { get; set; }
public string? Token { get; set; }
}
public required string Domain { get; set; }
public required string Username { get; set; }
public required string Password { get; set; }
}

View File

@@ -2,8 +2,8 @@
public sealed class MailData : Credentials {
public string? MailBody { get; set; }
public string? Receiver { get; set; }
public string? Subject { get; set; }
public required string MailBody { get; set; }
public required string Receiver { get; set; }
public required string Subject { get; set; }
}

View File

@@ -1,5 +1,5 @@
namespace BetterIServ.Backend.Entities;
public class SingleResult<TValue> {
public struct SingleResult<TValue> {
public TValue? Value { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace BetterIServ.Backend.Entities;
public struct Substitution {
public string Class { get; set; }
public int[] Times { get; set; }
public string Type { get; set; }
public string Representative { get; set; }
public string Lesson { get; set; }
public string Room { get; set; }
public string Teacher { get; set; }
public string Description { get; set; }
}

View File

@@ -0,0 +1,6 @@
namespace BetterIServ.Backend.Entities;
public struct UnitsData {
public IList<string> Notifications { get; set; }
public IList<Substitution> Substitutions { get; set; }
}

View File

@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Cors.Infrastructure;
using PuppeteerSharp;
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultChromiumRevision);
var builder = WebApplication.CreateBuilder(args);