@Injectable({providedIn: 'root'})
export class AuthService {
+ // Override this to store authtokens, etc. in a different location
+ storePrefix = 'eg.auth';
+
private authChannel: any;
private activeUser: AuthUser = null;
// Returns true if we are currently in op-change mode.
opChangeIsActive(): boolean {
- return Boolean(this.store.getLoginSessionItem('eg.auth.time.oc'));
+ return Boolean(this.store.getLoginSessionItem(`${this.storePrefix}.time.oc`));
}
// - Accessor functions always refer to the active user.
// Only necessary on new page loads. During op-change,
// for example, we already have an activeUser.
this.activeUser = new AuthUser(
- this.store.getLoginSessionItem('eg.auth.token'),
- this.store.getLoginSessionItem('eg.auth.time')
+ this.store.getLoginSessionItem(`${this.storePrefix}.token`),
+ this.store.getLoginSessionItem(`${this.storePrefix}.time`)
);
}
handleLoginOk(args: AuthLoginArgs, evt: EgEvent, isOpChange: boolean): Promise<void> {
if (isOpChange) {
- this.store.setLoginSessionItem('eg.auth.token.oc', this.token());
- this.store.setLoginSessionItem('eg.auth.time.oc', this.authtime());
+ this.store.setLoginSessionItem(`${this.storePrefix}.token.oc`, this.token());
+ this.store.setLoginSessionItem(`${this.storePrefix}.time.oc`, this.authtime());
}
this.activeUser = new AuthUser(
args.workstation
);
- this.store.setLoginSessionItem('eg.auth.token', this.token());
- this.store.setLoginSessionItem('eg.auth.time', this.authtime());
+ this.store.setLoginSessionItem(`${this.storePrefix}.token`, this.token());
+ this.store.setLoginSessionItem(`${this.storePrefix}.time`, this.authtime());
return Promise.resolve();
}
if (this.opChangeIsActive()) {
this.deleteSession();
this.activeUser = new AuthUser(
- this.store.getLoginSessionItem('eg.auth.token.oc'),
- this.store.getLoginSessionItem('eg.auth.time.oc'),
+ this.store.getLoginSessionItem(`${this.storePrefix}.token.oc`),
+ this.store.getLoginSessionItem(`${this.storePrefix}.time.oc`),
this.activeUser.workstation
);
- this.store.removeLoginSessionItem('eg.auth.token.oc');
- this.store.removeLoginSessionItem('eg.auth.time.oc');
- this.store.setLoginSessionItem('eg.auth.token', this.token());
- this.store.setLoginSessionItem('eg.auth.time', this.authtime());
+ this.store.removeLoginSessionItem(`${this.storePrefix}.token.oc`);
+ this.store.removeLoginSessionItem(`${this.storePrefix}.time.oc`);
+ this.store.setLoginSessionItem(`${this.storePrefix}.token`, this.token());
+ this.store.setLoginSessionItem(`${this.storePrefix}.time`, this.authtime());
}
// Re-fetch the user.
return this.testAuthToken();
--- /dev/null
+
+<div id="scko-banner" class="pb-2">
+ <div id="scko-logo-div">
+ <img src="/images/self_eg_logo.png"/>
+ </div>
+ <div class="scko-scan-container mt-3">
+ <ng-container *ngIf="scko.auth.user() && !scko.patron">
+ <div id="scko-scan-input-text" i18n>
+ Please log in with your username or library barcode.
+ </div>
+ <div class="d-flex mt-3 mb-3">
+ <div class="flex-1"></div>
+ <div>
+ <form (ngSubmit)="submitPatronLogin()" #patronLoginForm="ngForm"
+ autocomplete="off" class="form-validated form-inline">
+
+ <input type="text" class="form-control border border-dark shadow-rounded"
+ autocomplete="off" id="patron-username" required
+ [(ngModel)]="patronUsername" placeholder="Username or Barcode" i18n-placeholder>
+
+ <label class="sr-only" for="patron-password" i18n>Password</label>
+
+ <input type="password" class="form-control shadow border border-dark rounded ml-2"
+ autocomplete="off" id="patron-password" required
+ [(ngModel)]="patronUsername" placeholder="Password" i18n-placeholder>
+
+ <button type="submit" class="btn btn-dark ml-2">Submit</button>
+ </form>
+ </div>
+ <div class="flex-1"></div>
+ </div>
+ </ng-container>
+
+ </div>
+</div>
+
+<div *ngIf="!scko.auth.user()" class="container mt-3">
+
+ <div class="col-lg-6 offset-lg-3">
+ <fieldset>
+ <legend class="mb-0" i18n><h1>Staff Account Login</h1></legend>
+ <hr class="mt-1"/>
+ <form (ngSubmit)="submitStaffLogin()" #staffLoginForm="ngForm" class="form-validated">
+
+ <div class="form-group row">
+ <label class="col-lg-4 text-right font-weight-bold" for="username" i18n>Username</label>
+ <input
+ type="text"
+ class="form-control col-lg-8"
+ id="staff-username"
+ name="staff-username"
+ required
+ autocomplete="username"
+ i18n-placeholder
+ placeholder="Staff Username"
+ [(ngModel)]="staffUsername"/>
+ </div>
+
+ <div class="form-group row">
+ <label class="col-lg-4 text-right font-weight-bold" for="password" i18n>Password</label>
+ <input
+ type="password"
+ class="form-control col-lg-8"
+ id="staff-password"
+ name="staff-password"
+ required
+ autocomplete="current-password"
+ i18n-placeholder
+ placeholder="Staff Password"
+ [(ngModel)]="staffPassword"/>
+ </div>
+
+ <div class="form-group row" *ngIf="workstations && workstations.length">
+ <label class="col-lg-4 text-right font-weight-bold" for="workstation" i18n>Workstation</label>
+ <select
+ class="form-control col-lg-8"
+ id="workstation"
+ name="workstation"
+ required
+ [(ngModel)]="args.workstation">
+ <option *ngFor="let ws of workstations" [value]="ws.name">
+ {{ws.name}}
+ </option>
+ </select>
+ </div>
+
+ <div class="row">
+ <div class="col-lg-2 offset-lg-4 pl-0">
+ <button type="submit" class="btn btn-outline-dark" i18n>Sign In</button>
+ </div>
+ <div class="col-lg-4" *ngIf="loginFailed">
+ <div class="badge badge-warning p-2" i18n>Login Failed</div>
+ </div>
+ </div>
+ </form>
+ </fieldset>
+ </div>
+</div>
--- /dev/null
+import {Component, OnInit, NgZone, HostListener} from '@angular/core';
+import {Location} from '@angular/common';
+import {Router, ActivatedRoute, NavigationEnd} from '@angular/router';
+import {AuthService, AuthWsState} from '@eg/core/auth.service';
+import {StoreService} from '@eg/core/store.service';
+import {SckoService} from './scko.service';
+import {OrgService} from '@eg/core/org.service';
+
+@Component({
+ selector: 'eg-scko-banner',
+ templateUrl: 'banner.component.html'
+})
+
+export class SckoBannerComponent implements OnInit {
+
+ workstations: any[];
+ loginFailed = false;
+ workstationNotFound = false;
+
+ patronUsername: string;
+ patronPassword: string;
+
+ staffUsername: string;
+ staffPassword: string;
+ staffWorkstation: string;
+
+ constructor(
+ private route: ActivatedRoute,
+ private store: StoreService,
+ private auth: AuthService,
+ private ngLocation: Location,
+ private org: OrgService,
+ public scko: SckoService
+ ) {}
+
+ ngOnInit() {
+
+ const node = document.getElementById('staff-username');
+
+ console.log('PFX', this.scko.auth.storePrefix);
+ console.log(this.scko.auth.token());
+ console.log(this.scko.auth.user());
+
+ // NOTE: Displaying a list of workstations will not work for users
+ // of Hatch until the extension is updated to support /eg2/*/scko
+ this.store.getWorkstations()
+ .then(wsList => {
+ this.workstations = wsList;
+ return this.store.getDefaultWorkstation();
+ }).then(def => {
+ this.staffWorkstation = def;
+ this.applyWorkstation();
+ });
+ }
+
+ applyWorkstation() {
+ const wanted = this.route.snapshot.queryParamMap.get('workstation');
+ if (!wanted) { return; } // use the default
+
+ const exists = this.workstations.filter(w => w.name === wanted)[0];
+ if (exists) {
+ this.staffWorkstation = wanted;
+ } else {
+ console.error(`Unknown workstation requested: ${wanted}`);
+ }
+ }
+
+ submitStaffLogin() {
+
+ this.loginFailed = false;
+
+ const args = {
+ type: 'persistent',
+ username: this.staffUsername,
+ password: this.staffPassword,
+ workstation: this.staffWorkstation
+ };
+
+ this.loginFailed = false;
+ this.workstationNotFound = false;
+
+ this.auth.login(args).then(
+ ok => {
+
+ if (this.auth.workstationState === AuthWsState.NOT_FOUND_SERVER) {
+ this.loginFailed = true;
+ this.workstationNotFound = true;
+
+ } else {
+
+ // Initial login clears cached org unit setting values
+ // and user/workstation setting values
+ this.org.clearCachedSettings().then(_ => {
+
+ // Force reload of the app after a successful login.
+ // This allows the route resolver to re-run with a
+ // valid auth token and workstation.
+ window.location.href =
+ this.ngLocation.prepareExternalUrl('/scko');
+
+ });
+ }
+ },
+ notOk => {
+ this.loginFailed = true;
+ }
+ );
+ }
+
+ submitPatronLogin() {
+ }
+}
+
const routes: Routes = [{
path: '',
- component: SckoComponent
+ component: SckoComponent,
+ /*
+ children: [{
+
+ }]
+ */
}];
@NgModule({
-<div id="scko-banner" class="pb-2">
- <div id="scko-logo-div">
- <img src="/images/self_eg_logo.png"/>
- </div>
- <div class="scko-scan-container mt-3">
- <ng-container *ngIf="!patron">
- <div id="scko-scan-input-text" i18n>
- Please log in with your username or library barcode.
- </div>
- <div class="row form-validated form-inline d-flex mt-3 mb-3">
- <div class="flex-1"></div>
- <div>
- <label class="sr-only" for="patron-username" i18n>Username or Barcode</label>
- <input type="text" class="form-control border border-dark shadow-rounded"
- id="patron-username" placeholder="Username or Barcode" i18n-placeholder>
- <label class="sr-only" for="patron-password" i18n>Password</label>
- <input type="text" class="form-control shadow border border-dark rounded ml-2"
- id="patron-password" placeholder="Password" i18n-placeholder>
- <button type="submit" class="btn btn-dark ml-2">Submit</button>
- </div>
- <div class="flex-1"></div>
- </div>
- </ng-container>
- </div>
-</div>
+<eg-scko-banner></eg-scko-banner>
-<div id='staff-content-container'>
- <!-- page content -->
- <router-outlet></router-outlet>
-</div>
+<router-outlet></router-outlet>
<!-- global toast alerts -->
<eg-toast></eg-toast>
-import {Component, OnInit, NgZone, HostListener} from '@angular/core';
+import {Component, OnInit, ViewEncapsulation} from '@angular/core';
import {Router, ActivatedRoute, NavigationEnd} from '@angular/router';
-import {AuthService, AuthWsState} from '@eg/core/auth.service';
-import {NetService} from '@eg/core/net.service';
-import {IdlObject, IdlService} from '@eg/core/idl.service';
+import {AuthService} from '@eg/core/auth.service';
+import {SckoService} from './scko.service';
@Component({
templateUrl: 'scko.component.html',
- styleUrls: ['scko.component.css']
+ styleUrls: ['scko.component.css'],
+ encapsulation: ViewEncapsulation.None
})
export class SckoComponent implements OnInit {
- // Currently active patron account object.
- patron: IdlObject;
-
constructor(
private router: Router,
private route: ActivatedRoute,
- private net: NetService,
- private auth: AuthService,
+ public scko: SckoService
) {}
ngOnInit() {
import {SckoComponent} from './scko.component';
import {SckoRoutingModule} from './routing.module';
+import {SckoService} from './scko.service';
+import {SckoBannerComponent} from './banner.component';
@NgModule({
declarations: [
SckoComponent,
+ SckoBannerComponent,
],
imports: [
EgCommonModule,
CommonWidgetsModule,
SckoRoutingModule
+ ],
+ providers: [
+ SckoService
]
})
--- /dev/null
+import {Injectable, EventEmitter} from '@angular/core';
+import {NetService} from '@eg/core/net.service';
+import {AuthService} from '@eg/core/auth.service';
+import {EventService, EgEvent} from '@eg/core/event.service';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {StoreService} from '@eg/core/store.service';
+import {ServerStoreService} from '@eg/core/server-store.service';
+
+@Injectable({providedIn: 'root'})
+export class SckoService {
+
+ // Currently active patron account object.
+ patron: IdlObject;
+
+ constructor(
+ private net: NetService,
+ public auth: AuthService
+ ) {
+ this.auth.storePrefix = 'eg.scko';
+ }
+}
+
+
+