blob: fb0fd9e8cab93f02b8160264a2c5177f3f531d0b [file] [log] [blame]
Weiweie5640c62015-07-31 01:43:01 -07001# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2#
3# Copyright (C) 2014 Regents of the University of California.
4# Author: Teng Liang <philoliang2011@gmail.com>
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program. If not, see <http://www.gnu.org/licenses/>.
17# A copy of the GNU General Public License is in the file COPYING.
18"""
19DeviceUserAccessStorage implements a basic storage of devices, users and access
20"""
21
22import os
23import sqlite3
24from pyndn import Name
25from device_profile import DeviceProfile
26from hmac_key import HMACKey
27INIT_DEVICE_TABLE = ["""
28CREATE TABLE IF NOT EXISTS
29 Device(
30 id INTEGER,
31 prefix BLOB NOT NULL UNIQUE,
32 location BLOB,
33 category BLOB,
34 type BLOB,
35 model BLOB,
36 serial_number BLOB,
37 manufacturer BLOB,
38 seed_name BLOB NOT NULL,
39 seed_sequence BLOB NOT NULL,
40 seed_counter BLOB NOT NULL,
41 seed BLOB NOT NULL,
42 configuration_token BLOB NOT NULL,
43 configuration_token_sequence BLOB NOT NULL,
44 configuration_token_counter BLOB NOT NULL,
45
46 PRIMARY KEY (id)
47 );
48"""]
49
50INIT_COMMAND_TABLE = ["""
51CREATE TABLE IF NOT EXISTS
52 Command(
53 id INTEGER,
54 device_id INTEGER NOT NULL,
55 name BLOB NOT NULL,
56 command_token_name BLOB NOT NULL,
57 command_token_sequence BLOB NOT NULL,
58 command_token_counter BLOB NOT NULL,
59 command_token BLOB NOT NULL,
60
61 PRIMARY KEY(id)
62 FOREIGN KEY(device_id) REFERENCES Device(id)
63 );
64"""]
65
66INIT_SERVICE_PROFILE_TABLE = ["""
67CREATE TABLE IF NOT EXISTS
68 ServiceProfile(
69 id INTEGER,
70 device_id INTEGER NOT NULL,
71 name BLOB NOT NULL,
72
73 PRIMARY KEY(id)
74 FOREIGN KEY(device_id) REFERENCES Device(id)
75 );
76"""]
77
78class DeviceUserAccessStorage(object):
79 """
80 Create a new DeviceUserStorage to work with an SQLite file.
81 :param str databaseFilePath: (optional) The path of the SQLite file. If ommitted, use the default path.
82 """
83 def __init__(self, databaseFilePath = None):
84 if databaseFilePath == None or databaseFilePath == "":
85 if not "HOME" in os.environ:
86 home = '.'
87 else:
88 home = os.environ["HOME"]
89
90 dbDirectory = os.path.join(home, '.ndn')
91 if not os.path.exists(dbDirectory):
92 os.makedirs(dbDirectory)
93
94 databaseFilePath = os.path.join(dbDirectory, 'ndnhome-controller.db')
95
96 self._database = sqlite3.connect(databaseFilePath)
97
98 #Check if the Device table exists
99 cursor = self._database.cursor()
100 cursor.execute("SELECT name FROM sqlite_master WHERE TYPE ='table' and NAME = 'Device'")
101 if cursor.fetchone() == None:
102 #no device table exists, create one
103 for command in INIT_DEVICE_TABLE:
104 self._database.execute(command)
105 cursor.close()
106
107 #Check if the Command table exists
108 cursor = self._database.cursor()
109 cursor.execute("SELECT name FROM sqlite_master WHERE TYPE ='table' and NAME = 'Command'")
110 if cursor.fetchone() == None:
111 #no command table exists, create one
112 for command in INIT_COMMAND_TABLE:
113 self._database.execute(command)
114 cursor.close()
115
116 #Check if the ServiceProfile table exists
117 cursor = self._database.cursor()
118 cursor.execute("SELECT name FROM sqlite_master WHERE TYPE ='table' and NAME = 'ServiceProfile'")
119 if cursor.fetchone() == None:
120 #no ServiceProfile table exists, create one
121 for command in INIT_SERVICE_PROFILE_TABLE:
122 self._database.execute(command)
123 cursor.close()
124
125 self._database.commit()
126
127 def doesTableExist(self, tableName):
128 """
129 check if table exists
130 :param str tableName
131 :return True if exists, otherwise False
132 """
133 selectOperation = "SELECT name FROM sqlite_master WHERE TYPE='table' and NAME='" + tableName +"'"
134 #print selectOperation
135 cursor = self._database.cursor()
136 cursor.execute(selectOperation)
137 if cursor.fetchone() == None:
138 result = False
139 else:
140 result = True
141 cursor.close()
142 return result
143
144 def doesDeviceExist(self, prefix):
145 """
146 Check if the specified device already exists.
147
148 :param Name prefix: the prefix of device
149 :return True if the device exists, otherwise False
150 :rtype: bool
151 """
152 result = False
153 #print prefix
154 cursor = self._database.cursor()
155 cursor.execute("SELECT count(*) FROM Device WHERE prefix =?", (prefix.toUri(),))
156 (count,) = cursor.fetchone()
157 if count > 0:
158 result = True
159 #print 'device with %s is founnd, count %d' %(prefix, count)
160
161 cursor.close()
162 return result
163
164 def addDevice(self, deviceProfile, seed, configurationToken):
165 """
166 Add a new device to the Device table, do nothing if the device already exists
167
168 :param DeviceProfile devicePorfile: the deviceProfile of the device
169 :param Key seed: the seed of the device
170 :param Key configurationToken: the configurationToken of the device
171 :return the device id if it's added successfully, 0 if the device already exists, otherwise -1
172 :rtype: INTEGER
173 """
174 result = -1
175 data = (deviceProfile.getPrefix().toUri(),
176 deviceProfile.getLocation(),
177 deviceProfile.getCategory(),
178 deviceProfile.getType(),
179 deviceProfile.getModel(),
180 deviceProfile.getManufacturer(),
181 deviceProfile.getSerialNumber(),
182 seed.getName(),
183 seed.getSequence(),
184 seed.getCounter(),
185 seed.getKey(),
186 configurationToken.getKey(),
187 configurationToken.getSequence(),
188 configurationToken.getCounter()
189 )
190
191 #check if the device already exists, if yes return 0
192 prefixName = deviceProfile.getPrefix()
193 if self.doesDeviceExist(prefixName):
194 return 0
195
196 insertDevice = (
197 "INSERT INTO Device(prefix, location, category, type, model, manufacturer, serial_number, seed_name, seed_sequence, seed_counter,seed, configuration_token, configuration_token_sequence, configuration_token_counter)"
198 "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
199 )
200 cursor = self._database.cursor()
201 cursor.execute(insertDevice, data)
202 self._database.commit()
203 result = cursor.lastrowid
204 cursor.close()
205 return result
206
207 def getDeviceProfileFromDevice(self, prefix):
208 """
209 get the specified device profile
210 :param Name prefix: the device prefix
211 :return device profile of the device if exists, otherwise return None
212 :rtype: DeviceProfile
213 """
214 operation = (
215 "Select location, category, type, model, manufacturer, serial_number FROM Device "
216 "WHERE prefix = ?"
217 )
218
219 cursor = self._database.cursor()
220 cursor.execute(operation, (prefix.toUri(),))
221 result = cursor.fetchone()
222 cursor.close()
223 # print result
224 if result == None:
225 return None
226 else:
227 deviceProfile = DeviceProfile(prefix)
228 deviceProfile.setLocation(result[0])
229 deviceProfile.setCategory(result[1])
230 deviceProfile.setType(result[2])
231 deviceProfile.setModel(result[3])
232 deviceProfile.setManufacturer(result[4])
233 deviceProfile.setSerialNumber(result[5])
234
235 return deviceProfile
236
237 def getSeed(self, prefix):
238 """
239 get the seed of the specified device
240 :param Name prefix: the device prefix
241 :return seed of the device if exists, otherwise return None
242 :rtype: HMACKey
243
244 """
245 operation = (
246 "Select seed_name, seed_sequence, seed_counter, seed FROM Device "
247 "WHERE prefix = ?"
248 )
249
250 cursor = self._database.cursor()
251 cursor.execute(operation, (prefix.toUri(),))
252 result = cursor.fetchone()
253 cursor.close()
254 print result
255 if result == None:
256 return None
257 else:
258 seed = HMACKey(result[1], result[2], result[3], result[0])
259 return seed
260
261 # raise RuntimeError("getSeed is not implemented")
262
263 def getConfigurationToken(self, prefix):
264 """
265 get the seed of the specified device
266 :param Name prefix: the device prefix
267 :return seed of the device if exists, otherwise return None
268 :rtype: HMACKey
269
270 """
271 operation = (
272 "Select configuration_token_sequence, configuration_token_counter, configuration_token FROM Device "
273 "WHERE prefix = ?"
274 )
275
276 cursor = self._database.cursor()
277 cursor.execute(operation, (prefix.toUri(),))
278 result = cursor.fetchone()
279 cursor.close()
280 print result
281 if result == None:
282 return None
283 else:
284 configurationToken = HMACKey(result[0], result[1], result[2])
285 return configurationToken
286 # raise RuntimeError("getConfigurationToken is not implemented")
287
288 def getDeviceEntry(self, prefix):
289 """
290 get the specified device entry
291 :param Name prefix: the device prefix
292 :return '' return the corresponding row of the device
293 :rtype: str
294 """
295 cursor = self._database.cursor()
296 cursor.execute("SELECT * FROM Device WHERE prefix =?", (prefix.toUri(),))
297 row = cursor.fetchone()
298 cursor.close()
299 return row
300
301 def deleteDevice(self, prefix):
302 """
303 delete specified device.
304 :param Name prefix: The device prefix
305 :return: 1 if successful, 0 if no device to delete, otherwise -1.
306 :rtype: INTEGER
307 """
308 result = -1
309 if not self.doesDeviceExist(prefix):
310 return 0
311 cursor = self._database.cursor()
312 deleteDevice = "DELETE FROM Device WHERE prefix=?"
313 cursor.execute(deleteDevice, (prefix.toUri(),))
314 self._database.commit()
315 cursor.close()
316 return 1
317
318 def getDeviceId(self, prefix):
319 """
320 get the device id of some specified device
321 :param Name prefix: the device prefix
322 :return id of the device, 0 if the device doesn't exist
323 :rtype: INTEGER
324 """
325 if not self.doesDeviceExist(prefix):
326 return 0
327 cursor = self._database.cursor()
328 operation = "SELECT id FROM Device WHERE prefix=?"
329 cursor.execute(operation, (prefix.toUri(),))
330 result = cursor.fetchone()
331 deviceId = result[0]
332 self._database.commit()
333 cursor.close()
334 return deviceId
335
336 def updateDevice(self, prefix, newDeviceProfile = None , newSeed = None , newcConfigurationToken = None ):
337 """
338 update specifided device
339 :param Name prefix
340 :param DeviceProfile newDeviceProfile
341 :param HMACKey newSeed
342 :param newConfigurationToken
343 :return id of the device if successful, 0 if device not found, otherwise -1
344 :rtype int
345 """
346 raise RuntimeError("getConfigurationToken is not implemented")
347
348 def updateOneColumnOfDevice(self, prefix, columnName, newColumnValue):
349 """
350 update the value of a specified column of a specified device
351 :param Name prefix: the device prefix
352 :param str columnName: column to be updated
353 :param newColumnValue: new column value
354 :return id of the device if successful. 0 if device not found, otherwise -1
355 :rtype int
356 """
357 result = -1
358 if not self.doesDeviceExist(prefix):
359 return 0
360
361 updateDevice = "UPDATE Device Set " + columnName + "=? WHERE prefix=?"
362 #print updateDevice
363 cursor = self._database.cursor()
364 #print newColumnValue
365 cursor.execute(updateDevice, (newColumnValue,prefix.toUri()))
366 self._database.commit()
367 result = cursor.lastrowid
368 cursor.close()
369 return result
370
371 def doesCommandExist(self, deviceId, commandName):
372 """
373 check if the specified command already exists.
374
375 :param Integer device_id: the device id
376 :return True if the command exists, otherwise False
377 :rtype: bool
378 """
379 result = False
380
381 cursor = self._database.cursor()
382 cursor.execute("SELECT count(*) FROM Command WHERE device_id =? AND name = ?", (deviceId, commandName))
383 (count,) = cursor.fetchone()
384 if count > 0:
385 result = True
386
387 cursor.close()
388 return result
389
390 def addCommand(self, deviceId, name, commandToken):
391 """
392 Add a new command to the Command table, do nothing if the device already exists
393
394 :param int deviceId: the device id to which the command belongs to
395 :param str name: the command name
396 :param HMACKey commandToken: the command token
397 :return the command id if it's added successfully, 0 if the command already exists, otherwise -1
398 :rtype: int
399 """
400 result = -1
401 data = (deviceId,
402 name,
403 commandToken.getName(),
404 commandToken.getSequence(),
405 commandToken.getCounter(),
406 commandToken.getKey()
407 )
408
409 #check if the command already exists, if yes return 0
410 if self.doesCommandExist(deviceId, name):
411 return 0
412
413 insertCommand = (
414 "INSERT INTO Command(device_id, name, command_token_name, command_token_sequence, command_token_counter, command_token)"
415 "VALUES(?,?,?,?,?,?)"
416 )
417 cursor = self._database.cursor()
418 cursor.execute(insertCommand, data)
419 self._database.commit()
420 result = cursor.lastrowid
421 cursor.close()
422 return result
423
424 def deleteCommand(self, deviceId, name = None):
425 """
426 delete specified commands.
427 :param str name: The command name, if None, delete all commands of the device
428 :param int deviceId: device id of the command
429 :return: 1 if successful, 0 if no command to delete, otherwise -1.
430 :rtype: int
431 """
432 result = -1
433 if not name == None:
434 if not self.doesCommandExist(deviceId, name):
435 return 0
436 cursor = self._database.cursor()
437 deleteCommand = "DELETE FROM Command WHERE device_id=? AND name=?"
438 cursor.execute(deleteCommand, (deviceId, name))
439 self._database.commit()
440 cursor.close()
441 return 1
442 else:
443 selectOperation = "SELECT count(*) FROM Command WHERE deviceId=?"
444 cursor = self._database.cursor()
445 cursor.execute(selectOperation, (deviceId,))
446 (count,) = cursor.fetchone()
447 if not count > 0:
448 return 0
449 deleteCommand = "DELETE FROM Command WHERE deviceId=?"
450 cursor.execute(deleteCommand, (deviceId))
451 self._database.commit()
452 cursor.close()
453 return 1
454
455 return result
456
457 def getCommandsOfDevice(self, deviceId):
458 """
459 get all the commands of a specified device
460 :param int deviceId: device id of the command
461 :return command name list if any commands exist, otherwise None
462
463 """
464 operation = "SELECT name FROM Command WHERE device_id = ?"
465 #operation2 = "SELECT count(*) FROM Command WHERE device_id = ? "
466 cursor = self._database.cursor()
467 #cursor.execute(operation2,(deviceId,))
468 #(count,) = cursor.fetchone
469
470 #if not count > 0:
471 #return None
472 cursor.execute(operation, (deviceId,))
473 result = cursor.fetchall()
474 print result
475 commandList = []
476 if result == None:
477 return commandList
478 else:
479 for row in result:
480 commandList.append(row[0])
481
482 return commandList
483
484 def getCommandToken(self, deviceId, commandName):
485 """
486 get command token of a specified command
487 :param int deviceId: device id of the command
488 :param str commandName: device name of the command
489 :return command token if command existsm, otherwise None
490 :rtype HMACKey
491 """
492 operation = "SELECT command_token_sequence, command_token_counter,command_token, command_token_name FROM Command WHERE device_id = ? AND name = ?"
493 cursor = self._database.cursor()
494 cursor.execute(operation, (deviceId, commandName))
495 result = cursor.fetchone()
496 if result == None:
497 return None
498 else:
499 commandToken = HMACKey(result[0], result[1], result[2], result[3])
500 return commandToken
501
502 def doesServiceProfileExist(self, deviceId, serviceProfileName):
503 """
504 check if the specified service profile already exists.
505
506 :param Integer device_id: the device id
507 :param str serviceProfileName: name of the service profile
508 :return True if the service profile exists, otherwise False
509 :rtype: bool
510 """
511 result = False
512
513 cursor = self._database.cursor()
514 cursor.execute("SELECT count(*) FROM ServiceProfile WHERE device_id =? AND name = ?", (deviceId, serviceProfileName))
515 (count,) = cursor.fetchone()
516 if count > 0:
517 result = True
518
519 cursor.close()
520 return result
521
522 def addServiceProfile(self, deviceId, name):
523 """
524 Add a new command to the ServiceProfile table, do nothing if the device already exists
525
526 :param int deviceId: the device id to which the command belongs to
527 :param str name: the service profile name
528 :return the service profile id if it's added successfully, 0 if the service profile already exists, otherwise -1
529 :rtype: int
530 """
531 result = -1
532 data = (deviceId,
533 name,
534 )
535
536 #check if the service profile already exists, if yes return 0
537 if self.doesServiceProfileExist(deviceId, name):
538 return 0
539
540 insertCommand = (
541 "INSERT INTO ServiceProfile(device_id, name)"
542 "VALUES(?,?)"
543 )
544 cursor = self._database.cursor()
545 cursor.execute(insertCommand, data)
546 self._database.commit()
547 result = cursor.lastrowid
548 cursor.close()
549 return result
550
551 def deleteServiceProfile(self, deviceId, name = None):
552 """
553 delete specified service profile.
554 :param str name: The command name, if None, delete all profiless of the device
555 :param int deviceId: device id
556 :return: 1 if successful, 0 if no service profile to delete, otherwise -1.
557 :rtype: int
558 """
559 result = -1
560 if not name == None:
561 if not self.doesServiceProfileExist(deviceId, name):
562 return 0
563 cursor = self._database.cursor()
564 deleteProfile = "DELETE FROM ServiceProfile WHERE device_id=? AND name=?"
565 cursor.execute(deleteProfile, (deviceId, name))
566 self._database.commit()
567 cursor.close()
568 return 1
569 else:
570 selectOperation = "SELECT count(*) FROM ServiceProfile WHERE deviceId=?"
571 cursor = self._database.cursor()
572 cursor.execute(selectOperation, (deviceId,))
573 (count,) = cursor.fetchone()
574 if not count > 0:
575 return 0
576 deleteProfile = "DELETE FROM ServiceProfile WHERE deviceId=?"
577 cursor.execute(deleteProfile, (deviceId))
578 self._database.commit()
579 cursor.close()
580 return 1
581
582 return result
583
584 def getServiceProfilesOfDevice(self, deviceId):
585 """
586 get all the service profiles of a specified device
587 :param int deviceId: device id of the command
588 :return service profiles name list if any service profiles exist, otherwise None
589 """
590 operation = "SELECT name FROM ServiceProfile WHERE device_id = ?"
591 cursor = self._database.cursor()
592 cursor.execute(operation, (deviceId,))
593 result = cursor.fetchall()
594 #print result
595 serviceProfileList = []
596 if not result == None:
597 for row in result:
598 serviceProfileList.append(row[0])
599 return serviceProfileList
600
601