Routing for the privacy policy and legal notice.
Save those values in a new service, that will also watch for changes in config variables. UI is not good; this can be done later Share legal notice and privacy policy Created some containers for them
This commit is contained in:
parent
805b6a3fdd
commit
3e0618063b
@ -1,4 +1,8 @@
|
|||||||
{
|
{
|
||||||
|
"/apps/core/version": {
|
||||||
|
"target": "http://localhost:8000",
|
||||||
|
"secure": false
|
||||||
|
},
|
||||||
"/apps/users/login": {
|
"/apps/users/login": {
|
||||||
"target": "http://localhost:8000",
|
"target": "http://localhost:8000",
|
||||||
"secure": false
|
"secure": false
|
||||||
|
@ -1,12 +1,25 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { LoginComponent } from './site/login/login.component';
|
|
||||||
|
import { LoginComponent } from './site/login/components/login-wrapper/login.component';
|
||||||
|
import { LoginMaskComponent } from './site/login/components/login-mask/login-mask.component';
|
||||||
|
import { LoginLegalNoticeComponent } from './site/login/components/login-legal-notice/login-legal-notice.component';
|
||||||
|
import { LoginPrivacyPolicyComponent } from './site/login/components/login-privacy-policy/login-privacy-policy.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global app routing
|
* Global app routing
|
||||||
*/
|
*/
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'login', component: LoginComponent },
|
{
|
||||||
|
path: 'login',
|
||||||
|
component: LoginComponent,
|
||||||
|
children: [
|
||||||
|
{ path: '', component: LoginMaskComponent },
|
||||||
|
{ path: 'legalnotice', component: LoginLegalNoticeComponent },
|
||||||
|
{ path: 'privacypolicy', component: LoginPrivacyPolicyComponent }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
{ path: 'projector', loadChildren: './projector-container/projector-container.module#ProjectorContainerModule' },
|
{ path: 'projector', loadChildren: './projector-container/projector-container.module#ProjectorContainerModule' },
|
||||||
{ path: '', loadChildren: './site/site.module#SiteModule' },
|
{ path: '', loadChildren: './site/site.module#SiteModule' },
|
||||||
{ path: '**', redirectTo: '' }
|
{ path: '**', redirectTo: '' }
|
||||||
|
@ -5,6 +5,8 @@ import { Subject } from 'rxjs';
|
|||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
import { OpenSlidesComponent } from './openslides.component';
|
import { OpenSlidesComponent } from './openslides.component';
|
||||||
import { OpenSlidesService } from './core/services/openslides.service';
|
import { OpenSlidesService } from './core/services/openslides.service';
|
||||||
|
import { LoginDataService } from './core/services/login-data.service';
|
||||||
|
import { ConfigService } from './core/services/config.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Angular's global App Component
|
* Angular's global App Component
|
||||||
@ -38,7 +40,9 @@ export class AppComponent {
|
|||||||
public constructor(
|
public constructor(
|
||||||
translate: TranslateService,
|
translate: TranslateService,
|
||||||
private operator: OperatorService,
|
private operator: OperatorService,
|
||||||
private OpenSlides: OpenSlidesService
|
private OpenSlides: OpenSlidesService,
|
||||||
|
private configService: ConfigService,
|
||||||
|
private loginDataService: LoginDataService
|
||||||
) {
|
) {
|
||||||
// manually add the supported languages
|
// manually add the supported languages
|
||||||
translate.addLangs(['en', 'de', 'fr']);
|
translate.addLangs(['en', 'de', 'fr']);
|
||||||
@ -61,6 +65,8 @@ export class AppComponent {
|
|||||||
|
|
||||||
// Setup the operator after the root injector is known.
|
// Setup the operator after the root injector is known.
|
||||||
this.operator.setupSubscription();
|
this.operator.setupSubscription();
|
||||||
|
this.configService.setupSubscription();
|
||||||
|
this.loginDataService.setupSubscription();
|
||||||
|
|
||||||
this.OpenSlides.bootup(); // Yeah!
|
this.OpenSlides.bootup(); // Yeah!
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,9 @@ export class ConfigService extends OpenSlidesComponent {
|
|||||||
*/
|
*/
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super();
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public setupSubscription(): void {
|
||||||
this.DS.changeObservable.subscribe(data => {
|
this.DS.changeObservable.subscribe(data => {
|
||||||
// on changes notify the observers for specific keys.
|
// on changes notify the observers for specific keys.
|
||||||
if (data instanceof Config && this.configSubjects[data.key]) {
|
if (data instanceof Config && this.configSubjects[data.key]) {
|
||||||
|
15
client/src/app/core/services/login-data.service.spec.ts
Normal file
15
client/src/app/core/services/login-data.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginDataService } from './login-data.service';
|
||||||
|
|
||||||
|
describe('LoginDataService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [LoginDataService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([LoginDataService], (service: LoginDataService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
76
client/src/app/core/services/login-data.service.ts
Normal file
76
client/src/app/core/services/login-data.service.ts
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { OpenSlidesComponent } from 'app/openslides.component';
|
||||||
|
import { ConfigService } from './config.service';
|
||||||
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This service holds the privacy policy and the legal notice, so they are available
|
||||||
|
* even if the user is not logged in.
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class LoginDataService extends OpenSlidesComponent {
|
||||||
|
/**
|
||||||
|
* Holds the privacy policy
|
||||||
|
*/
|
||||||
|
private _privacy_policy = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable for the privacy policy
|
||||||
|
*/
|
||||||
|
public get privacy_policy(): Observable<string> {
|
||||||
|
return this._privacy_policy.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the legal notice
|
||||||
|
*/
|
||||||
|
private _legal_notice = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an observable for the legal notice
|
||||||
|
*/
|
||||||
|
public get legal_notice(): Observable<string> {
|
||||||
|
return this._legal_notice.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs this service. The config service is needed to update the privacy
|
||||||
|
* policy and legal notice, when their config values change.
|
||||||
|
* @param configService
|
||||||
|
*/
|
||||||
|
public constructor(private configService: ConfigService) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should be called, when the data store is set up. Updates the values when the
|
||||||
|
* corresponding config variables change.
|
||||||
|
*/
|
||||||
|
public setupSubscription(): void {
|
||||||
|
this.configService.get('general_event_privacy_policy').subscribe(value => {
|
||||||
|
this.setPrivacyPolicy(value);
|
||||||
|
});
|
||||||
|
this.configService.get('general_event_legal_notice').subscribe(value => {
|
||||||
|
this.setLegalNotice(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for the privacy policy
|
||||||
|
* @param privacyPolicy The new privacy policy to set
|
||||||
|
*/
|
||||||
|
public setPrivacyPolicy(privacyPolicy: string): void {
|
||||||
|
this._privacy_policy.next(privacyPolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter for the legal notice
|
||||||
|
* @param legalNotice The new legal notice to set
|
||||||
|
*/
|
||||||
|
public setLegalNotice(legalNotice: string): void {
|
||||||
|
this._legal_notice.next(legalNotice);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
<mat-toolbar color='primary' class="footer">
|
<mat-toolbar color='primary' class="footer">
|
||||||
<mat-toolbar-row>
|
<mat-toolbar-row>
|
||||||
<button mat-button class="footer-link" [routerLink]="['/legalnotice']">
|
<button mat-button class="footer-link" [routerLink]=legalNoticeUrl>
|
||||||
<span translate>Legal Notice</span>
|
<span translate>Legal Notice</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-button class="footer-link" [routerLink]="['/privacypolicy']">
|
<button mat-button class="footer-link" [routerLink]=privacyPolicyUrl>
|
||||||
<span translate>Privacy Policy</span>
|
<span translate>Privacy Policy</span>
|
||||||
</button>
|
</button>
|
||||||
<span class="footer-right">© <span translate>Copyright by</span> <a href='https://openslides.org/'>OpenSlides</a>
|
<span class="footer-right">© <span translate>Copyright by</span> <a href='https://openslides.org/'>OpenSlides</a>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reusable footer Apps.
|
* Reusable footer Apps.
|
||||||
@ -18,12 +19,29 @@ import { Component, OnInit } from '@angular/core';
|
|||||||
})
|
})
|
||||||
export class FooterComponent implements OnInit {
|
export class FooterComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
* Empty constructor
|
* Indicates to location of the legal notice
|
||||||
*/
|
*/
|
||||||
public constructor() {}
|
public legalNoticeUrl = '/legalnotice';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* empty onInit
|
* Indicated the location of the privacy policy
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {}
|
public privacyPolicyUrl = '/privacypolicy';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty constructor
|
||||||
|
*/
|
||||||
|
public constructor(private route: ActivatedRoute) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If on login page, redirect the legal notice and privacy policy not to /URL
|
||||||
|
* but to /login/URL
|
||||||
|
*/
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
if (this.route.snapshot.url[0] && this.route.snapshot.url[0].path === 'login') {
|
||||||
|
this.legalNoticeUrl = '/login/legalnotice';
|
||||||
|
this.privacyPolicyUrl = '/login/privacypolicy';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
<mat-card class="os-card on-transition-fade">
|
||||||
|
<div>
|
||||||
|
<div class='legal-notice-text' [innerHtml]='legalNotice'></div>
|
||||||
|
<mat-divider></mat-divider>
|
||||||
|
<div *ngIf="versionInfo" class='version-text'>
|
||||||
|
<a [attr.href]="versionInfo.openslides_url" target="_blank">
|
||||||
|
OpenSlides {{ versionInfo.openslides_version }}
|
||||||
|
</a>
|
||||||
|
(<span translate>License</span>: {{ versionInfo.openslides_license }})
|
||||||
|
|
||||||
|
<div *ngIf="versionInfo.plugins.length">
|
||||||
|
<div translate>Installed plugins</div>:
|
||||||
|
<div *ngFor="let plugin of versionInfo.plugins">
|
||||||
|
<a [attr.href]="plugin.url" target="_blank">
|
||||||
|
{{ plugin.verbose_name }} {{ plugin.version }}
|
||||||
|
</a>
|
||||||
|
<div *ngIf="plugin.license">
|
||||||
|
(<span translate>License</span>: {{ plugin.license }})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card>
|
@ -0,0 +1,9 @@
|
|||||||
|
.legal-notice-text {
|
||||||
|
display: block;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version-text {
|
||||||
|
display: block;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LegalNoticeContentComponent } from './legal-notice-content.component';
|
||||||
|
|
||||||
|
describe('LegalNoticeComponent', () => {
|
||||||
|
let component: LegalNoticeContentComponent;
|
||||||
|
let fixture: ComponentFixture<LegalNoticeContentComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [LegalNoticeContentComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LegalNoticeContentComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,106 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { LoginDataService } from '../../../core/services/login-data.service';
|
||||||
|
import { environment } from 'environments/environment';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Characterize a plugin. This data is retrieved from the server
|
||||||
|
*/
|
||||||
|
interface PluginDescription {
|
||||||
|
/**
|
||||||
|
* The name of the plugin
|
||||||
|
*/
|
||||||
|
verbose_name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the version
|
||||||
|
*/
|
||||||
|
version: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The url to the main webpage of the plugin
|
||||||
|
*/
|
||||||
|
url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The license
|
||||||
|
*/
|
||||||
|
license: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents metadata about the current installation.
|
||||||
|
*/
|
||||||
|
interface VersionResponse {
|
||||||
|
/**
|
||||||
|
* The lience string. Like 'MIT', 'GPLv2', ...
|
||||||
|
*/
|
||||||
|
openslides_license: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URl to the main webpage of OpenSlides.
|
||||||
|
*/
|
||||||
|
openslides_url: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current version.
|
||||||
|
*/
|
||||||
|
openslides_version: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of installed plugins.
|
||||||
|
*/
|
||||||
|
plugins: PluginDescription[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared component to hold the content of the Legal Notice.
|
||||||
|
* Used in login and site container.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'os-legal-notice-content',
|
||||||
|
templateUrl: './legal-notice-content.component.html',
|
||||||
|
styleUrls: ['./legal-notice-content.component.scss']
|
||||||
|
})
|
||||||
|
export class LegalNoticeContentComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* The legal notive text for the ui.
|
||||||
|
*/
|
||||||
|
public legalNotice: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the version info retrieved from the server for the ui.
|
||||||
|
*/
|
||||||
|
public versionInfo: VersionResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports the LoginDataService, the translations and and HTTP Service
|
||||||
|
* @param loginDataService
|
||||||
|
* @param translate
|
||||||
|
* @param http
|
||||||
|
*/
|
||||||
|
public constructor(
|
||||||
|
private loginDataService: LoginDataService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
private http: HttpClient
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes for the legal notice text.
|
||||||
|
*/
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.loginDataService.legal_notice.subscribe(legalNotice => {
|
||||||
|
if (legalNotice) {
|
||||||
|
this.legalNotice = this.translate.instant(legalNotice);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Query the version info.
|
||||||
|
this.http
|
||||||
|
.get<VersionResponse>(environment.urlPrefix + '/core/version/', {})
|
||||||
|
.subscribe((info: VersionResponse) => {
|
||||||
|
this.versionInfo = info;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
<mat-card class='os-card on-transition-fade'>
|
||||||
|
<div *ngIf='privacyPolicy' [innerHtml]='privacyPolicy'></div>
|
||||||
|
<div *ngIf='!privacyPolicy' translate>
|
||||||
|
The event manager hasn't set up a privacy policy yet.
|
||||||
|
</div>
|
||||||
|
</mat-card>
|
@ -0,0 +1,3 @@
|
|||||||
|
mat-card {
|
||||||
|
height: 100%;
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PrivacyPolicyContentComponent } from './privacy-policy-content.component';
|
||||||
|
|
||||||
|
describe('PrivacyPolicyComponent', () => {
|
||||||
|
let component: PrivacyPolicyContentComponent;
|
||||||
|
let fixture: ComponentFixture<PrivacyPolicyContentComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [PrivacyPolicyContentComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(PrivacyPolicyContentComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,37 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { LoginDataService } from '../../../core/services/login-data.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared component to hold the content of the Privacy Policy.
|
||||||
|
* Used in login and site container.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'os-privacy-policy-content',
|
||||||
|
templateUrl: './privacy-policy-content.component.html',
|
||||||
|
styleUrls: ['./privacy-policy-content.component.scss']
|
||||||
|
})
|
||||||
|
export class PrivacyPolicyContentComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* The actual privacy policy as string
|
||||||
|
*/
|
||||||
|
public privacyPolicy: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports the loginDataService and the translation service
|
||||||
|
* @param loginDataService Login Data
|
||||||
|
* @param translate for the translation
|
||||||
|
*/
|
||||||
|
public constructor(private loginDataService: LoginDataService, private translate: TranslateService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes for the privacy policy text
|
||||||
|
*/
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.loginDataService.privacy_policy.subscribe(privacyPolicy => {
|
||||||
|
if (privacyPolicy) {
|
||||||
|
this.privacyPolicy = this.translate.instant(privacyPolicy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
@ -14,7 +15,8 @@ import {
|
|||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
MatPaginatorModule,
|
MatPaginatorModule,
|
||||||
MatSortModule
|
MatSortModule,
|
||||||
|
MatTabsModule
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list';
|
||||||
@ -36,8 +38,8 @@ import { PermsDirective } from './directives/perms.directive';
|
|||||||
import { DomChangeDirective } from './directives/dom-change.directive';
|
import { DomChangeDirective } from './directives/dom-change.directive';
|
||||||
import { HeadBarComponent } from './components/head-bar/head-bar.component';
|
import { HeadBarComponent } from './components/head-bar/head-bar.component';
|
||||||
import { FooterComponent } from './components/footer/footer.component';
|
import { FooterComponent } from './components/footer/footer.component';
|
||||||
|
import { LegalNoticeContentComponent } from './components/legal-notice-content/legal-notice-content.component';
|
||||||
import { RouterModule } from '@angular/router';
|
import { PrivacyPolicyContentComponent } from './components/privacy-policy-content/privacy-policy-content.component';
|
||||||
|
|
||||||
library.add(fas);
|
library.add(fas);
|
||||||
|
|
||||||
@ -70,10 +72,10 @@ library.add(fas);
|
|||||||
MatListModule,
|
MatListModule,
|
||||||
MatExpansionModule,
|
MatExpansionModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatSnackBarModule,
|
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
TranslateModule.forChild(),
|
MatSnackBarModule,
|
||||||
FontAwesomeModule,
|
FontAwesomeModule,
|
||||||
|
TranslateModule.forChild(),
|
||||||
RouterModule
|
RouterModule
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
@ -96,13 +98,23 @@ library.add(fas);
|
|||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatDialogModule,
|
MatDialogModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
|
MatTabsModule,
|
||||||
FontAwesomeModule,
|
FontAwesomeModule,
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
PermsDirective,
|
PermsDirective,
|
||||||
DomChangeDirective,
|
DomChangeDirective,
|
||||||
FooterComponent,
|
FooterComponent,
|
||||||
HeadBarComponent
|
HeadBarComponent,
|
||||||
|
LegalNoticeContentComponent,
|
||||||
|
PrivacyPolicyContentComponent
|
||||||
],
|
],
|
||||||
declarations: [PermsDirective, DomChangeDirective, HeadBarComponent, FooterComponent]
|
declarations: [
|
||||||
|
PermsDirective,
|
||||||
|
DomChangeDirective,
|
||||||
|
HeadBarComponent,
|
||||||
|
FooterComponent,
|
||||||
|
LegalNoticeContentComponent,
|
||||||
|
PrivacyPolicyContentComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule {}
|
export class SharedModule {}
|
||||||
|
@ -1,13 +1,3 @@
|
|||||||
<mat-toolbar color='primary'>
|
<os-head-bar appName="Legal Notice"></os-head-bar>
|
||||||
<span class='app-name on-transition-fade' translate>Legal Notice</span>
|
|
||||||
</mat-toolbar>
|
|
||||||
|
|
||||||
<mat-card class="os-card on-transition-fade">
|
<os-legal-notice-content></os-legal-notice-content>
|
||||||
<div>
|
|
||||||
<div class='legal-notice-text' [innerHtml]='legalNotice'></div>
|
|
||||||
<mat-divider></mat-divider>
|
|
||||||
<div class='version-text'>
|
|
||||||
OpenSlides 3.0 PRE ALPHA (Lizenz: MIT)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mat-card>
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
.legal-notice-text {
|
|
||||||
display: block;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.version-text {
|
|
||||||
display: block;
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ConfigService } from '../../core/services/config.service';
|
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'os-legal-notice',
|
selector: 'os-legal-notice',
|
||||||
@ -8,15 +6,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
styleUrls: ['./legal-notice.component.scss']
|
styleUrls: ['./legal-notice.component.scss']
|
||||||
})
|
})
|
||||||
export class LegalNoticeComponent implements OnInit {
|
export class LegalNoticeComponent implements OnInit {
|
||||||
public legalNotice: string;
|
public constructor() {}
|
||||||
|
|
||||||
public constructor(private configService: ConfigService, private translate: TranslateService) {}
|
public ngOnInit(): void {}
|
||||||
|
|
||||||
public ngOnInit(): void {
|
|
||||||
this.configService.get('general_event_legal_notice').subscribe(value => {
|
|
||||||
if (value) {
|
|
||||||
this.legalNotice = this.translate.instant(value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
15
client/src/app/site/login/assets/login-info-pages.scss
Normal file
15
client/src/app/site/login/assets/login-info-pages.scss
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
.title-center {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-toolbar {
|
||||||
|
text-align: center;
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<main>
|
||||||
|
<mat-toolbar color="primary" translate>
|
||||||
|
Legal Notice
|
||||||
|
</mat-toolbar>
|
||||||
|
|
||||||
|
<os-legal-notice-content></os-legal-notice-content>
|
||||||
|
|
||||||
|
<button mat-raised-button color="accent" routerLink="/login" routerLinkActive="router-link-active" translate>Login</button>
|
||||||
|
</main>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginLegalNoticeComponent } from './login-legal-notice.component';
|
||||||
|
|
||||||
|
describe('LoginLegalNoticeComponent', () => {
|
||||||
|
let component: LoginLegalNoticeComponent;
|
||||||
|
let fixture: ComponentFixture<LoginLegalNoticeComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [LoginLegalNoticeComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LoginLegalNoticeComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container to display the legal notice on the login page.
|
||||||
|
* Uses the corresponding shared component
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'os-login-legal-notice',
|
||||||
|
templateUrl: './login-legal-notice.component.html',
|
||||||
|
styleUrls: ['./login-legal-notice.component.scss', '../../assets/login-info-pages.scss']
|
||||||
|
})
|
||||||
|
export class LoginLegalNoticeComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* Empty constructor
|
||||||
|
*/
|
||||||
|
public constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty onInit
|
||||||
|
*/
|
||||||
|
public ngOnInit(): void {}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
<div class="form-wrapper">
|
||||||
|
<mat-spinner *ngIf="inProcess"></mat-spinner>
|
||||||
|
<form [formGroup]="loginForm" class="login-form" (ngSubmit)="formLogin()">
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput required placeholder="User name" formControlName="username" [errorStateMatcher]="parentErrorStateMatcher">
|
||||||
|
</mat-form-field>
|
||||||
|
<br>
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput required placeholder="Password" formControlName="password" [type]="!hide ? 'password' : 'text'"
|
||||||
|
[errorStateMatcher]="parentErrorStateMatcher">
|
||||||
|
<fa-icon matSuffix [icon]="!hide ? 'eye-slash' : 'eye'" (click)="hide = !hide"></fa-icon>
|
||||||
|
<mat-error>{{loginErrorMsg}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<!-- forgot password button -->
|
||||||
|
<br>
|
||||||
|
<button type="button" class='forgot-password-button' (click)="resetPassword()" mat-button>Forgot Password?</button>
|
||||||
|
|
||||||
|
<!-- login button -->
|
||||||
|
<br>
|
||||||
|
<!-- TODO: Next to each other...-->
|
||||||
|
<button mat-raised-button color="primary" class='login-button' type="submit" translate>Login</button>
|
||||||
|
<button mat-raised-button *ngIf="areGuestsEnabled()" color="primary" class='login-button' type="button"
|
||||||
|
(click)="guestLogin()" translate>Login as Guest</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -2,23 +2,6 @@ mat-form-field {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
|
||||||
width: 100%;
|
|
||||||
flex: 1;
|
|
||||||
mat-toolbar {
|
|
||||||
min-height: 200px !important;
|
|
||||||
}
|
|
||||||
.login-logo-bar {
|
|
||||||
img {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
width: 90%;
|
|
||||||
height: 90%;
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.forgot-password-button {
|
.forgot-password-button {
|
||||||
float: right;
|
float: right;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -49,7 +32,3 @@ header {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
|
||||||
bottom: 0; //black magic to keep the toolbar active here
|
|
||||||
}
|
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginMaskComponent } from './login-mask.component';
|
||||||
|
|
||||||
|
describe('LoginMaskComponent', () => {
|
||||||
|
let component: LoginMaskComponent;
|
||||||
|
let fixture: ComponentFixture<LoginMaskComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [LoginMaskComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LoginMaskComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -1,6 +1,5 @@
|
|||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Title } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
import { BaseComponent } from 'app/base.component';
|
import { BaseComponent } from 'app/base.component';
|
||||||
import { AuthService } from 'app/core/services/auth.service';
|
import { AuthService } from 'app/core/services/auth.service';
|
||||||
@ -10,7 +9,8 @@ import { FormControl, FormGroupDirective, NgForm, FormGroup, Validators, FormBui
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { HttpErrorResponse, HttpClient } from '@angular/common/http';
|
import { HttpErrorResponse, HttpClient } from '@angular/common/http';
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { OpenSlidesService } from '../../core/services/openslides.service';
|
import { OpenSlidesService } from '../../../../core/services/openslides.service';
|
||||||
|
import { LoginDataService } from '../../../../core/services/login-data.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom error states. Might become part of the shared module later.
|
* Custom error states. Might become part of the shared module later.
|
||||||
@ -32,16 +32,16 @@ export class ParentErrorStateMatcher implements ErrorStateMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Login component.
|
* Login mask component.
|
||||||
*
|
*
|
||||||
* Handles user (and potentially guest) login
|
* Handles user and guest login
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'os-login',
|
selector: 'os-login-mask',
|
||||||
templateUrl: './login.component.html',
|
templateUrl: './login-mask.component.html',
|
||||||
styleUrls: ['./login.component.scss']
|
styleUrls: ['./login-mask.component.scss']
|
||||||
})
|
})
|
||||||
export class LoginComponent extends BaseComponent implements OnInit, OnDestroy {
|
export class LoginMaskComponent extends BaseComponent implements OnInit, OnDestroy {
|
||||||
/**
|
/**
|
||||||
* Show or hide password and change the indicator accordingly
|
* Show or hide password and change the indicator accordingly
|
||||||
*/
|
*/
|
||||||
@ -72,24 +72,19 @@ export class LoginComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
*/
|
*/
|
||||||
public inProcess = false;
|
public inProcess = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* The provacy policy send by the server.
|
|
||||||
*
|
|
||||||
* TODO: give an option to show it during login.
|
|
||||||
*/
|
|
||||||
public privacyPolicy: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the login component
|
* Constructor for the login component
|
||||||
*
|
*
|
||||||
* @param titleService Setting the title
|
|
||||||
* @param authService Authenticating the user
|
* @param authService Authenticating the user
|
||||||
* @param operator The representation of the current user
|
* @param operator The representation of the current user
|
||||||
* @param router forward to start page
|
* @param router forward to start page
|
||||||
* @param formBuilder To build the form and validate
|
* @param formBuilder To build the form and validate
|
||||||
|
* @param http used to get information before the login
|
||||||
|
* @param matSnackBar Display information
|
||||||
|
* @param OpenSlides The Service for OpenSlides
|
||||||
|
* @param loginDataService provide information about the legal notice and privacy policy
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
protected titleService: Title,
|
|
||||||
protected translate: TranslateService,
|
protected translate: TranslateService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private operator: OperatorService,
|
private operator: OperatorService,
|
||||||
@ -97,9 +92,10 @@ export class LoginComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
private matSnackBar: MatSnackBar,
|
private matSnackBar: MatSnackBar,
|
||||||
private OpenSlides: OpenSlidesService
|
private OpenSlides: OpenSlidesService,
|
||||||
|
private loginDataService: LoginDataService
|
||||||
) {
|
) {
|
||||||
super(titleService, translate);
|
super();
|
||||||
this.createForm();
|
this.createForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,15 +106,15 @@ export class LoginComponent extends BaseComponent implements OnInit, OnDestroy {
|
|||||||
* Observes the operator, if a user was already logged in, recreate to user and skip the login
|
* Observes the operator, if a user was already logged in, recreate to user and skip the login
|
||||||
*/
|
*/
|
||||||
public ngOnInit(): void {
|
public ngOnInit(): void {
|
||||||
super.setTitle('Login');
|
// Get the login data. Save information to the login data service
|
||||||
|
|
||||||
this.http.get<any>(environment.urlPrefix + '/users/login/', {}).subscribe(response => {
|
this.http.get<any>(environment.urlPrefix + '/users/login/', {}).subscribe(response => {
|
||||||
if (response.info_text) {
|
if (response.info_text) {
|
||||||
this.installationNotice = this.matSnackBar.open(response.info_text, this.translate.instant('OK'), {
|
this.installationNotice = this.matSnackBar.open(response.info_text, this.translate.instant('OK'), {
|
||||||
duration: 5000
|
duration: 5000
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.privacyPolicy = response.privacy_policy;
|
this.loginDataService.setPrivacyPolicy(response.privacy_policy);
|
||||||
|
this.loginDataService.setLegalNotice(response.legal_notice);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
<main>
|
||||||
|
<mat-toolbar color="primary" translate>
|
||||||
|
Privacy Policy
|
||||||
|
</mat-toolbar>
|
||||||
|
|
||||||
|
<os-privacy-policy-content></os-privacy-policy-content>
|
||||||
|
|
||||||
|
<button mat-raised-button color="accent" routerLink="/login" routerLinkActive="router-link-active" translate>Login</button>
|
||||||
|
</main>
|
@ -0,0 +1,24 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginPrivacyPolicyComponent } from './login-privacy-policy.component';
|
||||||
|
|
||||||
|
describe('LoginPrivacyPolicyComponent', () => {
|
||||||
|
let component: LoginPrivacyPolicyComponent;
|
||||||
|
let fixture: ComponentFixture<LoginPrivacyPolicyComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [LoginPrivacyPolicyComponent]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LoginPrivacyPolicyComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container to display the privacy policy on the login page.
|
||||||
|
* Uses the corresponding shared component
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'os-login-privacy-policy',
|
||||||
|
templateUrl: './login-privacy-policy.component.html',
|
||||||
|
styleUrls: ['./login-privacy-policy.component.scss', '../../assets/login-info-pages.scss']
|
||||||
|
})
|
||||||
|
export class LoginPrivacyPolicyComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* Empty Constructor
|
||||||
|
*/
|
||||||
|
public constructor() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty onInit
|
||||||
|
*/
|
||||||
|
public ngOnInit(): void {}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
<!-- The actual form -->
|
||||||
|
<header>
|
||||||
|
<mat-toolbar class="login-logo-bar" color="primary">
|
||||||
|
<img src='/assets/img/openslides-logo-h-dark-transparent.svg' alt='OpenSlides-logo'>
|
||||||
|
</mat-toolbar>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</main>
|
||||||
|
<footer class="page-footer">
|
||||||
|
<os-footer></os-footer>
|
||||||
|
</footer>
|
@ -0,0 +1,16 @@
|
|||||||
|
header {
|
||||||
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
|
mat-toolbar {
|
||||||
|
min-height: 200px !important;
|
||||||
|
}
|
||||||
|
.login-logo-bar {
|
||||||
|
img {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
width: 90%;
|
||||||
|
height: 90%;
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
import { BaseComponent } from '../../../../base.component';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login component.
|
||||||
|
*
|
||||||
|
* Serves as container for the login mask, legal notice and privacy policy
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'os-login',
|
||||||
|
templateUrl: './login.component.html',
|
||||||
|
styleUrls: ['./login.component.scss']
|
||||||
|
})
|
||||||
|
export class LoginComponent extends BaseComponent implements OnInit {
|
||||||
|
/**
|
||||||
|
* Imports the title service and the translate service
|
||||||
|
*
|
||||||
|
* @param titleService to set the title
|
||||||
|
* @param translate just needed because super.setTitle depends in the `translator.instant` function
|
||||||
|
*/
|
||||||
|
public constructor(protected titleService: Title, protected translate: TranslateService) {
|
||||||
|
super(titleService, translate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the title of the page
|
||||||
|
*/
|
||||||
|
public ngOnInit(): void {
|
||||||
|
super.setTitle('Login');
|
||||||
|
}
|
||||||
|
}
|
@ -1,38 +0,0 @@
|
|||||||
<!-- The actual form -->
|
|
||||||
<header>
|
|
||||||
<mat-toolbar class="login-logo-bar" color="primary">
|
|
||||||
<img src='/assets/img/openslides-logo-h-dark-transparent.svg' alt='OpenSlides-logo'>
|
|
||||||
</mat-toolbar>
|
|
||||||
</header>
|
|
||||||
<main>
|
|
||||||
<div class="form-wrapper">
|
|
||||||
|
|
||||||
<mat-spinner *ngIf="inProcess"></mat-spinner>
|
|
||||||
<form [formGroup]="loginForm" class="login-form" (ngSubmit)="formLogin()">
|
|
||||||
<mat-form-field>
|
|
||||||
<input matInput required placeholder="User name" formControlName="username" [errorStateMatcher]="parentErrorStateMatcher">
|
|
||||||
</mat-form-field>
|
|
||||||
<br>
|
|
||||||
<mat-form-field>
|
|
||||||
<input matInput required placeholder="Password" formControlName="password" [type]="!hide ? 'password' : 'text'" [errorStateMatcher]="parentErrorStateMatcher">
|
|
||||||
<fa-icon matSuffix [icon]="!hide ? 'eye-slash' : 'eye'" (click)="hide = !hide"></fa-icon>
|
|
||||||
<mat-error>{{loginErrorMsg}}</mat-error>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<!-- forgot password button -->
|
|
||||||
<br>
|
|
||||||
<button type="button" class='forgot-password-button' (click)="resetPassword()" mat-button>Forgot Password?</button>
|
|
||||||
|
|
||||||
<!-- login button -->
|
|
||||||
<br>
|
|
||||||
<!-- TODO: Next to each other...-->
|
|
||||||
<button mat-raised-button color="primary" class='login-button' type="submit" translate>Login</button>
|
|
||||||
<button mat-raised-button *ngIf="areGuestsEnabled()" color="primary" class='login-button' type="button" (click)="guestLogin()" translate>Login as Guest</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
<footer class="page-footer">
|
|
||||||
<os-footer></os-footer>
|
|
||||||
</footer>
|
|
@ -1,10 +1,15 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { LoginComponent } from './login.component';
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
import { LoginComponent } from './components/login-wrapper/login.component';
|
||||||
import { SharedModule } from '../../shared/shared.module';
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
import { LoginMaskComponent } from './components/login-mask/login-mask.component';
|
||||||
|
import { LoginLegalNoticeComponent } from './components/login-legal-notice/login-legal-notice.component';
|
||||||
|
import { LoginPrivacyPolicyComponent } from './components/login-privacy-policy/login-privacy-policy.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, SharedModule],
|
imports: [CommonModule, RouterModule, SharedModule],
|
||||||
declarations: [LoginComponent]
|
declarations: [LoginComponent, LoginMaskComponent, LoginLegalNoticeComponent, LoginPrivacyPolicyComponent]
|
||||||
})
|
})
|
||||||
export class LoginModule {}
|
export class LoginModule {}
|
||||||
|
@ -1,27 +1,3 @@
|
|||||||
<mat-toolbar color='primary'>
|
<os-head-bar appName="Privacy Policy"></os-head-bar>
|
||||||
<span class='app-name on-transition-fade' translate>Privacy Policy</span>
|
|
||||||
</mat-toolbar>
|
|
||||||
|
|
||||||
<mat-card class="os-card on-transition-fade">
|
<os-privacy-policy-content></os-privacy-policy-content>
|
||||||
<div>
|
|
||||||
OpenSlides speichert nur so viele personenbezogene Daten wie unbedingt nötig sind, um Besuchern Informationen und Dienste
|
|
||||||
zuverlässig und sicher anbieten zu können. Eine Auswertung der Dienste-Protokolle erfolgt nur von uns selbst und
|
|
||||||
auch nur, um mögliche Fehler, Einbruchsversuche oder technisches Verhalten der Server auf unseren Server zu analysieren.
|
|
||||||
Eine Weitergabe von Teilen der erhobenen Daten erfolgt ausschließlich gemäß gesetzlicher Verpflichtung z.B. an Strafverfolgungs-
|
|
||||||
oder Steuerbehörden. Nachfolgend wird genau aufgeschlüsselt, bei welcher Gelegenheit welche Daten wie lange gespeichert
|
|
||||||
sind. Zudem wird beschrieben, welche Schritte erforderlich sind um Daten zu löschen.
|
|
||||||
<h3 translate>Cookies</h3>
|
|
||||||
Beim Besuch der Website wird ein sogenanntes Cookie angelegt. Dieses Cookie wird ausschließlich dazu verwendet, um auf der
|
|
||||||
Website eingeloggt zu bleiben. Ein sogenanntes "Tracking Cookie" wird nicht verwendet.
|
|
||||||
<h3 translate>Logfiles</h3>
|
|
||||||
Zu OpenSlides gehören verschiedene Unter-Services. Diese loggen folgende Informationen: Quell-IP-Adresse, Zeitstempel, genutztes
|
|
||||||
Betriebssystem, verwendeter Web-Browser, Referer-URL, E-Mail-Adresse und besuchte Seite.
|
|
||||||
<h3 translate>Database</h3>
|
|
||||||
Als Mitglied werden folgende Daten von Ihnen gespeichert: Titel, Vorname, Nachname, EMail, Gliederungsebene, Teilnehmernummer,
|
|
||||||
Gruppenzugehörigkeit, Initiales Passwort im Klartext, Vergebenes Passwort als kryptografischer Hashwert und ein Kommentar
|
|
||||||
für interne Notizen. Diese Informationen werden mit den Aktionen innerhalb von OpenSlides in Verbindung gebracht.
|
|
||||||
Diese Informationen werden nicht an Dritte weiter gegeben und sind auch nicht für diese zugänglich.
|
|
||||||
<h3 translate>Deleting Files</h3>
|
|
||||||
Die Daten dieser OpenSlides-Demo-Instanz werden nächtlich automatisch gelöscht.
|
|
||||||
</div>
|
|
||||||
</mat-card>
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
mat-card {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
@ -7,7 +7,6 @@ import { StartComponent } from './start/start.component';
|
|||||||
import { PrivacyPolicyComponent } from './privacy-policy/privacy-policy.component';
|
import { PrivacyPolicyComponent } from './privacy-policy/privacy-policy.component';
|
||||||
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
|
import { LegalNoticeComponent } from './legal-notice/legal-notice.component';
|
||||||
import { AuthGuard } from '../core/services/auth-guard.service';
|
import { AuthGuard } from '../core/services/auth-guard.service';
|
||||||
// import { LoginComponent } from './login/login.component';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routung to all OpenSlides apps
|
* Routung to all OpenSlides apps
|
||||||
@ -15,15 +14,26 @@ import { AuthGuard } from '../core/services/auth-guard.service';
|
|||||||
* TODO: Plugins will have to append to the Routes-Array
|
* TODO: Plugins will have to append to the Routes-Array
|
||||||
*/
|
*/
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
// { path: 'login', component: LoginComponent },
|
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: SiteComponent,
|
component: SiteComponent,
|
||||||
children: [
|
children: [
|
||||||
{ path: '', component: StartComponent },
|
{
|
||||||
{ path: 'legalnotice', component: LegalNoticeComponent },
|
path: '',
|
||||||
{ path: 'privacypolicy', component: PrivacyPolicyComponent },
|
component: StartComponent
|
||||||
{ path: 'agenda', loadChildren: './agenda/agenda.module#AgendaModule' },
|
},
|
||||||
|
{
|
||||||
|
path: 'legalnotice',
|
||||||
|
component: LegalNoticeComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'privacypolicy',
|
||||||
|
component: PrivacyPolicyComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'agenda',
|
||||||
|
loadChildren: './agenda/agenda.module#AgendaModule'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'assignments',
|
path: 'assignments',
|
||||||
loadChildren: './assignments/assignments.module#AssignmentsModule'
|
loadChildren: './assignments/assignments.module#AssignmentsModule'
|
||||||
@ -32,12 +42,18 @@ const routes: Routes = [
|
|||||||
path: 'mediafiles',
|
path: 'mediafiles',
|
||||||
loadChildren: './mediafiles/mediafiles.module#MediafilesModule'
|
loadChildren: './mediafiles/mediafiles.module#MediafilesModule'
|
||||||
},
|
},
|
||||||
{ path: 'motions', loadChildren: './motions/motions.module#MotionsModule' },
|
{
|
||||||
|
path: 'motions',
|
||||||
|
loadChildren: './motions/motions.module#MotionsModule'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'settings',
|
path: 'settings',
|
||||||
loadChildren: './settings/settings.module#SettingsModule'
|
loadChildren: './settings/settings.module#SettingsModule'
|
||||||
},
|
},
|
||||||
{ path: 'users', loadChildren: './users/users.module#UsersModule' }
|
{
|
||||||
|
path: 'users',
|
||||||
|
loadChildren: './users/users.module#UsersModule'
|
||||||
|
}
|
||||||
],
|
],
|
||||||
canActivateChild: [AuthGuard]
|
canActivateChild: [AuthGuard]
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,14 @@ export class SiteComponent extends BaseComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
operator: OperatorService,
|
public operator: OperatorService,
|
||||||
public vp: ViewportService,
|
public vp: ViewportService,
|
||||||
public translate: TranslateService,
|
public translate: TranslateService,
|
||||||
public dialog: MatDialog
|
public dialog: MatDialog
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
operator.getObservable().subscribe(user => {
|
this.operator.getObservable().subscribe(user => {
|
||||||
if (user) {
|
if (user) {
|
||||||
this.username = user.full_name;
|
this.username = user.full_name;
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,11 +94,11 @@ export class StartComponent extends BaseComponent implements OnInit {
|
|||||||
console.log('the user: ', user1fromStore);
|
console.log('the user: ', user1fromStore);
|
||||||
|
|
||||||
console.log('remove a single user:');
|
console.log('remove a single user:');
|
||||||
this.DS.remove(User, 100);
|
// this.DS.remove(User, 100);
|
||||||
console.log('remove more users');
|
console.log('remove more users');
|
||||||
this.DS.remove(User, 200, 201, 202);
|
// this.DS.remove(User, 200, 201, 202);
|
||||||
console.log('remove an array of users');
|
console.log('remove an array of users');
|
||||||
this.DS.remove(User, ...[321, 363, 399]);
|
// this.DS.remove(User, ...[321, 363, 399]);
|
||||||
|
|
||||||
console.log('test filter: ');
|
console.log('test filter: ');
|
||||||
console.log(this.DS.filter<User>(User, user => user.id === 1));
|
console.log(this.DS.filter<User>(User, user => user.id === 1));
|
||||||
|
@ -453,8 +453,10 @@ class UserLoginView(APIView):
|
|||||||
password='<strong>admin</strong>')
|
password='<strong>admin</strong>')
|
||||||
else:
|
else:
|
||||||
context['info_text'] = ''
|
context['info_text'] = ''
|
||||||
# Add the privacy policy, so the client can display it even, it is not logged in.
|
# Add the privacy policy and legal notice, so the client can display it
|
||||||
|
# even, it is not logged in.
|
||||||
context['privacy_policy'] = config['general_event_privacy_policy']
|
context['privacy_policy'] = config['general_event_privacy_policy']
|
||||||
|
context['legal_notice'] = config['general_event_legal_notice']
|
||||||
else:
|
else:
|
||||||
# self.request.method == 'POST'
|
# self.request.method == 'POST'
|
||||||
context['user_id'] = self.user.pk
|
context['user_id'] = self.user.pk
|
||||||
|
Loading…
Reference in New Issue
Block a user