blob: ebc63a6018eb526eb509ed1f949c2e7ca3573c2c [file] [log] [blame]
Philipp Maier2b11c322021-03-17 12:37:39 +01001# coding=utf-8
2"""Abstraction of card data that can be queried from external source
3
4(C) 2021 by Sysmocom s.f.m.c. GmbH
5All Rights Reserved
6
7Author: Philipp Maier
8
9This program is free software: you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation, either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program. If not, see <http://www.gnu.org/licenses/>.
21"""
22
23import csv
24
25card_data_provider = []
26
27class CardData(object):
28
Philipp Maier46f09af2021-03-25 20:24:27 +010029 VALID_FIELD_NAMES = ['ICCID', 'ADM1', 'IMSI', 'PIN1', 'PIN2', 'PUK1', 'PUK2']
Philipp Maier2b11c322021-03-17 12:37:39 +010030
31 # check input parameters, but do nothing concrete yet
32 def get_data(self, fields=[], key='ICCID', value=""):
33 """abstract implementation of get_data that only verifies the function parameters"""
34
35 for f in fields:
36 if (f not in self.VALID_FIELD_NAMES):
37 raise ValueError("Requested field name '%s' is not a valid field name, valid field names are: %s" %
38 (f, str(self.VALID_FIELD_NAMES)))
39
40 if (key not in self.VALID_FIELD_NAMES):
41 raise ValueError("Key field name '%s' is not a valid field name, valid field names are: %s" %
42 (key, str(self.VALID_FIELD_NAMES)))
43
44 return {}
45
46 def get_field(self, field, key='ICCID', value=""):
47 """get a single field from CSV file using a specified key/value pair"""
48 fields = [field]
49 result = self.get(fields, key, value)
50 return result.get(field)
51
52
53class CardDataCsv(CardData):
54 """card data class that allows the user to query against a specified CSV file"""
55 csv_file = None
56 filename = None
57
58 def __init__(self, filename):
59 self.csv_file = open(filename, 'r')
60 if not self.csv_file:
61 raise RuntimeError("Could not open CSV-File '%s'" % filename)
62 self.filename = filename
63
64 def get(self, fields, key, value):
65 """get fields from CSV file using a specified key/value pair"""
66 super().get_data(fields, key, value)
67
68 self.csv_file.seek(0)
69 cr = csv.DictReader(self.csv_file)
70 if not cr:
71 raise RuntimeError("Could not open DictReader for CSV-File '%s'" % self.filename)
72 cr.fieldnames = [ field.upper() for field in cr.fieldnames ]
73
74 rc = {}
75 for row in cr:
76 if row[key] == value:
77 for f in fields:
78 if f in row:
79 rc.update({f : row[f]})
80 else:
81 raise RuntimeError("CSV-File '%s' lacks column '%s'" %
82 (self.filename, f))
83 return rc
84
85
86def card_data_register(provider, provider_list=card_data_provider):
87 """Register a new card data provider"""
88 if not isinstance(provider, CardData):
89 raise ValueError("provider is not a card data provier")
90 provider_list.append(provider)
91
92
93def card_data_get(fields, key, value, provider_list=card_data_provider):
94 """Query all registered card data providers"""
95 for p in provider_list:
96 if not isinstance(p, CardData):
97 raise ValueError("provider list contains provider, which is not a card data provier")
98 result = p.get(fields, key, value)
99 if result:
100 return result
101 return {}
102
103
104def card_data_get_field(field, key, value, provider_list=card_data_provider):
105 """Query all registered card data providers for a single field"""
106 for p in provider_list:
107 if not isinstance(p, CardData):
108 raise ValueError("provider list contains provider, which is not a card data provier")
109 result = p.get_field(field, key, value)
110 if result:
111 return result
112 return None
113