##// END OF EJS Templates
Fixed Windows installation based on work of Mantis406 fork: "Replace py-bcrypt to make Windows installation easier"...
marcink -
r1118:b0e2c949 beta
parent child Browse files
Show More
@@ -1,52 +1,53 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.__init__
4 4 ~~~~~~~~~~~~~~~~~~
5 5
6 6 RhodeCode, a web based repository management based on pylons
7 7 versioning implementation: http://semver.org/
8 8
9 9 :created_on: Apr 9, 2010
10 10 :author: marcink
11 11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software; you can redistribute it and/or
15 15 # modify it under the terms of the GNU General Public License
16 16 # as published by the Free Software Foundation; version 2
17 17 # of the License or (at your opinion) any later version of the license.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program; if not, write to the Free Software
26 26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 27 # MA 02110-1301, USA.
28
28 import platform
29 29
30 30 VERSION = (1, 2, 0, 'beta')
31 31 __version__ = '.'.join((str(each) for each in VERSION[:4]))
32 32 __dbversion__ = 3 #defines current db version for migrations
33 __platform__ = platform.system()
33 34
34 35 try:
35 36 from rhodecode.lib.utils import get_current_revision
36 37 _rev = get_current_revision()
37 38 except ImportError:
38 39 #this is needed when doing some setup.py operations
39 40 _rev = False
40 41
41 42 if len(VERSION) > 3 and _rev:
42 43 __version__ += ' [rev:%s]' % _rev[0]
43 44
44 45 def get_version():
45 46 """Returns shorter version (digit parts only) as string."""
46 47
47 48 return '.'.join((str(each) for each in VERSION[:3]))
48 49
49 50 BACKENDS = {
50 51 'hg': 'Mercurial repository',
51 #'git': 'Git repository',
52 #'git': 'Git repository',
52 53 }
@@ -1,550 +1,591 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.auth
4 4 ~~~~~~~~~~~~~~~~~~
5 5
6 6 authentication and permission libraries
7 7
8 8 :created_on: Apr 4, 2010
9 9 :copyright: (c) 2010 by marcink.
10 10 :license: LICENSE_NAME, see LICENSE_FILE for more details.
11 11 """
12 12 # This program is free software; you can redistribute it and/or
13 13 # modify it under the terms of the GNU General Public License
14 14 # as published by the Free Software Foundation; version 2
15 15 # of the License or (at your opinion) any later version of the license.
16 16 #
17 17 # This program is distributed in the hope that it will be useful,
18 18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 20 # GNU General Public License for more details.
21 21 #
22 22 # You should have received a copy of the GNU General Public License
23 23 # along with this program; if not, write to the Free Software
24 24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 25 # MA 02110-1301, USA.
26 26
27 import bcrypt
28 27 import random
29 28 import logging
30 29 import traceback
31 30 import hashlib
31
32 32 from tempfile import _RandomNameSequence
33 33 from decorator import decorator
34 34
35 35 from pylons import config, session, url, request
36 36 from pylons.controllers.util import abort, redirect
37 37 from pylons.i18n.translation import _
38 38
39 from rhodecode import __platform__
40
41 if __platform__ == 'Windows':
42 from hashlib import sha256
43 if __platform__ in ('Linux', 'Darwin'):
44 import bcrypt
45
46
39 47 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
40 48 from rhodecode.lib.utils import get_repo_slug
41 49 from rhodecode.lib.auth_ldap import AuthLdap
42 50
43 51 from rhodecode.model import meta
44 52 from rhodecode.model.user import UserModel
45 53 from rhodecode.model.db import Permission
46 54
47 55
48 56 log = logging.getLogger(__name__)
49 57
50 58 class PasswordGenerator(object):
51 59 """This is a simple class for generating password from
52 60 different sets of characters
53 61 usage:
54 62 passwd_gen = PasswordGenerator()
55 63 #print 8-letter password containing only big and small letters of alphabet
56 64 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
57 65 """
58 66 ALPHABETS_NUM = r'''1234567890'''#[0]
59 67 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
60 68 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
61 69 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
62 70 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
63 71 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
64 72 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
65 73 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
66 74 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
67 75
68 76 def __init__(self, passwd=''):
69 77 self.passwd = passwd
70 78
71 79 def gen_password(self, len, type):
72 80 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
73 81 return self.passwd
74 82
83 class RhodeCodeCrypto(object):
84
85 @classmethod
86 def hash_string(cls, str_):
87 """
88 Cryptographic function used for password hashing based on pybcrypt
89 or pycrypto in windows
90
91 :param password: password to hash
92 """
93 if __platform__ == 'Windows':
94 return sha256(str_).hexdigest()
95 elif __platform__ in ('Linux', 'Darwin'):
96 return bcrypt.hashpw(str_, bcrypt.gensalt(10))
97 else:
98 raise Exception('Unknown or unsupoprted platform %s' % __platform__)
99
100 @classmethod
101 def hash_check(cls, password, hashed):
102 """
103 Checks matching password with it's hashed value, runs different
104 implementation based on platform it runs on
105
106 :param password: password
107 :param hashed: password in hashed form
108 """
109
110 if __platform__ == 'Windows':
111 return sha256(password).hexdigest() == hashed
112 elif __platform__ in ('Linux', 'Darwin'):
113 return bcrypt.hashpw(password, hashed) == hashed
114 else:
115 raise Exception('Unknown or unsupoprted platform %s' % __platform__)
116
117
118
119
75 120
76 121 def get_crypt_password(password):
77 """Cryptographic function used for password hashing based on pybcrypt
78
79 :param password: password to hash
80 """
81 return bcrypt.hashpw(password, bcrypt.gensalt(10))
122 return RhodeCodeCrypto.hash_string(password)
123
124 def check_password(password, hashed):
125 return RhodeCodeCrypto.hash_check(password, hashed)
82 126
83 127 def generate_api_key(username, salt=None):
84 128 if salt is None:
85 129 salt = _RandomNameSequence().next()
86 130
87 131 return hashlib.sha1(username + salt).hexdigest()
88 132
89 def check_password(password, hashed):
90 return bcrypt.hashpw(password, hashed) == hashed
91
92 133 def authfunc(environ, username, password):
93 134 """Dummy authentication function used in Mercurial/Git/ and access control,
94 135
95 136 :param environ: needed only for using in Basic auth
96 137 """
97 138 return authenticate(username, password)
98 139
99 140
100 141 def authenticate(username, password):
101 142 """Authentication function used for access control,
102 143 firstly checks for db authentication then if ldap is enabled for ldap
103 144 authentication, also creates ldap user if not in database
104 145
105 146 :param username: username
106 147 :param password: password
107 148 """
108 149 user_model = UserModel()
109 150 user = user_model.get_by_username(username, cache=False)
110 151
111 152 log.debug('Authenticating user using RhodeCode account')
112 153 if user is not None and not user.ldap_dn:
113 154 if user.active:
114 155
115 156 if user.username == 'default' and user.active:
116 157 log.info('user %s authenticated correctly as anonymous user',
117 158 username)
118 159 return True
119 160
120 161 elif user.username == username and check_password(password, user.password):
121 162 log.info('user %s authenticated correctly', username)
122 163 return True
123 164 else:
124 165 log.warning('user %s is disabled', username)
125 166
126 167 else:
127 168 log.debug('Regular authentication failed')
128 169 user_obj = user_model.get_by_username(username, cache=False,
129 170 case_insensitive=True)
130 171
131 172 if user_obj is not None and not user_obj.ldap_dn:
132 173 log.debug('this user already exists as non ldap')
133 174 return False
134 175
135 176 from rhodecode.model.settings import SettingsModel
136 177 ldap_settings = SettingsModel().get_ldap_settings()
137 178
138 179 #======================================================================
139 180 # FALLBACK TO LDAP AUTH IF ENABLE
140 181 #======================================================================
141 182 if ldap_settings.get('ldap_active', False):
142 183 log.debug("Authenticating user using ldap")
143 184 kwargs = {
144 185 'server':ldap_settings.get('ldap_host', ''),
145 186 'base_dn':ldap_settings.get('ldap_base_dn', ''),
146 187 'port':ldap_settings.get('ldap_port'),
147 188 'bind_dn':ldap_settings.get('ldap_dn_user'),
148 189 'bind_pass':ldap_settings.get('ldap_dn_pass'),
149 190 'use_ldaps':ldap_settings.get('ldap_ldaps'),
150 191 'tls_reqcert':ldap_settings.get('ldap_tls_reqcert'),
151 192 'ldap_filter':ldap_settings.get('ldap_filter'),
152 193 'search_scope':ldap_settings.get('ldap_search_scope'),
153 194 'attr_login':ldap_settings.get('ldap_attr_login'),
154 195 'ldap_version':3,
155 196 }
156 197 log.debug('Checking for ldap authentication')
157 198 try:
158 199 aldap = AuthLdap(**kwargs)
159 200 (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password)
160 201 log.debug('Got ldap DN response %s', user_dn)
161 202
162 203 user_attrs = {
163 204 'name' : ldap_attrs[ldap_settings.get('ldap_attr_firstname')][0],
164 205 'lastname' : ldap_attrs[ldap_settings.get('ldap_attr_lastname')][0],
165 206 'email' : ldap_attrs[ldap_settings.get('ldap_attr_email')][0],
166 207 }
167 208
168 209 if user_model.create_ldap(username, password, user_dn, user_attrs):
169 210 log.info('created new ldap user %s', username)
170 211
171 212 return True
172 213 except (LdapUsernameError, LdapPasswordError,):
173 214 pass
174 215 except (Exception,):
175 216 log.error(traceback.format_exc())
176 217 pass
177 218 return False
178 219
179 220 class AuthUser(object):
180 221 """
181 222 A simple object that handles all attributes of user in RhodeCode
182 223
183 224 It does lookup based on API key,given user, or user present in session
184 225 Then it fills all required information for such user. It also checks if
185 226 anonymous access is enabled and if so, it returns default user as logged
186 227 in
187 228 """
188 229
189 230 def __init__(self, user_id=None, api_key=None):
190 231
191 232 self.user_id = user_id
192 233 self.api_key = api_key
193 234
194 235 self.username = 'None'
195 236 self.name = ''
196 237 self.lastname = ''
197 238 self.email = ''
198 239 self.is_authenticated = False
199 240 self.admin = False
200 241 self.permissions = {}
201 242 self.propagate_data()
202 243
203 244
204 245 def propagate_data(self):
205 246 user_model = UserModel()
206 247 if self.api_key:
207 248 #try go get user by api key
208 249 log.debug('Auth User lookup by API KEY %s', self.api_key)
209 250 user_model.fill_data(self, api_key=self.api_key)
210 251 else:
211 252 log.debug('Auth User lookup by USER ID %s', self.user_id)
212 253 self.anonymous_user = user_model.get_by_username('default', cache=True)
213 254
214 255 if self.user_id is not None and self.user_id != self.anonymous_user.user_id:
215 256 user_model.fill_data(self, user_id=self.user_id)
216 257 else:
217 258 if self.anonymous_user.active is True:
218 259 user_model.fill_data(self, user_id=self.anonymous_user.user_id)
219 260 #then we set this user is logged in
220 261 self.is_authenticated = True
221 262 else:
222 263 self.is_authenticated = False
223 264
224 265 log.debug('Auth User is now %s', self)
225 266 user_model.fill_perms(self)
226 267
227 268 @property
228 269 def is_admin(self):
229 270 return self.admin
230 271
231 272 def __repr__(self):
232 273 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
233 274 self.is_authenticated)
234 275
235 276 def set_authenticated(self, authenticated=True):
236 277
237 278 if self.user_id != self.anonymous_user.user_id:
238 279 self.is_authenticated = authenticated
239 280
240 281
241 282 def set_available_permissions(config):
242 283 """This function will propagate pylons globals with all available defined
243 284 permission given in db. We don't want to check each time from db for new
244 285 permissions since adding a new permission also requires application restart
245 286 ie. to decorate new views with the newly created permission
246 287
247 288 :param config: current pylons config instance
248 289
249 290 """
250 291 log.info('getting information about all available permissions')
251 292 try:
252 293 sa = meta.Session()
253 294 all_perms = sa.query(Permission).all()
254 295 except:
255 296 pass
256 297 finally:
257 298 meta.Session.remove()
258 299
259 300 config['available_permissions'] = [x.permission_name for x in all_perms]
260 301
261 302 #===============================================================================
262 303 # CHECK DECORATORS
263 304 #===============================================================================
264 305 class LoginRequired(object):
265 306 """
266 307 Must be logged in to execute this function else
267 308 redirect to login page
268 309
269 310 :param api_access: if enabled this checks only for valid auth token
270 311 and grants access based on valid token
271 312 """
272 313
273 314 def __init__(self, api_access=False):
274 315 self.api_access = api_access
275 316
276 317 def __call__(self, func):
277 318 return decorator(self.__wrapper, func)
278 319
279 320 def __wrapper(self, func, *fargs, **fkwargs):
280 321 cls = fargs[0]
281 322 user = cls.rhodecode_user
282 323
283 324 api_access_ok = False
284 325 if self.api_access:
285 326 log.debug('Checking API KEY access for %s', cls)
286 327 if user.api_key == request.GET.get('api_key'):
287 328 api_access_ok = True
288 329 else:
289 330 log.debug("API KEY token not valid")
290 331
291 332 log.debug('Checking if %s is authenticated @ %s', user.username, cls)
292 333 if user.is_authenticated or api_access_ok:
293 334 log.debug('user %s is authenticated', user.username)
294 335 return func(*fargs, **fkwargs)
295 336 else:
296 337 log.warn('user %s NOT authenticated', user.username)
297 338
298 339 p = ''
299 340 if request.environ.get('SCRIPT_NAME') != '/':
300 341 p += request.environ.get('SCRIPT_NAME')
301 342
302 343 p += request.environ.get('PATH_INFO')
303 344 if request.environ.get('QUERY_STRING'):
304 345 p += '?' + request.environ.get('QUERY_STRING')
305 346
306 347 log.debug('redirecting to login page with %s', p)
307 348 return redirect(url('login_home', came_from=p))
308 349
309 350 class NotAnonymous(object):
310 351 """Must be logged in to execute this function else
311 352 redirect to login page"""
312 353
313 354 def __call__(self, func):
314 355 return decorator(self.__wrapper, func)
315 356
316 357 def __wrapper(self, func, *fargs, **fkwargs):
317 358 cls = fargs[0]
318 359 self.user = cls.rhodecode_user
319 360
320 361 log.debug('Checking if user is not anonymous @%s', cls)
321 362
322 363 anonymous = self.user.username == 'default'
323 364
324 365 if anonymous:
325 366 p = ''
326 367 if request.environ.get('SCRIPT_NAME') != '/':
327 368 p += request.environ.get('SCRIPT_NAME')
328 369
329 370 p += request.environ.get('PATH_INFO')
330 371 if request.environ.get('QUERY_STRING'):
331 372 p += '?' + request.environ.get('QUERY_STRING')
332 373
333 374 import rhodecode.lib.helpers as h
334 375 h.flash(_('You need to be a registered user to perform this action'),
335 376 category='warning')
336 377 return redirect(url('login_home', came_from=p))
337 378 else:
338 379 return func(*fargs, **fkwargs)
339 380
340 381 class PermsDecorator(object):
341 382 """Base class for controller decorators"""
342 383
343 384 def __init__(self, *required_perms):
344 385 available_perms = config['available_permissions']
345 386 for perm in required_perms:
346 387 if perm not in available_perms:
347 388 raise Exception("'%s' permission is not defined" % perm)
348 389 self.required_perms = set(required_perms)
349 390 self.user_perms = None
350 391
351 392 def __call__(self, func):
352 393 return decorator(self.__wrapper, func)
353 394
354 395
355 396 def __wrapper(self, func, *fargs, **fkwargs):
356 397 cls = fargs[0]
357 398 self.user = cls.rhodecode_user
358 399 self.user_perms = self.user.permissions
359 400 log.debug('checking %s permissions %s for %s %s',
360 401 self.__class__.__name__, self.required_perms, cls,
361 402 self.user)
362 403
363 404 if self.check_permissions():
364 405 log.debug('Permission granted for %s %s', cls, self.user)
365 406 return func(*fargs, **fkwargs)
366 407
367 408 else:
368 409 log.warning('Permission denied for %s %s', cls, self.user)
369 410 #redirect with forbidden ret code
370 411 return abort(403)
371 412
372 413
373 414
374 415 def check_permissions(self):
375 416 """Dummy function for overriding"""
376 417 raise Exception('You have to write this function in child class')
377 418
378 419 class HasPermissionAllDecorator(PermsDecorator):
379 420 """Checks for access permission for all given predicates. All of them
380 421 have to be meet in order to fulfill the request
381 422 """
382 423
383 424 def check_permissions(self):
384 425 if self.required_perms.issubset(self.user_perms.get('global')):
385 426 return True
386 427 return False
387 428
388 429
389 430 class HasPermissionAnyDecorator(PermsDecorator):
390 431 """Checks for access permission for any of given predicates. In order to
391 432 fulfill the request any of predicates must be meet
392 433 """
393 434
394 435 def check_permissions(self):
395 436 if self.required_perms.intersection(self.user_perms.get('global')):
396 437 return True
397 438 return False
398 439
399 440 class HasRepoPermissionAllDecorator(PermsDecorator):
400 441 """Checks for access permission for all given predicates for specific
401 442 repository. All of them have to be meet in order to fulfill the request
402 443 """
403 444
404 445 def check_permissions(self):
405 446 repo_name = get_repo_slug(request)
406 447 try:
407 448 user_perms = set([self.user_perms['repositories'][repo_name]])
408 449 except KeyError:
409 450 return False
410 451 if self.required_perms.issubset(user_perms):
411 452 return True
412 453 return False
413 454
414 455
415 456 class HasRepoPermissionAnyDecorator(PermsDecorator):
416 457 """Checks for access permission for any of given predicates for specific
417 458 repository. In order to fulfill the request any of predicates must be meet
418 459 """
419 460
420 461 def check_permissions(self):
421 462 repo_name = get_repo_slug(request)
422 463
423 464 try:
424 465 user_perms = set([self.user_perms['repositories'][repo_name]])
425 466 except KeyError:
426 467 return False
427 468 if self.required_perms.intersection(user_perms):
428 469 return True
429 470 return False
430 471 #===============================================================================
431 472 # CHECK FUNCTIONS
432 473 #===============================================================================
433 474
434 475 class PermsFunction(object):
435 476 """Base function for other check functions"""
436 477
437 478 def __init__(self, *perms):
438 479 available_perms = config['available_permissions']
439 480
440 481 for perm in perms:
441 482 if perm not in available_perms:
442 483 raise Exception("'%s' permission in not defined" % perm)
443 484 self.required_perms = set(perms)
444 485 self.user_perms = None
445 486 self.granted_for = ''
446 487 self.repo_name = None
447 488
448 489 def __call__(self, check_Location=''):
449 490 user = session.get('rhodecode_user', False)
450 491 if not user:
451 492 return False
452 493 self.user_perms = user.permissions
453 494 self.granted_for = user
454 495 log.debug('checking %s %s %s', self.__class__.__name__,
455 496 self.required_perms, user)
456 497
457 498 if self.check_permissions():
458 499 log.debug('Permission granted %s @ %s', self.granted_for,
459 500 check_Location or 'unspecified location')
460 501 return True
461 502
462 503 else:
463 504 log.warning('Permission denied for %s @ %s', self.granted_for,
464 505 check_Location or 'unspecified location')
465 506 return False
466 507
467 508 def check_permissions(self):
468 509 """Dummy function for overriding"""
469 510 raise Exception('You have to write this function in child class')
470 511
471 512 class HasPermissionAll(PermsFunction):
472 513 def check_permissions(self):
473 514 if self.required_perms.issubset(self.user_perms.get('global')):
474 515 return True
475 516 return False
476 517
477 518 class HasPermissionAny(PermsFunction):
478 519 def check_permissions(self):
479 520 if self.required_perms.intersection(self.user_perms.get('global')):
480 521 return True
481 522 return False
482 523
483 524 class HasRepoPermissionAll(PermsFunction):
484 525
485 526 def __call__(self, repo_name=None, check_Location=''):
486 527 self.repo_name = repo_name
487 528 return super(HasRepoPermissionAll, self).__call__(check_Location)
488 529
489 530 def check_permissions(self):
490 531 if not self.repo_name:
491 532 self.repo_name = get_repo_slug(request)
492 533
493 534 try:
494 535 self.user_perms = set([self.user_perms['repositories']\
495 536 [self.repo_name]])
496 537 except KeyError:
497 538 return False
498 539 self.granted_for = self.repo_name
499 540 if self.required_perms.issubset(self.user_perms):
500 541 return True
501 542 return False
502 543
503 544 class HasRepoPermissionAny(PermsFunction):
504 545
505 546 def __call__(self, repo_name=None, check_Location=''):
506 547 self.repo_name = repo_name
507 548 return super(HasRepoPermissionAny, self).__call__(check_Location)
508 549
509 550 def check_permissions(self):
510 551 if not self.repo_name:
511 552 self.repo_name = get_repo_slug(request)
512 553
513 554 try:
514 555 self.user_perms = set([self.user_perms['repositories']\
515 556 [self.repo_name]])
516 557 except KeyError:
517 558 return False
518 559 self.granted_for = self.repo_name
519 560 if self.required_perms.intersection(self.user_perms):
520 561 return True
521 562 return False
522 563
523 564 #===============================================================================
524 565 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
525 566 #===============================================================================
526 567
527 568 class HasPermissionAnyMiddleware(object):
528 569 def __init__(self, *perms):
529 570 self.required_perms = set(perms)
530 571
531 572 def __call__(self, user, repo_name):
532 573 usr = AuthUser(user.user_id)
533 574 try:
534 575 self.user_perms = set([usr.permissions['repositories'][repo_name]])
535 576 except:
536 577 self.user_perms = set()
537 578 self.granted_for = ''
538 579 self.username = user.username
539 580 self.repo_name = repo_name
540 581 return self.check_permissions()
541 582
542 583 def check_permissions(self):
543 584 log.debug('checking mercurial protocol '
544 585 'permissions %s for user:%s repository:%s', self.user_perms,
545 586 self.username, self.repo_name)
546 587 if self.required_perms.intersection(self.user_perms):
547 588 log.debug('permission granted')
548 589 return True
549 590 log.debug('permission denied')
550 591 return False
@@ -1,108 +1,112 b''
1 1 import sys
2 2 from rhodecode import get_version
3 from rhodecode import __platform__
3 4
4 5 py_version = sys.version_info
5 6
6 7 requirements = [
7 8 "Pylons==1.0.0",
8 9 "WebHelpers>=1.2",
9 10 "SQLAlchemy>=0.6.6",
10 11 "Mako>=0.4.0",
11 12 "vcs>=0.2.0",
12 13 "pygments>=1.4",
13 14 "mercurial>=1.7.5",
14 15 "whoosh>=1.3.4",
15 16 "celery>=2.2.4",
16 "py-bcrypt",
17 17 "babel",
18 18 ]
19 19
20 20 classifiers = ['Development Status :: 4 - Beta',
21 21 'Environment :: Web Environment',
22 22 'Framework :: Pylons',
23 23 'Intended Audience :: Developers',
24 24 'License :: OSI Approved :: BSD License',
25 25 'Operating System :: OS Independent',
26 26 'Programming Language :: Python', ]
27 27
28 28 if py_version < (2, 6):
29 29 requirements.append("simplejson")
30 30 requirements.append("pysqlite")
31 31
32 if __platform__ in ('Linux', 'Darwin'):
33 requirements.append("py-bcrypt")
34
35
32 36 #additional files from project that goes somewhere in the filesystem
33 37 #relative to sys.prefix
34 38 data_files = []
35 39
36 40 #additional files that goes into package itself
37 41 package_data = {'rhodecode': ['i18n/*/LC_MESSAGES/*.mo', ], }
38 42
39 43 description = ('Mercurial repository browser/management with '
40 44 'build in push/pull server and full text search')
41 45 keywords = ' '.join (['rhodecode', 'rhodiumcode', 'mercurial', 'git',
42 46 'repository management', 'hgweb replacement'
43 47 'hgwebdir', 'gitweb replacement', 'serving hgweb',
44 48 ])
45 49 #long description
46 50 try:
47 51 readme_file = 'README.rst'
48 52 changelog_file = 'docs/changelog.rst'
49 53 long_description = open(readme_file).read() + '\n\n' + \
50 54 open(changelog_file).read()
51 55
52 56 except IOError, err:
53 57 sys.stderr.write("[WARNING] Cannot find file specified as "
54 58 "long_description (%s)\n or changelog (%s) skipping that file" \
55 59 % (readme_file, changelog_file))
56 60 long_description = description
57 61
58 62
59 63 try:
60 64 from setuptools import setup, find_packages
61 65 except ImportError:
62 66 from ez_setup import use_setuptools
63 67 use_setuptools()
64 68 from setuptools import setup, find_packages
65 69 #packages
66 70 packages = find_packages(exclude=['ez_setup'])
67 71
68 72 setup(
69 73 name='RhodeCode',
70 74 version=get_version(),
71 75 description=description,
72 76 long_description=long_description,
73 77 keywords=keywords,
74 78 license='BSD',
75 79 author='Marcin Kuzminski',
76 80 author_email='marcin@python-works.com',
77 81 url='http://hg.python-works.com',
78 82 install_requires=requirements,
79 83 classifiers=classifiers,
80 84 setup_requires=["PasteScript>=1.6.3"],
81 85 data_files=data_files,
82 86 packages=packages,
83 87 include_package_data=True,
84 88 test_suite='nose.collector',
85 89 package_data=package_data,
86 90 message_extractors={'rhodecode': [
87 91 ('**.py', 'python', None),
88 92 ('templates/**.mako', 'mako', {'input_encoding': 'utf-8'}),
89 93 ('public/**', 'ignore', None)]},
90 94 zip_safe=False,
91 95 paster_plugins=['PasteScript', 'Pylons'],
92 96 entry_points="""
93 97 [paste.app_factory]
94 98 main = rhodecode.config.middleware:make_app
95 99
96 100 [paste.app_install]
97 101 main = pylons.util:PylonsInstaller
98 102
99 103 [paste.global_paster_command]
100 104 make-index = rhodecode.lib.indexers:MakeIndex
101 105 upgrade-db = rhodecode.lib.dbmigrate:UpgradeDb
102 106 celeryd=rhodecode.lib.celerypylons.commands:CeleryDaemonCommand
103 107 celerybeat=rhodecode.lib.celerypylons.commands:CeleryBeatCommand
104 108 camqadm=rhodecode.lib.celerypylons.commands:CAMQPAdminCommand
105 109 celeryev=rhodecode.lib.celerypylons.commands:CeleryEventCommand
106 110
107 111 """,
108 112 )
General Comments 0
You need to be logged in to leave comments. Login now