* Ported from NodeJS to Python

* Migrated to libfprint-2
This commit is contained in:
2021-12-08 14:35:55 +01:00
commit 62ed8744f2
7 changed files with 475 additions and 0 deletions
+131
View File
@@ -0,0 +1,131 @@
var app = new Vue({
el: '#app',
data: {
step: 0,
phone: '',
errorMessage: '',
otp: '',
busy: {
login: false
},
user: {
phone: '',
username: '',
roles: []
},
staff: {
reference: ''
},
fingerDetails: {
'right-thumb': { },
'right-index-finger': { }
},
socket: null
},
created: function () {
var userStr = localStorage.getItem("user");
if (userStr) {
this.user = JSON.parse(userStr);
this.step = 1;
}
this.socket = io();
this.socket.on("connect", () => { })
this.socket.on("fprint-enroll-done", (data) => {
console.log({ event: 'enroll-done', data});
if (data.ok) {
let { id, fingerprint, data: { finger }} = data;
this.step = 1.2;
this.fingerDetails[finger] = { id, fingerprint, finger }
}
this.busy.login = false;
})
this.socket.on("fprint-verify-done", (data) => {
console.log({ event: 'verify-done', data});
});
},
methods: {
authenticateUrl: function (api, authenticate = true) {
return `https://apis.a2loft.net/identity${api}` + (authenticate ? `?phone=${this.user.phone}&otp=${this.otp}` : '');
},
login: async function () {
this.busy.login = true;
var { data } = await axios.get(
this.authenticateUrl(`/validate/uc/${this.phone}/${this.otp}`, false)
);
this.errorMessage = '';
if (!data.ok)
this.errorMessage = "Invalid OTP specified.";
else {
localStorage.setItem("user", JSON.stringify(data.data));
this.user = data.data;
this.step = 1.0;
}
this.busy.login = false;
},
logout: function () {
localStorage.removeItem("user");
this.step = 0;
},
loadUserByReference: async function () {
this.busy.login = true;
try {
var { data } = await axios.get(
this.authenticateUrl(`/uc/${this.staff.reference}`)
);
if (!data.ok) {
swal("Oops!", `Operation failed. ${data.message}.` + this.staff.reference, "error");
} else {
this.staff = data.data;
// this.staff.verified = false;
this.step = 1.1;
}
} finally {
this.busy.login = false;
}
},
captureFingerPrint: async function (finger) {
this.busy.login = true;
this.step = 1.1;
// var { data: { success, message: { id, data, fingerprint } } } = await axios.post("http://localhost:9000/api/user", {
// name: this.staff.reference
// });
// this.fingerDetails = { id, fingerprint };
// var { data } = await axios.delete(`http://localhost:9000/api/user/${id}`);
// console.log(`${id} purged.`);
this.socket.emit("fprint-enroll", { finger });
},
saveFingerPrint: async function () {
this.busy.login = true;
try {
var fingerprints = Object.keys(this.fingerprints).map(finger => {
return {
finger,
fingerprint: this.fingerprints[finger]
}
});
var { data } = await axios.post(
this.authenticateUrl(`/uc/fingerprints/${this.staff.reference}`),
{ fingerprints }
);
if (data.ok) {
swal("Saved", `Fingerprint saved for ${this.staff.name} with reference ${this.staff.reference}.`, "success");
this.newEnrolment();
} else {
swal("Oops!", `Operation failed. ${data.message}.` + this.staff.reference, "error");
}
} finally {
this.busy.login = false;
}
},
newEnrolment: function () {
this.step = 1.0;
this.staff.reference = "";
}
}
})
+175
View File
@@ -0,0 +1,175 @@
<html>
<head>
<title>Fingerprint Service</title>
<script src="https://cdn.socket.io/4.4.0/socket.io.min.js" integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<style>
.disabledbutton {
pointer-events: none;
opacity: 0.4;
}
</style>
</head>
<body style="font-size: 14px; font-family: 'Segoe UI';">
<div class="container" id="app">
<div class="col-md-12">
<div style="margin-top: 100px;">
</div>
<h1>
UNICAL Biometrics Enrolment Wizard
</h1>
<hr />
<div v-if="step > 0" style="text-align: right">
<span style="cursor: pointer;" v-on:click="newEnrolment">+ New
Enrolment</span>&nbsp;&nbsp;&bull;&nbsp;&nbsp;
<span>~{{user.username.substring(7)}}</span> &nbsp;&nbsp;&bull;&nbsp;&nbsp; <span v-on:click='logout'
style="cursor: pointer; font-weight: bold;">Logout</span>
<hr />
</div>
<div v-if="step == 0">
<div style="background-color: whitesmoke; margin-left: auto; margin-right: auto; padding: 10px;">
<form class="form" style="padding: 20px;">
<h3>Agent Login</h3>
<br />
<div class="form-group">
<label>Phone Number</label>
<input type="text" v-model="phone" class="form-control" />
</div>
<div class="form-group">
<label>One Time Password</label>
<input type="password" v-model="otp" class="form-control" />
</div>
<div class="form-group">
<div class="btn btn-success btn-block" v-bind:class="{ disabledbutton: busy.login || !phone || !otp }"
v-on:click="login">
<span v-if="!busy.login">Login</span>
<span v-else>Please wait...</span>
</div>
</div>
<div class="form-group" v-if="errorMessage">
<div class="alert alert-danger">{{errorMessage}}</div>
</div>
</form>
</div>
</div>
<div v-if="step >= 1">
<div v-if="step == 1.0">
<form class="form" style="padding: 20px;">
<h3>New Profile Enrollment</h3>
<br />
<div class="form-group">
<label>Reference Number</label>
<input type="text" v-model="staff.reference" class="form-control" />
</div>
<div class="form-group">
<label>OTP</label>
<input type="text" v-model="otp" class="form-control" />
</div>
<div class="form-group">
<div class="btn btn-success" v-bind:class="{ disabledbutton: busy.login || !staff.reference || !otp }"
v-on:click="loadUserByReference">
<span v-if="!busy.login">Get Details</span>
<span v-else>Please wait...</span>
</div>
</div>
</form>
</div>
<div v-if="step >= 1.1">
<form class="form form-horizontal" style="padding: 20px;">
<h3>Enroll Profile</h3>
<br />
<div class="form-group">
<label>Reference Number</label>
<input type="text" readonly v-model="staff.reference" class="form-control" />
</div>
<div class="form-group">
<label>Name</label>
<input type="text" readonly v-model="staff.name" class="form-control" />
</div>
<div class="form-group">
<label>Reference</label>
<input type="text" readonly v-model="staff.domainReference" class="form-control" />
</div>
<div class="form-group">
<label>Rank</label>
<input type="text" readonly v-model="staff.domainRankDescription" class="form-control" />
</div>
<div class="form-group">
<label>Total Fingerprint Enrollment(s)</label>
<input type="text" readonly v-model="staff.fingerPrintCaptureCount" class="form-control" />
</div>
<div class="form-group" v-if="step >= 1.1">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Finger</label>
<input type="text" readonly value="Right Thumb" class="form-control" />
</div>
<div class="form-group" v-if="fingerDetails['right-thumb'].id">
<label>Enrolment ID</label>
<input type="text" readonly v-model="fingerDetails['right-thumb'].id" class="form-control" />
</div>
<div class="btn btn-success" style="display: inline" v-if="!fingerDetails['right-thumb'].id" v-bind:class="{ disabledbutton: busy.login }"
v-on:click="() => { captureFingerPrint('right-thumb') }">
<span v-if="!busy.login">Capture Fingerprint</span>
<span v-else>Please wait...</span>
</div>
<div class="btn btn-warning" style="display: inline" v-if="fingerDetails['right-thumb'].id" v-bind:class="{ disabledbutton: busy.login }"
v-on:click="() => { captureFingerPrint('right-thumb') }">
<span v-if="!busy.login">Recapture Fingerprint</span>
<span v-else>Please wait...</span>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>Finger</label>
<input type="text" readonly value="Right Index Finger" class="form-control" />
</div>
<div class="form-group" v-if="fingerDetails['right-index-finger'].id">
<label>Enrolment ID</label>
<input type="text" readonly v-model="fingerDetails['right-index-finger'].id" class="form-control" />
</div>
<div class="btn btn-success" style="display: inline" v-if="!fingerDetails['right-index-finger'].id" v-bind:class="{ disabledbutton: busy.login }"
v-on:click="() => { captureFingerPrint('right-index-finger') }">
<span v-if="!busy.login">Capture Fingerprint</span>
<span v-else>Please wait...</span>
</div>
<div class="btn btn-warning" style="display: inline" v-if="fingerDetails['right-index-finger'].id" v-bind:class="{ disabledbutton: busy.login }"
v-on:click="() => { captureFingerPrint('right-index-finger') }">
<span v-if="!busy.login">Recapture Fingerprint</span>
<span v-else>Please wait...</span>
</div>
</div>
</div>
<!-- &nbsp;&nbsp;Your profile has <span style="color: red; font-weight: bold;" v-if="!staff.verified">NOT </span>been verified. -->
</div>
<div v-if="fingerDetails['right-thumb'].id && fingerDetails['right-index-finger'].id">
<div class="form-group">
<label>OTP</label>
<input type="text" v-model="otp" class="form-control" />
</div>
<div class="form-group">
<div class="btn btn-success" v-bind:class="{ disabledbutton: busy.login || !otp }"
v-on:click="saveFingerPrint">
<span v-if="!busy.login">Save Finger Print</span>
<span v-else>Please wait...</span>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- production version, optimized for size and speed -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
<script src="/assets/app.js"></script>
</body>
</html>