Skip to content

Commit

Permalink
[321] Show localized warning to the user when drive is not verified (#…
Browse files Browse the repository at this point in the history
…417)

* Show localized warning to the user when drive is not verified

* Show localized warning to the user when drive is not verified

* Update alert box for unsynced drives to be the same as for synced ones

* Space the buttons around

* Space the buttons around

* Remove unused field in form

* Loop drive syncing until all are sent correctly

* Specify length in regex
  • Loading branch information
arturtamborski authored Feb 5, 2020
1 parent b1c887e commit ea12139
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 63 deletions.
2 changes: 1 addition & 1 deletion backend/fleet_management/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
1 change: 1 addition & 0 deletions backend/fleet_management/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class Meta:
"end_location",
"timestamp",
"signature",
"is_verified",
)
read_only_fields = ("is_verified",)

Expand Down
14 changes: 8 additions & 6 deletions backend/pah_fm/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/components/MainForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
@reset.prevent="$emit('reset')"
>
<slot />
<div class="form-group">
<div class="form-group form-buttons">
<button class="btn btn-primary col-xs-3">
{{ $t('drive_form.submit') }}
</button>
<span style="flex: 1" />
<input
v-if="resetable"
type="reset"
Expand Down Expand Up @@ -55,3 +56,10 @@ export default {
},
};
</script>

<style scoped lang="scss">
.form-buttons {
display: flex;
flex-direction: row;
}
</style>
6 changes: 4 additions & 2 deletions frontend/src/services/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
1 change: 1 addition & 0 deletions frontend/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -21,6 +22,7 @@ Vue.use(Vuex);

const initialState = {
[USER]: null,
[HASH]: null,
[INCORRECT_DRIVE_ENTRIES]: [],
[UNSYNCHRONISED_DRIVES]: [],
[LANGUAGE]: null,
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
"project": "Проект",
"starting_mileage": "Початкове значення вимірювального приладу",
"unsynced_drives": "Не синхронізовані поїздки",
"total_mileage": "Total {total} km"
"total_mileage": "Всього {total} км",
"unverified_drive": "Цей привід не перевірено, зв'яжіться з людиною з ПАУ, відповідальною за накопичувачі, щоб вирішити його"
},
"header": {
"polish_humanitarian_action": "Польська Гуманітарна Акція"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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",
Expand Down
53 changes: 25 additions & 28 deletions frontend/src/views/DriveFormView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -159,7 +159,7 @@
<label for="driveHash">{{ $t('drive_form.drive_hash') }}</label>
<input
id="driveHash"
type="number"
type="text"
v-model.number="computeHash"
class="form-control"
readonly
Expand All @@ -169,23 +169,19 @@
<label for="signature">{{ $t('drive_form.signature') }}</label>
<input
id="signature"
type="number"
name="signature"
min="0"
type="text"
pattern="[0-9]{6}"
inputmode="numeric"
maxlength="6"
v-model.number="form.signature"
onkeypress="return event.key === 'Enter'
|| (Number(event.key) >= 0
&& Number(event.key) <= 9
&& event.target.value < 20000000)"
v-model="form.signature"
class="form-control"
:class="{ 'is-invalid': isInvalid['signature'] }"
>
</div>
<div class="form-group col-xs-12">
{{ $t('drive_form.distance_traveled', { distance: distance }) }}
</div>

<b-alert
class="col-xs-12"
variant="success"
Expand All @@ -200,10 +196,18 @@
variant="secondary"
dismissible
:show="confirmationOffline"
@dismissed="confirmationffline = false"
@dismissed="confirmationOffline=false"
>
<b>{{ $t('drive_form.drive_added_offline_notification') }}</b>
</b-alert>
<b-alert
class="col-xs-12"
variant="warning"
dismissible
:show="(confirmationOnline || confirmationOffline) && !isVerified"
>
<b>{{ $t('drives.unverified_drive') }}</b>
</b-alert>
</main-form>
</template>

Expand Down Expand Up @@ -260,7 +264,7 @@ export default {
components: { vSelect, MainForm },
mixins: [FormMixin, GroupGuardMixin],
mounted() {
this.loadFormData({ ...initialFormData });
this.loadFormData(initialFormData);
},
data() {
return {
Expand All @@ -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),
},
Expand All @@ -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];
Expand Down
26 changes: 19 additions & 7 deletions frontend/src/views/DrivesView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
class="card"
v-for="drive in unsyncedDrives"
:key="drive.id"
:class="{ verified: drive.verified }"
>
<div
class="card-header"
@click="showDrive(drive.timestamp)"
:class="{ verified: drive.isVerified }"
>
<h5 class="mb-0">
<span class="font-weight-bold">{{ drive.date }}</span>
Expand Down Expand Up @@ -56,6 +56,13 @@
<span class="font-weight-bold mr-1">{{ $t('drives.ending_mileage') }}</span>
<span>{{ drive.endMileage }}</span>
</p>
<div
v-if="!drive.isVerified"
class="alert alert-warning col-xs-12"
role="alert"
>
{{ $t('drives.unverified_drive') }}
</div>
</div>
</div>
</div>
Expand All @@ -80,11 +87,11 @@
<div
class="card-header"
@click="showDrive(drive.id)"
:class="{ verified: drive.verified }"
:class="{ verified: drive.isVerified }"
>
<h5 class="mb-0">
<span class="font-weight-bold">{{ drive.date }}</span>
{{ $t('drives.from_to', { from: drive.startLocation, destination: drive.endLocation}) }}
{{ $t('drives.from_to', { from: drive.startLocation, destination: drive.endLocation }) }}
</h5>
</div>
<div :class="['collapse', { show: visibleDrive === drive.id }]">
Expand All @@ -109,6 +116,13 @@
<span class="font-weight-bold mr-1">{{ $t('drives.ending_mileage') }}</span>
<span>{{ drive.endMileage }}</span>
</p>
<div
v-if="!drive.isVerified"
class="alert alert-warning col-xs-12"
role="alert"
>
{{ $t('drives.unverified_drive') }}
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -158,18 +172,16 @@ export default {
</script>

<style scoped lang="scss">
@import '../scss/base';
.card-header {
cursor: pointer;
border-left: 5px solid #28a745;
border-left: 5px solid #ffc107;
}
.heading {
text-align: center;
}
.verified {
border-left: 5px solid #ffc107;
border-left: 5px solid #28a745;
}
</style>
13 changes: 5 additions & 8 deletions frontend/src/views/PassengerSubmitView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
id="signature"
type="text"
name="signature"
v-model.number="computeSignature"
class="form-control passenger-input"
:value="computeSignature()"
readonly
>
</div>
Expand All @@ -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],
Expand All @@ -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);
},
},
};
Expand Down
Loading

0 comments on commit ea12139

Please sign in to comment.