Archived
Private
Public Access
1
0

Login finished

This commit is contained in:
2023-04-15 17:54:37 +02:00
parent 7165ce1ae3
commit 72f08fc9cb
25 changed files with 412 additions and 62 deletions

25
.dockerignore Normal file
View File

@@ -0,0 +1,25 @@
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/.idea
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/azds.yaml
**/bin
**/charts
**/docker-compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

2
BetterIServ.Backend/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
obj

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.3" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<Content Include="..\.dockerignore">
<Link>.dockerignore</Link>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,42 @@
using System.Net;
using Microsoft.AspNetCore.Mvc;
namespace BetterIServ.Backend.Controllers;
[ApiController]
public class HelperController : Controller {
[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 e) {
return Unauthorized();
}
}
}

View File

@@ -0,0 +1,20 @@
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["BetterIServ.Backend/BetterIServ.Backend.csproj", "BetterIServ.Backend/"]
RUN dotnet restore "BetterIServ.Backend/BetterIServ.Backend.csproj"
COPY . .
WORKDIR "/src/BetterIServ.Backend"
RUN dotnet build "BetterIServ.Backend.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "BetterIServ.Backend.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "BetterIServ.Backend.dll"]

View File

@@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Cors.Infrastructure;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseCors(options => {
options.WithOrigins("http://localhost:8100");
options.AllowCredentials();
});
app.UseAuthorization();
app.MapControllers();
app.Run();

View File

@@ -0,0 +1,41 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:49668",
"sslPort": 44383
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5273",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7147;http://localhost:5273",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@@ -9,7 +9,8 @@
"build": "ng build", "build": "ng build",
"watch": "ng build --watch --configuration development", "watch": "ng build --watch --configuration development",
"test": "ng test", "test": "ng test",
"lint": "ng lint" "lint": "ng lint",
"serve": "ionic serve"
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {

View File

@@ -0,0 +1,41 @@
import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {Userdata} from "../entities/userdata";
import {firstValueFrom} from "rxjs";
@Injectable({
providedIn: 'root',
})
export class IServService {
public userdata?: Userdata;
private backend: string = "http://localhost:5273";
constructor(private client: HttpClient) {
const data = localStorage.getItem("userdata");
if (data != null) {
this.userdata = JSON.parse(data);
}
}
public async login(email: string, password: string): Promise<boolean> {
const split = email.split('@');
this.userdata = {};
this.userdata.username = split[0];
this.userdata.domain = split[1];
this.userdata.password = password;
const data = new FormData();
data.append("email", email);
data.append("password", password);
try {
this.userdata.token = await firstValueFrom(this.client.post(`${this.backend}/login`, data, {responseType: "text"}));
localStorage.setItem("userdata", JSON.stringify(this.userdata));
return true;
}catch (error) {
return false;
}
}
}

View File

@@ -2,9 +2,9 @@
<ion-split-pane contentId="main-content"> <ion-split-pane contentId="main-content">
<ion-menu contentId="main-content" type="overlay"> <ion-menu contentId="main-content" type="overlay">
<ion-content> <ion-content>
<ion-list id="inbox-list"> <ion-list>
<ion-list-header>Inbox</ion-list-header> <ion-list-header>BetterIServ</ion-list-header>
<ion-note>hi@ionicframework.com</ion-note> <ion-note>{{iserv.userdata?.username}}@{{iserv.userdata?.domain}}</ion-note>
<ion-menu-toggle auto-hide="false" *ngFor="let p of appPages; let i = index"> <ion-menu-toggle auto-hide="false" *ngFor="let p of appPages; let i = index">
<ion-item routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false" routerLinkActive="selected"> <ion-item routerDirection="root" [routerLink]="[p.url]" lines="none" detail="false" routerLinkActive="selected">
@@ -12,15 +12,13 @@
<ion-label>{{ p.title }}</ion-label> <ion-label>{{ p.title }}</ion-label>
</ion-item> </ion-item>
</ion-menu-toggle> </ion-menu-toggle>
</ion-list>
<ion-list id="labels-list"> <ion-menu-toggle auto-hide="false">
<ion-list-header>Labels</ion-list-header> <ion-item lines="none" detail="false" (click)="logout()">
<ion-icon aria-hidden="true" slot="start" ios="log-out-outline" md="log-out-sharp"></ion-icon>
<ion-item *ngFor="let label of labels" lines="none"> <ion-label>Ausloggen</ion-label>
<ion-icon aria-hidden="true" slot="start" ios="bookmark-outline" md="bookmark-sharp"></ion-icon> </ion-item>
<ion-label>{{ label }}</ion-label> </ion-menu-toggle>
</ion-item>
</ion-list> </ion-list>
</ion-content> </ion-content>
</ion-menu> </ion-menu>

View File

@@ -22,27 +22,17 @@ ion-menu.md ion-note {
padding-left: 10px; padding-left: 10px;
} }
ion-menu.md ion-list#inbox-list { ion-menu.md ion-list {
border-bottom: 1px solid var(--ion-color-step-150, #d7d8da); border-bottom: 1px solid var(--ion-color-step-150, #d7d8da);
} }
ion-menu.md ion-list#inbox-list ion-list-header { ion-menu.md ion-list ion-list-header {
font-size: 22px; font-size: 22px;
font-weight: 600; font-weight: 600;
min-height: 20px; min-height: 20px;
} }
ion-menu.md ion-list#labels-list ion-list-header {
font-size: 16px;
margin-bottom: 18px;
color: #757575;
min-height: 26px;
}
ion-menu.md ion-item { ion-menu.md ion-item {
--padding-start: 10px; --padding-start: 10px;
--padding-end: 10px; --padding-end: 10px;

View File

@@ -1,7 +1,8 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { RouterLink, RouterLinkActive } from '@angular/router'; import {Router, RouterLink, RouterLinkActive} from '@angular/router';
import { IonicModule } from '@ionic/angular'; import { IonicModule } from '@ionic/angular';
import {IServService} from "./Api/iserv.service";
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: 'app.component.html', templateUrl: 'app.component.html',
@@ -10,14 +11,26 @@ import { IonicModule } from '@ionic/angular';
imports: [IonicModule, RouterLink, RouterLinkActive, CommonModule], imports: [IonicModule, RouterLink, RouterLinkActive, CommonModule],
}) })
export class AppComponent { export class AppComponent {
public appPages = [ public appPages = [
{ title: 'Inbox', url: '/folder/inbox', icon: 'mail' }, { title: 'Übersicht', url: '/home', icon: 'home' },
{ title: 'Outbox', url: '/folder/outbox', icon: 'paper-plane' }, { title: 'E-Mail', url: '/email', icon: 'mail' },
{ title: 'Favorites', url: '/folder/favorites', icon: 'heart' }, { title: 'Dateien', url: '/files', icon: 'folder' },
{ title: 'Archived', url: '/folder/archived', icon: 'archive' }, { title: 'Aufgaben', url: '/tasks', icon: 'clipboard' },
{ title: 'Trash', url: '/folder/trash', icon: 'trash' }, { title: 'Stundenplan', url: '/schedule', icon: 'grid' },
{ title: 'Spam', url: '/folder/spam', icon: 'warning' }, { title: 'Vertretungsplan', url: '/substitution', icon: 'list' },
]; ];
public labels = ['Family', 'Friends', 'Notes', 'Work', 'Travel', 'Reminders']; public email = "leon.hoppe@hgbp.de";
constructor() {}
constructor(private router: Router, public iserv: IServService) {
if (localStorage.getItem("userdata") == null) {
this.router.navigate(["login"]);
}
}
public logout() {
localStorage.removeItem("userdata");
this.router.navigate(["login"]);
}
} }

View File

@@ -3,12 +3,15 @@ import { Routes } from '@angular/router';
export const routes: Routes = [ export const routes: Routes = [
{ {
path: '', path: '',
redirectTo: 'folder/inbox', redirectTo: 'home',
pathMatch: 'full', pathMatch: 'full',
}, },
{ {
path: 'folder/:id', path: 'home',
loadComponent: () => loadComponent: () => import('./home/home.page').then( m => m.HomePage)
import('./folder/folder.page').then((m) => m.FolderPage), },
{
path: 'login',
loadComponent: () => import('./login/login.page').then( m => m.LoginPage)
}, },
]; ];

View File

@@ -0,0 +1,6 @@
export interface Userdata {
domain?: string,
username?: string,
password?: string,
token?: string
}

View File

@@ -1,20 +0,0 @@
import { Component, inject, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { IonicModule } from '@ionic/angular';
@Component({
selector: 'app-folder',
templateUrl: './folder.page.html',
styleUrls: ['./folder.page.scss'],
standalone: true,
imports: [IonicModule],
})
export class FolderPage implements OnInit {
public folder!: string;
private activatedRoute = inject(ActivatedRoute);
constructor() {}
ngOnInit() {
this.folder = this.activatedRoute.snapshot.paramMap.get('id') as string;
}
}

View File

@@ -3,19 +3,19 @@
<ion-buttons slot="start"> <ion-buttons slot="start">
<ion-menu-button></ion-menu-button> <ion-menu-button></ion-menu-button>
</ion-buttons> </ion-buttons>
<ion-title>{{ folder }}</ion-title> <ion-title>Übersicht</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content [fullscreen]="true"> <ion-content [fullscreen]="true">
<ion-header collapse="condense"> <ion-header collapse="condense">
<ion-toolbar> <ion-toolbar>
<ion-title size="large">{{ folder }}</ion-title> <ion-title size="large">Übersicht</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<div id="container"> <div id="container">
<strong class="capitalize">{{ folder }}</strong> <strong class="capitalize">Übersicht</strong>
<p>Explore <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p> <p>Explore <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p>
</div> </div>
</ion-content> </ion-content>

View File

@@ -0,0 +1,19 @@
import {Component, OnInit} from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
@Component({
selector: 'app-home',
templateUrl: './home.page.html',
styleUrls: ['./home.page.scss'],
standalone: true,
imports: [IonicModule, CommonModule, FormsModule]
})
export class HomePage implements OnInit {
ngOnInit() {
}
}

View File

@@ -0,0 +1,20 @@
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>BetterIServ</ion-title>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<div class="card-container">
<ion-card>
<ion-card-header>
<ion-card-title>IServ Anmeldedaten</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-input label="E-Mail" type="email" #email/>
<ion-input label="Passwort" type="password" #password/>
<ion-button (click)="onLogin(email.value?.toString(), password.value?.toString())">Einloggen</ion-button>
</ion-card-content>
</ion-card>
</div>
</ion-content>

View File

@@ -0,0 +1,24 @@
.card-container {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
ion-card {
width: 90%;
ion-card-content {
display: flex;
flex-direction: column;
ion-input {
margin-block: 15px;
}
ion-button {
flex-grow: 0;
margin-inline: auto;
}
}
}
}

View File

@@ -0,0 +1,40 @@
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {AlertController, IonicModule} from '@ionic/angular';
import {IServService} from "../Api/iserv.service";
import {Router} from "@angular/router";
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
standalone: true,
imports: [IonicModule, CommonModule, FormsModule]
})
export class LoginPage implements OnInit {
constructor(private iservApi: IServService, private router: Router, private alerts: AlertController) { }
ngOnInit() {
}
public async onLogin(email?: string, password?: string) {
if (email == undefined || password == undefined) return;
if (await this.iservApi.login(email, password)) {
await this.router.navigate(['home']);
}else {
const alert = await this.alerts.create({
header: "Fehler",
message: "Die angegebenen Logindaten sind nicht korrekt!",
buttons: ['Ok']
});
await alert.present();
}
console.log(this.iservApi.userdata);
}
}

View File

@@ -6,6 +6,7 @@ import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { routes } from './app/app.routes'; import { routes } from './app/app.routes';
import { AppComponent } from './app/app.component'; import { AppComponent } from './app/app.component';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
import {HttpClientModule} from "@angular/common/http";
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();
@@ -15,6 +16,7 @@ bootstrapApplication(AppComponent, {
providers: [ providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
importProvidersFrom(IonicModule.forRoot({})), importProvidersFrom(IonicModule.forRoot({})),
importProvidersFrom(HttpClientModule),
provideRouter(routes), provideRouter(routes),
], ],
}); });

16
BetterIServ.sln Normal file
View File

@@ -0,0 +1,16 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BetterIServ.Backend", "BetterIServ.Backend\BetterIServ.Backend.csproj", "{B0FA03B9-0A4D-4A71-BF71-0CF374F108CE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B0FA03B9-0A4D-4A71-BF71-0CF374F108CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0FA03B9-0A4D-4A71-BF71-0CF374F108CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0FA03B9-0A4D-4A71-BF71-0CF374F108CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B0FA03B9-0A4D-4A71-BF71-0CF374F108CE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal