Skip to content
Snippets Groups Projects
Commit 66445b0f authored by Anders H. Rebner's avatar Anders H. Rebner
Browse files

#86 Autentifiseringstavlemodul bruker coder, coder modifisert

parent ea490850
No related branches found
No related tags found
1 merge request!50#86 Modul: Autentiseringstavle
Pipeline #78079 failed
"""Generate codes."""
import string
"""Generate codes.
# https://realpython.com/lessons/cryptographically-secure-random-data-python/
Source: # https://realpython.com/lessons/cryptographically-secure-random-data-python/
"""
import string
import secrets
def get_code(code_length, mode="ascii"):
def get_code(code_length, mode="ascii", space_interval=0):
"""
Generate a single random code.
......@@ -13,18 +14,18 @@ def get_code(code_length, mode="ascii"):
----------
code_length : int
The length of the code
mode : string
'ascii' for letters (default), 'digits' for digits and 'combo'
for combination of letters and digits.
for combination of letters and digits, by default 'ascii'.
space_interval : int or None
Spaces will be inserted to code each interval if not 0, by default 0.
Return
------
code : string
The code
The code.
"""
code = ""
i = 0
if mode == "ascii":
characters = string.ascii_uppercase
......@@ -37,10 +38,22 @@ def get_code(code_length, mode="ascii"):
"Invalid value for argument 'mode': " "'{}'".format(mode)
)
if not isinstance(space_interval, int):
raise ValueError(
"Invalid value for argument 'separate_interval': "
"'{}'".format(space_interval)
)
i = 0
while i < code_length:
letter = secrets.choice(characters)
code += letter
i += 1
# Add spaces to code if interval is given
if space_interval > 0:
code = insert_spaces(code, space_interval)
return code
......@@ -93,3 +106,41 @@ def get_code_length_needed(number_of_entries):
code_length = code_length + 1
return code_length
def insert_spaces(code, interval):
"""Add spaces between code-character each interval.
Parameters
----------
code : string
Code to add spaces to.
interval : int
Interval for inserting spaces.
Returns
-------
string
Code separated with spaces.
"""
# Choose starting point for separating code with spaces, depending on
# SEPARATE_INTERVAL and CODE_LENGTH being even or odd numbers.
# If code is 1234567 and interval is 3, code will be 1234 567 instead
# of 123 456 7 after space separation.
code_length = len(code)
if (
interval % 2 == 0
and code_length % 2 == 0
or interval % 2 != 0
and code_length % 2 != 0
):
start = interval - 1
else:
start = interval
# Convert to list to add spaces in-between characters
code = list(code)
for i in range(start, code_length - interval, interval):
code[i] += " "
return "".join(code)
"""Module containing SOI-module 'Autentifiseringstavle'."""
import string
from random import choices
from PySide2.QtWidgets import QTableWidget, QTableWidgetItem
from PySide2 import QtGui
from PySide2.QtCore import Qt
from soitool.coder import get_code
from soitool.modules.module_base import (
ModuleBase,
get_table_size,
......@@ -13,10 +13,11 @@ from soitool.modules.module_base import (
START_NO_OF_AUTHENTICATION_CODES = 10
CODE_LENGTH = 26
CODE_CHARACTERS = string.ascii_uppercase # Codes consist of these characters
CODE_CHARACTERS = "ascii" # Has to be 'ascii', 'digits' or 'combo'
# Codes will consist of A-Z if 'ascii', 0-9 if 'digits' and A-Z+0-9 if 'combo'.
ROW_IDENTIFIERS = string.ascii_uppercase # Characters for first column,
# it's length determines maximum number of codes (rows).
SEPARATE_INTERVAL = 5 # Adds space between sets of characters, 0 => no spaces
SPACE_INTERVAL = 5 # Adds space between sets of characters, 0 => no spaces
# If code is 123456 and interval is 2, code will be 12 34 56
# If code is 1234567 and interval is 2, code will be 123 45 67
......@@ -32,7 +33,7 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta):
By default, the widget initializes with a headline, a row-count of
START_NO_OF_AUTHENTIFICATION_CODES and three columns.
Row x in the first column contains the character CODE_CHARACTERS[x].
Row x in the first column contains the character ROW_IDENTIFIERS[x].
Row x in the second column contains the character x.
Row x in the third column contains an authentification code.
......@@ -53,6 +54,18 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta):
QTableWidget.__init__(self)
ModuleBase.__init__(self)
if CODE_CHARACTERS == "ascii":
self.code_characters = string.ascii_uppercase
elif CODE_CHARACTERS == "digits":
self.code_characters = string.digits
elif CODE_CHARACTERS == "combo":
self.code_characters = string.ascii_uppercase + string.digits
else:
raise ValueError(
"Invalid value for CONSTANT 'CODE_CHARACTERS': "
"'{}'".format(CODE_CHARACTERS)
)
# Remove headers and scrollbars
self.horizontalHeader().hide()
self.verticalHeader().hide()
......@@ -140,30 +153,10 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta):
# Randomly generate a new code until it is unique
unique_code = False
while not unique_code:
code = choices(CODE_CHARACTERS, k=CODE_LENGTH)
code = get_code(CODE_LENGTH, CODE_CHARACTERS, SPACE_INTERVAL)
unique_code = code not in existing_codes
# Choose starting point for separating code with spaces, depending on
# SEPARATE_INTERVAL and CODE_LENGTH being even or odd numbers.
# If code is 1234567 and interval is 3, code will be 1234 567 instead
# of 123 456 7 after space separation.
if (
SEPARATE_INTERVAL % 2 == 0
and CODE_LENGTH % 2 == 0
or SEPARATE_INTERVAL % 2 != 0
and CODE_LENGTH % 2 != 0
):
start = SEPARATE_INTERVAL - 1
else:
start = SEPARATE_INTERVAL
# Separate code with spaces
for i in range(
start, len(code) - SEPARATE_INTERVAL, SEPARATE_INTERVAL
):
code[i] += " "
return "".join(code)
return code
def keyPressEvent(self, event):
"""Add or remove row when 'Ctrl + +' and 'Ctrl + -' are pressed."""
......@@ -193,7 +186,7 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta):
# Loop through all rows starting with the new row
for i in range(row_index + 1, self.rowCount()):
# Insert row identifier in first column
item_first = QTableWidgetItem(CODE_CHARACTERS[i - 1])
item_first = QTableWidgetItem(self.code_characters[i - 1])
item_first.setFlags(item_first.flags() ^ Qt.ItemIsEditable)
self.setItem(i, 0, item_first)
......@@ -223,7 +216,7 @@ class AuthentificationBoardModule(ModuleBase, QTableWidget, metaclass=Meta):
# 'Decrease' row identifiers below the removed row
# If first row is removed, identifier A,B,C becomes A,B (not B,C)
for i in range(row_index, self.rowCount()):
self.item(i, 0).setText(CODE_CHARACTERS[i - 1])
self.item(i, 0).setText(self.code_characters[i - 1])
self.item(i, 1).setText(str(i - 1))
resize_table(self, resize_column=False)
......@@ -296,24 +289,7 @@ def generate_authentification_codes(amount=START_NO_OF_AUTHENTICATION_CODES):
"""
codes = []
for _ in range(amount):
code = choices(CODE_CHARACTERS, k=CODE_LENGTH)
# Choose starting point for separating code with spaces, depending on
# SEPARATE_INTERVAL and CODE_LENGTH being even or odd numbers.
# If code is 1234567 and interval is 3, code will be 1234 567 instead
# of 123 456 7 after space separation.
if (
SEPARATE_INTERVAL % 2 == 0
and CODE_LENGTH % 2 == 0
or SEPARATE_INTERVAL % 2 != 0
and CODE_LENGTH % 2 != 0
):
start = SEPARATE_INTERVAL - 1
else:
start = SEPARATE_INTERVAL
for i in range(
start, len(code) - SEPARATE_INTERVAL, SEPARATE_INTERVAL
):
code[i] += " "
codes.append("".join(code))
code = get_code(CODE_LENGTH, CODE_CHARACTERS, SPACE_INTERVAL)
codes.append(code)
return codes
......@@ -10,7 +10,6 @@ from soitool.modules.module_authentification_board import (
HEADLINE_TEXT,
ROW_IDENTIFIERS,
CODE_LENGTH,
CODE_CHARACTERS,
)
from soitool.soi import SOI
......@@ -50,10 +49,10 @@ class TestDefaultAuthentificationBoardModule(unittest.TestCase):
# Assert cell content in third column is correct
code = self.module.item(1, 2).text()
self.assertTrue(len(code) >= CODE_LENGTH)
# Assert all code characters are taken from list CODE_CHARACTERS
# Assert all code characters are taken from list code_characters
for _, character in enumerate(code):
if character != " ":
self.assertTrue(character in CODE_CHARACTERS)
self.assertTrue(character in self.module.code_characters)
# Assert all codes are unique
code_list = self.module.get_codes()
code_set = set(code_list)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment