VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/testmanager/core/useraccount.py@ 65226

Last change on this file since 65226 was 65226, checked in by vboxsync, 8 years ago

TestManager: Hacked up some basic testbox sorting during the weekly meeting.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.4 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: useraccount.py 65226 2017-01-10 15:36:36Z vboxsync $
3
4"""
5Test Manager - User DB records management.
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2012-2016 Oracle Corporation
11
12This file is part of VirtualBox Open Source Edition (OSE), as
13available from http://www.virtualbox.org. This file is free software;
14you can redistribute it and/or modify it under the terms of the GNU
15General Public License (GPL) as published by the Free Software
16Foundation, in version 2 as it comes in the "COPYING" file of the
17VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19
20The contents of this file may alternatively be used under the terms
21of the Common Development and Distribution License Version 1.0
22(CDDL) only, as it comes in the "COPYING.CDDL" file of the
23VirtualBox OSE distribution, in which case the provisions of the
24CDDL are applicable instead of those of the GPL.
25
26You may elect to license modified versions of this file under the
27terms and conditions of either the GPL or the CDDL or both.
28"""
29__version__ = "$Revision: 65226 $"
30
31
32# Standard python imports.
33import unittest;
34
35# Validation Kit imports.
36from testmanager import config;
37from testmanager.core.base import ModelDataBase, ModelLogicBase, ModelDataBaseTestCase, TMTooManyRows, TMRowNotFound;
38
39
40class UserAccountData(ModelDataBase):
41 """
42 User account data
43 """
44
45 ksIdAttr = 'uid';
46
47 ksParam_uid = 'UserAccount_uid'
48 ksParam_tsExpire = 'UserAccount_tsExpire'
49 ksParam_tsEffective = 'UserAccount_tsEffective'
50 ksParam_uidAuthor = 'UserAccount_uidAuthor'
51 ksParam_sLoginName = 'UserAccount_sLoginName'
52 ksParam_sUsername = 'UserAccount_sUsername'
53 ksParam_sEmail = 'UserAccount_sEmail'
54 ksParam_sFullName = 'UserAccount_sFullName'
55
56 kasAllowNullAttributes = ['uid', 'tsEffective', 'tsExpire', 'uidAuthor'];
57
58
59 def __init__(self):
60 """Init parameters"""
61 ModelDataBase.__init__(self);
62 self.uid = None;
63 self.tsEffective = None;
64 self.tsExpire = None;
65 self.uidAuthor = None;
66 self.sUsername = None;
67 self.sEmail = None;
68 self.sFullName = None;
69 self.sLoginName = None;
70
71 def initFromDbRow(self, aoRow):
72 """
73 Init from database table row
74 Returns self. Raises exception of the row is None.
75 """
76 if aoRow is None:
77 raise TMRowNotFound('User not found.');
78
79 self.uid = aoRow[0];
80 self.tsEffective = aoRow[1];
81 self.tsExpire = aoRow[2];
82 self.uidAuthor = aoRow[3];
83 self.sUsername = aoRow[4];
84 self.sEmail = aoRow[5];
85 self.sFullName = aoRow[6];
86 self.sLoginName = aoRow[7];
87 return self;
88
89 def initFromDbWithId(self, oDb, uid, tsNow = None, sPeriodBack = None):
90 """
91 Initialize the object from the database.
92 """
93 oDb.execute(self.formatSimpleNowAndPeriodQuery(oDb,
94 'SELECT *\n'
95 'FROM Users\n'
96 'WHERE uid = %s\n'
97 , ( uid, ), tsNow, sPeriodBack));
98 aoRow = oDb.fetchOne()
99 if aoRow is None:
100 raise TMRowNotFound('uid=%s not found (tsNow=%s sPeriodBack=%s)' % (uid, tsNow, sPeriodBack,));
101 return self.initFromDbRow(aoRow);
102
103 def _validateAndConvertAttribute(self, sAttr, sParam, oValue, aoNilValues, fAllowNull, oDb):
104 # Custom handling of the email field.
105 if sAttr == 'sEmail':
106 return ModelDataBase.validateEmail(oValue, aoNilValues = aoNilValues, fAllowNull = fAllowNull);
107
108 # Automatically lowercase the login name if we're supposed to do case
109 # insensitive matching. (The feature assumes lower case in DB.)
110 if sAttr == 'sLoginName' and oValue is not None and config.g_kfLoginNameCaseInsensitive:
111 oValue = oValue.lower();
112
113 return ModelDataBase._validateAndConvertAttribute(self, sAttr, sParam, oValue, aoNilValues, fAllowNull, oDb);
114
115
116class UserAccountLogic(ModelLogicBase):
117 """
118 User account logic (for the Users table).
119 """
120
121 def __init__(self, oDb):
122 ModelLogicBase.__init__(self, oDb)
123 self.dCache = None;
124
125 def fetchForListing(self, iStart, cMaxRows, tsNow, aiSortColumns = None):
126 """
127 Fetches user accounts.
128
129 Returns an array (list) of UserAccountData items, empty list if none.
130 Raises exception on error.
131 """
132 _ = aiSortColumns;
133 if tsNow is None:
134 self._oDb.execute('SELECT *\n'
135 'FROM Users\n'
136 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
137 'ORDER BY sUsername DESC\n'
138 'LIMIT %s OFFSET %s\n'
139 , (cMaxRows, iStart,));
140 else:
141 self._oDb.execute('SELECT *\n'
142 'FROM Users\n'
143 'WHERE tsExpire > %s\n'
144 ' AND tsEffective <= %s\n'
145 'ORDER BY sUsername DESC\n'
146 'LIMIT %s OFFSET %s\n'
147 , (tsNow, tsNow, cMaxRows, iStart,));
148
149 aoRows = [];
150 for _ in range(self._oDb.getRowCount()):
151 aoRows.append(UserAccountData().initFromDbRow(self._oDb.fetchOne()));
152 return aoRows;
153
154 def addEntry(self, oData, uidAuthor, fCommit = False):
155 """
156 Add user account entry to the DB.
157 """
158 self._oDb.callProc('UserAccountLogic_addEntry',
159 (uidAuthor, oData.sUsername, oData.sEmail, oData.sFullName, oData.sLoginName,));
160 self._oDb.maybeCommit(fCommit);
161 return True;
162
163 def editEntry(self, oData, uidAuthor, fCommit = False):
164 """
165 Modify user account.
166 """
167 self._oDb.callProc('UserAccountLogic_editEntry',
168 (uidAuthor, oData.uid, oData.sUsername, oData.sEmail, oData.sFullName, oData.sLoginName,));
169 self._oDb.maybeCommit(fCommit);
170 return True;
171
172 def removeEntry(self, uidAuthor, uid, fCascade = False, fCommit = False):
173 """
174 Delete user account
175 """
176 self._oDb.callProc('UserAccountLogic_delEntry', (uidAuthor, uid));
177 self._oDb.maybeCommit(fCommit);
178 _ = fCascade;
179 return True;
180
181 def _getByField(self, sField, sValue):
182 """
183 Get user account record by its field value
184 """
185 self._oDb.execute('SELECT *\n'
186 'FROM Users\n'
187 'WHERE tsExpire = \'infinity\'::TIMESTAMP\n'
188 ' AND ' + sField + ' = %s'
189 , (sValue,))
190
191 aRows = self._oDb.fetchAll()
192 if len(aRows) not in (0, 1):
193 raise TMTooManyRows('Found more than one user account with the same credentials. Database structure is corrupted.')
194
195 try:
196 return aRows[0]
197 except IndexError:
198 return []
199
200 def getById(self, idUserId):
201 """
202 Get user account information by ID.
203 """
204 return self._getByField('uid', idUserId)
205
206 def tryFetchAccountByLoginName(self, sLoginName):
207 """
208 Try get user account information by login name.
209
210 Returns UserAccountData if found, None if not.
211 Raises exception on DB error.
212 """
213 if config.g_kfLoginNameCaseInsensitive:
214 sLoginName = sLoginName.lower();
215
216 self._oDb.execute('SELECT *\n'
217 'FROM Users\n'
218 'WHERE sLoginName = %s\n'
219 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
220 , (sLoginName, ));
221 if self._oDb.getRowCount() != 1:
222 if self._oDb.getRowCount() != 0:
223 raise self._oDb.integrityException('%u rows in Users with sLoginName="%s"'
224 % (self._oDb.getRowCount(), sLoginName));
225 return None;
226 return UserAccountData().initFromDbRow(self._oDb.fetchOne());
227
228 def cachedLookup(self, uid):
229 """
230 Looks up the current UserAccountData object for uid via an object cache.
231
232 Returns a shared UserAccountData object. None if not found.
233 Raises exception on DB error.
234 """
235 if self.dCache is None:
236 self.dCache = self._oDb.getCache('UserAccount');
237
238 oUser = self.dCache.get(uid, None);
239 if oUser is None:
240 self._oDb.execute('SELECT *\n'
241 'FROM Users\n'
242 'WHERE uid = %s\n'
243 ' AND tsExpire = \'infinity\'::TIMESTAMP\n'
244 , (uid, ));
245 if self._oDb.getRowCount() == 0:
246 # Maybe it was deleted, try get the last entry.
247 self._oDb.execute('SELECT *\n'
248 'FROM Users\n'
249 'WHERE uid = %s\n'
250 'ORDER BY tsExpire DESC\n'
251 'LIMIT 1\n'
252 , (uid, ));
253 elif self._oDb.getRowCount() > 1:
254 raise self._oDb.integrityException('%s infinity rows for %s' % (self._oDb.getRowCount(), uid));
255
256 if self._oDb.getRowCount() == 1:
257 oUser = UserAccountData().initFromDbRow(self._oDb.fetchOne());
258 self.dCache[uid] = oUser;
259 return oUser;
260
261 def resolveChangeLogAuthors(self, aoEntries):
262 """
263 Given an array of ChangeLogEntry instances, set sAuthor to whatever
264 uidAuthor resolves to.
265
266 Returns aoEntries.
267 Raises exception on DB error.
268 """
269 for oEntry in aoEntries:
270 oUser = self.cachedLookup(oEntry.uidAuthor)
271 if oUser is not None:
272 oEntry.sAuthor = oUser.sUsername;
273 return aoEntries;
274
275
276#
277# Unit testing.
278#
279
280# pylint: disable=C0111
281class UserAccountDataTestCase(ModelDataBaseTestCase):
282 def setUp(self):
283 self.aoSamples = [UserAccountData(),];
284
285if __name__ == '__main__':
286 unittest.main();
287 # not reached.
288
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette