diff --git a/backend/fleet_management/admin.py b/backend/fleet_management/admin.py index 6adb123c..a16a8484 100644 --- a/backend/fleet_management/admin.py +++ b/backend/fleet_management/admin.py @@ -48,7 +48,7 @@ class Meta: class DriveAdmin(ImportExportModelAdmin): resource_class = DriveResource list_filter = ("driver__country",) - list_display = ("__str__", "country") + list_display = ("__str__", "country", "is_verified") class CustomUserAdmin(UserAdmin): diff --git a/backend/fleet_management/serializers.py b/backend/fleet_management/serializers.py index 1fcaf111..c8df9448 100644 --- a/backend/fleet_management/serializers.py +++ b/backend/fleet_management/serializers.py @@ -90,6 +90,7 @@ class Meta: "end_location", "timestamp", "signature", + "is_verified", ) read_only_fields = ("is_verified",) diff --git a/backend/pah_fm/settings.py b/backend/pah_fm/settings.py index fffb7c9a..eec23b9a 100644 --- a/backend/pah_fm/settings.py +++ b/backend/pah_fm/settings.py @@ -28,12 +28,14 @@ DEBUG = os.environ.get('DEBUG', '0') == '1' ALLOWED_HOSTS = [ - 'localhost', - '127.0.0.1', - '52.232.62.212', - '.pahfm.codeforpoznan.pl', - '.lemik.pl', - ] + 'localhost', + '127.0.0.1', + '52.232.62.212', + '.pahfm.codeforpoznan.pl', +] + +if DEBUG: + ALLOWED_HOSTS = ['*'] # Application definition diff --git a/frontend/src/components/MainForm.vue b/frontend/src/components/MainForm.vue index 266ec878..d8f86004 100644 --- a/frontend/src/components/MainForm.vue +++ b/frontend/src/components/MainForm.vue @@ -14,10 +14,11 @@ @reset.prevent="$emit('reset')" > -
+
+ + + diff --git a/frontend/src/services/crypto.js b/frontend/src/services/crypto.js index 14eab79a..a6c08410 100644 --- a/frontend/src/services/crypto.js +++ b/frontend/src/services/crypto.js @@ -37,6 +37,8 @@ const modexp = (base, exp, mod) => { return res; }; -export const sign = (msg, priv) => modexp(msg, priv.d, priv.n); +const int = n => parseInt(n, 10); -export const verify = (msg, sgn, pub) => modexp(sgn, pub.e, pub.n) === msg % pub.n; +export const sign = (msg, d, n) => modexp(int(msg), int(d), int(n)); + +export const verify = (msg, sgn, e, n) => modexp(int(sgn), int(e), int(n)) === int(msg) % int(n); diff --git a/frontend/src/store/actions.js b/frontend/src/store/actions.js index 87359c1b..b2136d69 100644 --- a/frontend/src/store/actions.js +++ b/frontend/src/store/actions.js @@ -92,6 +92,7 @@ export const actions = { try { await post('drives', mappedDrive); commit(SYNC_ITEM_SUCCESS, timestamp); + dispatch(SYNC); } catch (e) { if (e.response && e.response.status === 409) { // was synced previously diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 796a8802..3ff46c12 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -12,6 +12,7 @@ import { modules } from './modules'; import { totalMileageReducer, totalMileageFilter } from '../utils'; export const USER = 'user'; +export const HASH = 'hash'; export const CARS = 'cars'; export const LANGUAGE = 'language'; @@ -21,6 +22,7 @@ Vue.use(Vuex); const initialState = { [USER]: null, + [HASH]: null, [INCORRECT_DRIVE_ENTRIES]: [], [UNSYNCHRONISED_DRIVES]: [], [LANGUAGE]: null, diff --git a/frontend/src/translations.json b/frontend/src/translations.json index 14ed249c..c681a14b 100644 --- a/frontend/src/translations.json +++ b/frontend/src/translations.json @@ -56,7 +56,8 @@ "project": "Проект", "starting_mileage": "Початкове значення вимірювального приладу", "unsynced_drives": "Не синхронізовані поїздки", - "total_mileage": "Total {total} km" + "total_mileage": "Всього {total} км", + "unverified_drive": "Цей привід не перевірено, зв'яжіться з людиною з ПАУ, відповідальною за накопичувачі, щоб вирішити його" }, "header": { "polish_humanitarian_action": "Польська Гуманітарна Акція" @@ -142,7 +143,8 @@ "project": "Project", "starting_mileage": "Starting mileage:", "unsynced_drives": "Unsynchronized drives", - "total_mileage": "Total {total} km" + "total_mileage": "Total {total} km", + "unverified_drive": "This drive was not verified, contact with a person from PAH responsible for drives to solve it." }, "header": { "polish_humanitarian_action": "Polish Humanitarian Action" @@ -228,7 +230,8 @@ "project": "Projekt", "starting_mileage": "Początkowy stan licznika:", "unsynced_drives": "Przejazdy niezsynchronizowane", - "total_mileage": "Razem {total} km" + "total_mileage": "Razem {total} km", + "unverified_drive": "Ten przejazd nie został zweryfikowany, skontaktuj się z osobą z PAH odpowiedzialną za przejazdy by to wyjaśnić." }, "login": { "password": "Hasło", diff --git a/frontend/src/views/DriveFormView.vue b/frontend/src/views/DriveFormView.vue index f2c09f5c..16c62e90 100644 --- a/frontend/src/views/DriveFormView.vue +++ b/frontend/src/views/DriveFormView.vue @@ -41,7 +41,7 @@ && Number(event.key) <= 9 && event.target.value < 20000000)" type="number" - v-model="form.startMileage" + v-model.number="form.startMileage" name="startMileage" @input="syncToLocalStorage" class="form-control" @@ -148,7 +148,7 @@ && Number(event.key) <= 9 && event.target.value < 20000000)" type="number" - v-model="form.endMileage" + v-model.number="form.endMileage" @input="syncToLocalStorage" name="endMileage" class="form-control" @@ -159,7 +159,7 @@ {{ $t('drive_form.signature') }} @@ -185,7 +182,6 @@
{{ $t('drive_form.distance_traveled', { distance: distance }) }}
- {{ $t('drive_form.drive_added_offline_notification') }} + + {{ $t('drives.unverified_drive') }} + @@ -260,7 +264,7 @@ export default { components: { vSelect, MainForm }, mixins: [FormMixin, GroupGuardMixin], mounted() { - this.loadFormData({ ...initialFormData }); + this.loadFormData(initialFormData); }, data() { return { @@ -281,23 +285,20 @@ export default { this.validateForm(this.validator); this.confirmationOffline = false; this.confirmationOnline = false; + this.isVerified = false; if (this.listOfErrors.length === 0) { - const passenger = this.passengers.find(p => p.value === parseInt(this.form.passenger, 10)); - const pubKey = { - e: parseInt(passenger.rsaPubE, 10), - n: parseInt(passenger.rsaModulusN, 10), - }; - const verified = verify( - parseInt(this.computeHash, 10), + const passenger = this.passengers.find(p => p.value.toString() === this.form.passenger); + this.isVerified = verify( + this.computeHash, this.form.signature || 0, - pubKey, + passenger.rsaPubE, + passenger.rsaModulusN, ); this[actions.SUBMIT]({ form: { ...this.form, - - verified, + isVerified: this.isVerified, passengers: [this.form.passenger], timestamp: Math.floor(Date.now() / 1000), }, @@ -315,11 +316,7 @@ export default { }, validator(data) { const { startMileage, endMileage } = data; - if ( - !!startMileage && - !!endMileage && - parseInt(startMileage, 10) >= parseInt(endMileage, 10) - ) { + if (!!startMileage && !!endMileage && startMileage >= endMileage) { const errorStartMileage = this.$t('drive_form.start_mileage_error'); const errorEndMileage = this.$t('drive_form.end_mileage_error'); return [errorStartMileage, errorEndMileage]; diff --git a/frontend/src/views/DrivesView.vue b/frontend/src/views/DrivesView.vue index b36a34cc..5afc7080 100644 --- a/frontend/src/views/DrivesView.vue +++ b/frontend/src/views/DrivesView.vue @@ -23,11 +23,11 @@ class="card" v-for="drive in unsyncedDrives" :key="drive.id" - :class="{ verified: drive.verified }" >
{{ drive.date }} @@ -56,6 +56,13 @@ {{ $t('drives.ending_mileage') }} {{ drive.endMileage }}

+
@@ -80,11 +87,11 @@
{{ drive.date }} - {{ $t('drives.from_to', { from: drive.startLocation, destination: drive.endLocation}) }} + {{ $t('drives.from_to', { from: drive.startLocation, destination: drive.endLocation }) }}
@@ -109,6 +116,13 @@ {{ $t('drives.ending_mileage') }} {{ drive.endMileage }}

+
@@ -158,11 +172,9 @@ export default { diff --git a/frontend/src/views/PassengerSubmitView.vue b/frontend/src/views/PassengerSubmitView.vue index 2b7fd36b..731455e2 100644 --- a/frontend/src/views/PassengerSubmitView.vue +++ b/frontend/src/views/PassengerSubmitView.vue @@ -10,8 +10,8 @@ id="signature" type="text" name="signature" - v-model.number="computeSignature" class="form-control passenger-input" + :value="computeSignature()" readonly > @@ -31,7 +31,7 @@ import '../scss/passenger.scss'; import { GET_HASH } from '../store/constants'; import { sign } from '../services/crypto'; import { USER } from '../store'; -import { padWithZeros } from '../utils'; +import { padWithZeros as pad } from '../utils'; export default { mixins: [GroupGuardMixin], @@ -43,15 +43,12 @@ export default { return next({ path: '/passenger' }); }, computed: { - getHash: undefined, ...mapState([USER]), ...mapGetters([GET_HASH]), + }, + methods: { computeSignature() { - const privKey = { - d: parseInt(this.user.rsaPrivD, 10), - n: parseInt(this.user.rsaModulusN, 10), - }; - return padWithZeros(sign(this.getHash, privKey), 6); + return pad(sign(this.getHash, this.user.rsaPrivD, this.user.rsaModulusN), 6); }, }, }; diff --git a/frontend/src/views/PassengerView.vue b/frontend/src/views/PassengerView.vue index ace21c61..e46c5dcf 100644 --- a/frontend/src/views/PassengerView.vue +++ b/frontend/src/views/PassengerView.vue @@ -8,14 +8,19 @@
@@ -61,7 +66,7 @@ export default { } }, validator() { - if (String(this.form.hash).length !== 6) { + if (this.form.hash.length !== 6) { this.isInvalid.hash = true; return [this.$t('passenger_form.invalid_length')]; }