##// END OF EJS Templates
fixed #570 explicit users group permissions can overwrite owner permissions...
marcink -
r2864:5c1ad3b4 beta
parent child Browse files
Show More
@@ -1,786 +1,789 b''
1 1 .. _changelog:
2 2
3 3 =========
4 4 Changelog
5 5 =========
6 6
7 7
8 8 1.4.3 (**2012-XX-XX**)
9 9 ----------------------
10 10
11 11 :status: in-progress
12 12 :branch: beta
13 13
14 14 news
15 15 ++++
16 16
17 17 - #558 Added config file to hooks extra data
18 - bumbped mercurial version to 2.3.1
18 19
19 20 fixes
20 21 +++++
21 22
23 - fixed #570 explicit users group permissions can overwrite owner permissions
24
22 25 1.4.2 (**2012-09-12**)
23 26 ----------------------
24 27
25 28 news
26 29 ++++
27 30
28 31 - added option to menu to quick lock/unlock repository for users that have
29 32 write access to
30 33 - Implemented permissions for writing to repo
31 34 groups. Now only write access to group allows to create a repostiory
32 35 within that group
33 36 - #565 Add support for {netloc} and {scheme} to alternative_gravatar_url
34 37 - updated translation for zh_CN
35 38
36 39 fixes
37 40 +++++
38 41
39 42 - fixed visual permissions check on repos groups inside groups
40 43 - fixed issues with non-ascii search terms in search, and indexers
41 44 - fixed parsing of page number in GET parameters
42 45 - fixed issues with generating pull-request overview for repos with
43 46 bookmarks and tags, also preview doesn't loose chosen revision from
44 47 select dropdown
45 48
46 49 1.4.1 (**2012-09-07**)
47 50 ----------------------
48 51
49 52 news
50 53 ++++
51 54
52 55 - always put a comment about code-review status change even if user send
53 56 empty data
54 57 - modified_on column saves repository update and it's going to be used
55 58 later for light version of main page ref #500
56 59 - pull request notifications send much nicer emails with details about pull
57 60 request
58 61 - #551 show breadcrumbs in summary view for repositories inside a group
59 62
60 63 fixes
61 64 +++++
62 65
63 66 - fixed migrations of permissions that can lead to inconsistency.
64 67 Some users sent feedback that after upgrading from older versions issues
65 68 with updating default permissions occurred. RhodeCode detects that now and
66 69 resets default user permission to initial state if there is a need for that.
67 70 Also forces users to set the default value for new forking permission.
68 71 - #535 improved apache wsgi example configuration in docs
69 72 - fixes #550 mercurial repositories comparision failed when origin repo had
70 73 additional not-common changesets
71 74 - fixed status of code-review in preview windows of pull request
72 75 - git forks were not initialized at bare repos
73 76 - fixes #555 fixes issues with comparing non-related repositories
74 77 - fixes #557 follower counter always counts up
75 78 - fixed issue #560 require push ssl checkbox wasn't shown when option was
76 79 enabled
77 80 - fixed #559
78 81 - fixed issue #559 fixed bug in routing that mapped repo names with <name>_<num> in name as
79 82 if it was a request to url by repository ID
80 83
81 84 1.4.0 (**2012-09-03**)
82 85 ----------------------
83 86
84 87 news
85 88 ++++
86 89
87 90 - new codereview system
88 91 - email map, allowing users to have multiple email addresses mapped into
89 92 their accounts
90 93 - improved git-hook system. Now all actions for git are logged into journal
91 94 including pushed revisions, user and IP address
92 95 - changed setup-app into setup-rhodecode and added default options to it.
93 96 - new git repos are created as bare now by default
94 97 - #464 added links to groups in permission box
95 98 - #465 mentions autocomplete inside comments boxes
96 99 - #469 added --update-only option to whoosh to re-index only given list
97 100 of repos in index
98 101 - rhodecode-api CLI client
99 102 - new git http protocol replaced buggy dulwich implementation.
100 103 Now based on pygrack & gitweb
101 104 - Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and
102 105 reformated based on user suggestions. Additional rss/atom feeds for user
103 106 journal
104 107 - various i18n improvements
105 108 - #478 permissions overview for admin in user edit view
106 109 - File view now displays small gravatars off all authors of given file
107 110 - Implemented landing revisions. Each repository will get landing_rev attribute
108 111 that defines 'default' revision/branch for generating readme files
109 112 - Implemented #509, RhodeCode enforces SSL for push/pulling if requested at
110 113 earliest possible call.
111 114 - Import remote svn repositories to mercurial using hgsubversion.
112 115 - Fixed #508 RhodeCode now has a option to explicitly set forking permissions
113 116 - RhodeCode can use alternative server for generating avatar icons
114 117 - implemented repositories locking. Pull locks, push unlocks. Also can be done
115 118 via API calls
116 119 - #538 form for permissions can handle multiple users at once
117 120
118 121 fixes
119 122 +++++
120 123
121 124 - improved translations
122 125 - fixes issue #455 Creating an archive generates an exception on Windows
123 126 - fixes #448 Download ZIP archive keeps file in /tmp open and results
124 127 in out of disk space
125 128 - fixes issue #454 Search results under Windows include proceeding
126 129 backslash
127 130 - fixed issue #450. Rhodecode no longer will crash when bad revision is
128 131 present in journal data.
129 132 - fix for issue #417, git execution was broken on windows for certain
130 133 commands.
131 134 - fixed #413. Don't disable .git directory for bare repos on deleting
132 135 - fixed issue #459. Changed the way of obtaining logger in reindex task.
133 136 - fixed #453 added ID field in whoosh SCHEMA that solves the issue of
134 137 reindexing modified files
135 138 - fixed #481 rhodecode emails are sent without Date header
136 139 - fixed #458 wrong count when no repos are present
137 140 - fixed issue #492 missing `\ No newline at end of file` test at the end of
138 141 new chunk in html diff
139 142 - full text search now works also for commit messages
140 143
141 144 1.3.6 (**2012-05-17**)
142 145 ----------------------
143 146
144 147 news
145 148 ++++
146 149
147 150 - chinese traditional translation
148 151 - changed setup-app into setup-rhodecode and added arguments for auto-setup
149 152 mode that doesn't need user interaction
150 153
151 154 fixes
152 155 +++++
153 156
154 157 - fixed no scm found warning
155 158 - fixed __future__ import error on rcextensions
156 159 - made simplejson required lib for speedup on JSON encoding
157 160 - fixes #449 bad regex could get more than revisions from parsing history
158 161 - don't clear DB session when CELERY_EAGER is turned ON
159 162
160 163 1.3.5 (**2012-05-10**)
161 164 ----------------------
162 165
163 166 news
164 167 ++++
165 168
166 169 - use ext_json for json module
167 170 - unified annotation view with file source view
168 171 - notification improvements, better inbox + css
169 172 - #419 don't strip passwords for login forms, make rhodecode
170 173 more compatible with LDAP servers
171 174 - Added HTTP_X_FORWARDED_FOR as another method of extracting
172 175 IP for pull/push logs. - moved all to base controller
173 176 - #415: Adding comment to changeset causes reload.
174 177 Comments are now added via ajax and doesn't reload the page
175 178 - #374 LDAP config is discarded when LDAP can't be activated
176 179 - limited push/pull operations are now logged for git in the journal
177 180 - bumped mercurial to 2.2.X series
178 181 - added support for displaying submodules in file-browser
179 182 - #421 added bookmarks in changelog view
180 183
181 184 fixes
182 185 +++++
183 186
184 187 - fixed dev-version marker for stable when served from source codes
185 188 - fixed missing permission checks on show forks page
186 189 - #418 cast to unicode fixes in notification objects
187 190 - #426 fixed mention extracting regex
188 191 - fixed remote-pulling for git remotes remopositories
189 192 - fixed #434: Error when accessing files or changesets of a git repository
190 193 with submodules
191 194 - fixed issue with empty APIKEYS for users after registration ref. #438
192 195 - fixed issue with getting README files from git repositories
193 196
194 197 1.3.4 (**2012-03-28**)
195 198 ----------------------
196 199
197 200 news
198 201 ++++
199 202
200 203 - Whoosh logging is now controlled by the .ini files logging setup
201 204 - added clone-url into edit form on /settings page
202 205 - added help text into repo add/edit forms
203 206 - created rcextensions module with additional mappings (ref #322) and
204 207 post push/pull/create repo hooks callbacks
205 208 - implemented #377 Users view for his own permissions on account page
206 209 - #399 added inheritance of permissions for users group on repos groups
207 210 - #401 repository group is automatically pre-selected when adding repos
208 211 inside a repository group
209 212 - added alternative HTTP 403 response when client failed to authenticate. Helps
210 213 solving issues with Mercurial and LDAP
211 214 - #402 removed group prefix from repository name when listing repositories
212 215 inside a group
213 216 - added gravatars into permission view and permissions autocomplete
214 217 - #347 when running multiple RhodeCode instances, properly invalidates cache
215 218 for all registered servers
216 219
217 220 fixes
218 221 +++++
219 222
220 223 - fixed #390 cache invalidation problems on repos inside group
221 224 - fixed #385 clone by ID url was loosing proxy prefix in URL
222 225 - fixed some unicode problems with waitress
223 226 - fixed issue with escaping < and > in changeset commits
224 227 - fixed error occurring during recursive group creation in API
225 228 create_repo function
226 229 - fixed #393 py2.5 fixes for routes url generator
227 230 - fixed #397 Private repository groups shows up before login
228 231 - fixed #396 fixed problems with revoking users in nested groups
229 232 - fixed mysql unicode issues + specified InnoDB as default engine with
230 233 utf8 charset
231 234 - #406 trim long branch/tag names in changelog to not break UI
232 235
233 236 1.3.3 (**2012-03-02**)
234 237 ----------------------
235 238
236 239 news
237 240 ++++
238 241
239 242
240 243 fixes
241 244 +++++
242 245
243 246 - fixed some python2.5 compatibility issues
244 247 - fixed issues with removed repos was accidentally added as groups, after
245 248 full rescan of paths
246 249 - fixes #376 Cannot edit user (using container auth)
247 250 - fixes #378 Invalid image urls on changeset screen with proxy-prefix
248 251 configuration
249 252 - fixed initial sorting of repos inside repo group
250 253 - fixes issue when user tried to resubmit same permission into user/user_groups
251 254 - bumped beaker version that fixes #375 leap error bug
252 255 - fixed raw_changeset for git. It was generated with hg patch headers
253 256 - fixed vcs issue with last_changeset for filenodes
254 257 - fixed missing commit after hook delete
255 258 - fixed #372 issues with git operation detection that caused a security issue
256 259 for git repos
257 260
258 261 1.3.2 (**2012-02-28**)
259 262 ----------------------
260 263
261 264 news
262 265 ++++
263 266
264 267
265 268 fixes
266 269 +++++
267 270
268 271 - fixed git protocol issues with repos-groups
269 272 - fixed git remote repos validator that prevented from cloning remote git repos
270 273 - fixes #370 ending slashes fixes for repo and groups
271 274 - fixes #368 improved git-protocol detection to handle other clients
272 275 - fixes #366 When Setting Repository Group To Blank Repo Group Wont Be
273 276 Moved To Root
274 277 - fixes #371 fixed issues with beaker/sqlalchemy and non-ascii cache keys
275 278 - fixed #373 missing cascade drop on user_group_to_perm table
276 279
277 280 1.3.1 (**2012-02-27**)
278 281 ----------------------
279 282
280 283 news
281 284 ++++
282 285
283 286
284 287 fixes
285 288 +++++
286 289
287 290 - redirection loop occurs when remember-me wasn't checked during login
288 291 - fixes issues with git blob history generation
289 292 - don't fetch branch for git in file history dropdown. Causes unneeded slowness
290 293
291 294 1.3.0 (**2012-02-26**)
292 295 ----------------------
293 296
294 297 news
295 298 ++++
296 299
297 300 - code review, inspired by github code-comments
298 301 - #215 rst and markdown README files support
299 302 - #252 Container-based and proxy pass-through authentication support
300 303 - #44 branch browser. Filtering of changelog by branches
301 304 - mercurial bookmarks support
302 305 - new hover top menu, optimized to add maximum size for important views
303 306 - configurable clone url template with possibility to specify protocol like
304 307 ssh:// or http:// and also manually alter other parts of clone_url.
305 308 - enabled largefiles extension by default
306 309 - optimized summary file pages and saved a lot of unused space in them
307 310 - #239 option to manually mark repository as fork
308 311 - #320 mapping of commit authors to RhodeCode users
309 312 - #304 hashes are displayed using monospace font
310 313 - diff configuration, toggle white lines and context lines
311 314 - #307 configurable diffs, whitespace toggle, increasing context lines
312 315 - sorting on branches, tags and bookmarks using YUI datatable
313 316 - improved file filter on files page
314 317 - implements #330 api method for listing nodes ar particular revision
315 318 - #73 added linking issues in commit messages to chosen issue tracker url
316 319 based on user defined regular expression
317 320 - added linking of changesets in commit messages
318 321 - new compact changelog with expandable commit messages
319 322 - firstname and lastname are optional in user creation
320 323 - #348 added post-create repository hook
321 324 - #212 global encoding settings is now configurable from .ini files
322 325 - #227 added repository groups permissions
323 326 - markdown gets codehilite extensions
324 327 - new API methods, delete_repositories, grante/revoke permissions for groups
325 328 and repos
326 329
327 330
328 331 fixes
329 332 +++++
330 333
331 334 - rewrote dbsession management for atomic operations, and better error handling
332 335 - fixed sorting of repo tables
333 336 - #326 escape of special html entities in diffs
334 337 - normalized user_name => username in api attributes
335 338 - fixes #298 ldap created users with mixed case emails created conflicts
336 339 on saving a form
337 340 - fixes issue when owner of a repo couldn't revoke permissions for users
338 341 and groups
339 342 - fixes #271 rare JSON serialization problem with statistics
340 343 - fixes #337 missing validation check for conflicting names of a group with a
341 344 repositories group
342 345 - #340 fixed session problem for mysql and celery tasks
343 346 - fixed #331 RhodeCode mangles repository names if the a repository group
344 347 contains the "full path" to the repositories
345 348 - #355 RhodeCode doesn't store encrypted LDAP passwords
346 349
347 350 1.2.5 (**2012-01-28**)
348 351 ----------------------
349 352
350 353 news
351 354 ++++
352 355
353 356 fixes
354 357 +++++
355 358
356 359 - #340 Celery complains about MySQL server gone away, added session cleanup
357 360 for celery tasks
358 361 - #341 "scanning for repositories in None" log message during Rescan was missing
359 362 a parameter
360 363 - fixed creating archives with subrepos. Some hooks were triggered during that
361 364 operation leading to crash.
362 365 - fixed missing email in account page.
363 366 - Reverted Mercurial to 2.0.1 for windows due to bug in Mercurial that makes
364 367 forking on windows impossible
365 368
366 369 1.2.4 (**2012-01-19**)
367 370 ----------------------
368 371
369 372 news
370 373 ++++
371 374
372 375 - RhodeCode is bundled with mercurial series 2.0.X by default, with
373 376 full support to largefiles extension. Enabled by default in new installations
374 377 - #329 Ability to Add/Remove Groups to/from a Repository via AP
375 378 - added requires.txt file with requirements
376 379
377 380 fixes
378 381 +++++
379 382
380 383 - fixes db session issues with celery when emailing admins
381 384 - #331 RhodeCode mangles repository names if the a repository group
382 385 contains the "full path" to the repositories
383 386 - #298 Conflicting e-mail addresses for LDAP and RhodeCode users
384 387 - DB session cleanup after hg protocol operations, fixes issues with
385 388 `mysql has gone away` errors
386 389 - #333 doc fixes for get_repo api function
387 390 - #271 rare JSON serialization problem with statistics enabled
388 391 - #337 Fixes issues with validation of repository name conflicting with
389 392 a group name. A proper message is now displayed.
390 393 - #292 made ldap_dn in user edit readonly, to get rid of confusion that field
391 394 doesn't work
392 395 - #316 fixes issues with web description in hgrc files
393 396
394 397 1.2.3 (**2011-11-02**)
395 398 ----------------------
396 399
397 400 news
398 401 ++++
399 402
400 403 - added option to manage repos group for non admin users
401 404 - added following API methods for get_users, create_user, get_users_groups,
402 405 get_users_group, create_users_group, add_user_to_users_groups, get_repos,
403 406 get_repo, create_repo, add_user_to_repo
404 407 - implements #237 added password confirmation for my account
405 408 and admin edit user.
406 409 - implements #291 email notification for global events are now sent to all
407 410 administrator users, and global config email.
408 411
409 412 fixes
410 413 +++++
411 414
412 415 - added option for passing auth method for smtp mailer
413 416 - #276 issue with adding a single user with id>10 to usergroups
414 417 - #277 fixes windows LDAP settings in which missing values breaks the ldap auth
415 418 - #288 fixes managing of repos in a group for non admin user
416 419
417 420 1.2.2 (**2011-10-17**)
418 421 ----------------------
419 422
420 423 news
421 424 ++++
422 425
423 426 - #226 repo groups are available by path instead of numerical id
424 427
425 428 fixes
426 429 +++++
427 430
428 431 - #259 Groups with the same name but with different parent group
429 432 - #260 Put repo in group, then move group to another group -> repo becomes unavailable
430 433 - #258 RhodeCode 1.2 assumes egg folder is writable (lockfiles problems)
431 434 - #265 ldap save fails sometimes on converting attributes to booleans,
432 435 added getter and setter into model that will prevent from this on db model level
433 436 - fixed problems with timestamps issues #251 and #213
434 437 - fixes #266 RhodeCode allows to create repo with the same name and in
435 438 the same parent as group
436 439 - fixes #245 Rescan of the repositories on Windows
437 440 - fixes #248 cannot edit repos inside a group on windows
438 441 - fixes #219 forking problems on windows
439 442
440 443 1.2.1 (**2011-10-08**)
441 444 ----------------------
442 445
443 446 news
444 447 ++++
445 448
446 449
447 450 fixes
448 451 +++++
449 452
450 453 - fixed problems with basic auth and push problems
451 454 - gui fixes
452 455 - fixed logger
453 456
454 457 1.2.0 (**2011-10-07**)
455 458 ----------------------
456 459
457 460 news
458 461 ++++
459 462
460 463 - implemented #47 repository groups
461 464 - implemented #89 Can setup google analytics code from settings menu
462 465 - implemented #91 added nicer looking archive urls with more download options
463 466 like tags, branches
464 467 - implemented #44 into file browsing, and added follow branch option
465 468 - implemented #84 downloads can be enabled/disabled for each repository
466 469 - anonymous repository can be cloned without having to pass default:default
467 470 into clone url
468 471 - fixed #90 whoosh indexer can index chooses repositories passed in command
469 472 line
470 473 - extended journal with day aggregates and paging
471 474 - implemented #107 source code lines highlight ranges
472 475 - implemented #93 customizable changelog on combined revision ranges -
473 476 equivalent of githubs compare view
474 477 - implemented #108 extended and more powerful LDAP configuration
475 478 - implemented #56 users groups
476 479 - major code rewrites optimized codes for speed and memory usage
477 480 - raw and diff downloads are now in git format
478 481 - setup command checks for write access to given path
479 482 - fixed many issues with international characters and unicode. It uses utf8
480 483 decode with replace to provide less errors even with non utf8 encoded strings
481 484 - #125 added API KEY access to feeds
482 485 - #109 Repository can be created from external Mercurial link (aka. remote
483 486 repository, and manually updated (via pull) from admin panel
484 487 - beta git support - push/pull server + basic view for git repos
485 488 - added followers page and forks page
486 489 - server side file creation (with binary file upload interface)
487 490 and edition with commits powered by codemirror
488 491 - #111 file browser file finder, quick lookup files on whole file tree
489 492 - added quick login sliding menu into main page
490 493 - changelog uses lazy loading of affected files details, in some scenarios
491 494 this can improve speed of changelog page dramatically especially for
492 495 larger repositories.
493 496 - implements #214 added support for downloading subrepos in download menu.
494 497 - Added basic API for direct operations on rhodecode via JSON
495 498 - Implemented advanced hook management
496 499
497 500 fixes
498 501 +++++
499 502
500 503 - fixed file browser bug, when switching into given form revision the url was
501 504 not changing
502 505 - fixed propagation to error controller on simplehg and simplegit middlewares
503 506 - fixed error when trying to make a download on empty repository
504 507 - fixed problem with '[' chars in commit messages in journal
505 508 - fixed #99 Unicode errors, on file node paths with non utf-8 characters
506 509 - journal fork fixes
507 510 - removed issue with space inside renamed repository after deletion
508 511 - fixed strange issue on formencode imports
509 512 - fixed #126 Deleting repository on Windows, rename used incompatible chars.
510 513 - #150 fixes for errors on repositories mapped in db but corrupted in
511 514 filesystem
512 515 - fixed problem with ascendant characters in realm #181
513 516 - fixed problem with sqlite file based database connection pool
514 517 - whoosh indexer and code stats share the same dynamic extensions map
515 518 - fixes #188 - relationship delete of repo_to_perm entry on user removal
516 519 - fixes issue #189 Trending source files shows "show more" when no more exist
517 520 - fixes issue #197 Relative paths for pidlocks
518 521 - fixes issue #198 password will require only 3 chars now for login form
519 522 - fixes issue #199 wrong redirection for non admin users after creating a repository
520 523 - fixes issues #202, bad db constraint made impossible to attach same group
521 524 more than one time. Affects only mysql/postgres
522 525 - fixes #218 os.kill patch for windows was missing sig param
523 526 - improved rendering of dag (they are not trimmed anymore when number of
524 527 heads exceeds 5)
525 528
526 529 1.1.8 (**2011-04-12**)
527 530 ----------------------
528 531
529 532 news
530 533 ++++
531 534
532 535 - improved windows support
533 536
534 537 fixes
535 538 +++++
536 539
537 540 - fixed #140 freeze of python dateutil library, since new version is python2.x
538 541 incompatible
539 542 - setup-app will check for write permission in given path
540 543 - cleaned up license info issue #149
541 544 - fixes for issues #137,#116 and problems with unicode and accented characters.
542 545 - fixes crashes on gravatar, when passed in email as unicode
543 546 - fixed tooltip flickering problems
544 547 - fixed came_from redirection on windows
545 548 - fixed logging modules, and sql formatters
546 549 - windows fixes for os.kill issue #133
547 550 - fixes path splitting for windows issues #148
548 551 - fixed issue #143 wrong import on migration to 1.1.X
549 552 - fixed problems with displaying binary files, thanks to Thomas Waldmann
550 553 - removed name from archive files since it's breaking ui for long repo names
551 554 - fixed issue with archive headers sent to browser, thanks to Thomas Waldmann
552 555 - fixed compatibility for 1024px displays, and larger dpi settings, thanks to
553 556 Thomas Waldmann
554 557 - fixed issue #166 summary pager was skipping 10 revisions on second page
555 558
556 559
557 560 1.1.7 (**2011-03-23**)
558 561 ----------------------
559 562
560 563 news
561 564 ++++
562 565
563 566 fixes
564 567 +++++
565 568
566 569 - fixed (again) #136 installation support for FreeBSD
567 570
568 571
569 572 1.1.6 (**2011-03-21**)
570 573 ----------------------
571 574
572 575 news
573 576 ++++
574 577
575 578 fixes
576 579 +++++
577 580
578 581 - fixed #136 installation support for FreeBSD
579 582 - RhodeCode will check for python version during installation
580 583
581 584 1.1.5 (**2011-03-17**)
582 585 ----------------------
583 586
584 587 news
585 588 ++++
586 589
587 590 - basic windows support, by exchanging pybcrypt into sha256 for windows only
588 591 highly inspired by idea of mantis406
589 592
590 593 fixes
591 594 +++++
592 595
593 596 - fixed sorting by author in main page
594 597 - fixed crashes with diffs on binary files
595 598 - fixed #131 problem with boolean values for LDAP
596 599 - fixed #122 mysql problems thanks to striker69
597 600 - fixed problem with errors on calling raw/raw_files/annotate functions
598 601 with unknown revisions
599 602 - fixed returned rawfiles attachment names with international character
600 603 - cleaned out docs, big thanks to Jason Harris
601 604
602 605 1.1.4 (**2011-02-19**)
603 606 ----------------------
604 607
605 608 news
606 609 ++++
607 610
608 611 fixes
609 612 +++++
610 613
611 614 - fixed formencode import problem on settings page, that caused server crash
612 615 when that page was accessed as first after server start
613 616 - journal fixes
614 617 - fixed option to access repository just by entering http://server/<repo_name>
615 618
616 619 1.1.3 (**2011-02-16**)
617 620 ----------------------
618 621
619 622 news
620 623 ++++
621 624
622 625 - implemented #102 allowing the '.' character in username
623 626 - added option to access repository just by entering http://server/<repo_name>
624 627 - celery task ignores result for better performance
625 628
626 629 fixes
627 630 +++++
628 631
629 632 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
630 633 apollo13 and Johan Walles
631 634 - small fixes in journal
632 635 - fixed problems with getting setting for celery from .ini files
633 636 - registration, password reset and login boxes share the same title as main
634 637 application now
635 638 - fixed #113: to high permissions to fork repository
636 639 - fixed problem with '[' chars in commit messages in journal
637 640 - removed issue with space inside renamed repository after deletion
638 641 - db transaction fixes when filesystem repository creation failed
639 642 - fixed #106 relation issues on databases different than sqlite
640 643 - fixed static files paths links to use of url() method
641 644
642 645 1.1.2 (**2011-01-12**)
643 646 ----------------------
644 647
645 648 news
646 649 ++++
647 650
648 651
649 652 fixes
650 653 +++++
651 654
652 655 - fixes #98 protection against float division of percentage stats
653 656 - fixed graph bug
654 657 - forced webhelpers version since it was making troubles during installation
655 658
656 659 1.1.1 (**2011-01-06**)
657 660 ----------------------
658 661
659 662 news
660 663 ++++
661 664
662 665 - added force https option into ini files for easier https usage (no need to
663 666 set server headers with this options)
664 667 - small css updates
665 668
666 669 fixes
667 670 +++++
668 671
669 672 - fixed #96 redirect loop on files view on repositories without changesets
670 673 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
671 674 and server crashed with errors
672 675 - fixed large tooltips problems on main page
673 676 - fixed #92 whoosh indexer is more error proof
674 677
675 678 1.1.0 (**2010-12-18**)
676 679 ----------------------
677 680
678 681 news
679 682 ++++
680 683
681 684 - rewrite of internals for vcs >=0.1.10
682 685 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
683 686 with older clients
684 687 - anonymous access, authentication via ldap
685 688 - performance upgrade for cached repos list - each repository has its own
686 689 cache that's invalidated when needed.
687 690 - performance upgrades on repositories with large amount of commits (20K+)
688 691 - main page quick filter for filtering repositories
689 692 - user dashboards with ability to follow chosen repositories actions
690 693 - sends email to admin on new user registration
691 694 - added cache/statistics reset options into repository settings
692 695 - more detailed action logger (based on hooks) with pushed changesets lists
693 696 and options to disable those hooks from admin panel
694 697 - introduced new enhanced changelog for merges that shows more accurate results
695 698 - new improved and faster code stats (based on pygments lexers mapping tables,
696 699 showing up to 10 trending sources for each repository. Additionally stats
697 700 can be disabled in repository settings.
698 701 - gui optimizations, fixed application width to 1024px
699 702 - added cut off (for large files/changesets) limit into config files
700 703 - whoosh, celeryd, upgrade moved to paster command
701 704 - other than sqlite database backends can be used
702 705
703 706 fixes
704 707 +++++
705 708
706 709 - fixes #61 forked repo was showing only after cache expired
707 710 - fixes #76 no confirmation on user deletes
708 711 - fixes #66 Name field misspelled
709 712 - fixes #72 block user removal when he owns repositories
710 713 - fixes #69 added password confirmation fields
711 714 - fixes #87 RhodeCode crashes occasionally on updating repository owner
712 715 - fixes #82 broken annotations on files with more than 1 blank line at the end
713 716 - a lot of fixes and tweaks for file browser
714 717 - fixed detached session issues
715 718 - fixed when user had no repos he would see all repos listed in my account
716 719 - fixed ui() instance bug when global hgrc settings was loaded for server
717 720 instance and all hgrc options were merged with our db ui() object
718 721 - numerous small bugfixes
719 722
720 723 (special thanks for TkSoh for detailed feedback)
721 724
722 725
723 726 1.0.2 (**2010-11-12**)
724 727 ----------------------
725 728
726 729 news
727 730 ++++
728 731
729 732 - tested under python2.7
730 733 - bumped sqlalchemy and celery versions
731 734
732 735 fixes
733 736 +++++
734 737
735 738 - fixed #59 missing graph.js
736 739 - fixed repo_size crash when repository had broken symlinks
737 740 - fixed python2.5 crashes.
738 741
739 742
740 743 1.0.1 (**2010-11-10**)
741 744 ----------------------
742 745
743 746 news
744 747 ++++
745 748
746 749 - small css updated
747 750
748 751 fixes
749 752 +++++
750 753
751 754 - fixed #53 python2.5 incompatible enumerate calls
752 755 - fixed #52 disable mercurial extension for web
753 756 - fixed #51 deleting repositories don't delete it's dependent objects
754 757
755 758
756 759 1.0.0 (**2010-11-02**)
757 760 ----------------------
758 761
759 762 - security bugfix simplehg wasn't checking for permissions on commands
760 763 other than pull or push.
761 764 - fixed doubled messages after push or pull in admin journal
762 765 - templating and css corrections, fixed repo switcher on chrome, updated titles
763 766 - admin menu accessible from options menu on repository view
764 767 - permissions cached queries
765 768
766 769 1.0.0rc4 (**2010-10-12**)
767 770 --------------------------
768 771
769 772 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
770 773 - removed cache_manager settings from sqlalchemy meta
771 774 - added sqlalchemy cache settings to ini files
772 775 - validated password length and added second try of failure on paster setup-app
773 776 - fixed setup database destroy prompt even when there was no db
774 777
775 778
776 779 1.0.0rc3 (**2010-10-11**)
777 780 -------------------------
778 781
779 782 - fixed i18n during installation.
780 783
781 784 1.0.0rc2 (**2010-10-11**)
782 785 -------------------------
783 786
784 787 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
785 788 occure. After vcs is fixed it'll be put back again.
786 789 - templating/css rewrites, optimized css. No newline at end of file
@@ -1,669 +1,673 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.user
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 users model for RhodeCode
7 7
8 8 :created_on: Apr 9, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import itertools
29 29 from pylons import url
30 30 from pylons.i18n.translation import _
31 31
32 32 from sqlalchemy.exc import DatabaseError
33 33 from sqlalchemy.orm import joinedload
34 34
35 35 from rhodecode.lib.utils2 import safe_unicode, generate_api_key
36 36 from rhodecode.lib.caching_query import FromCache
37 37 from rhodecode.model import BaseModel
38 38 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
39 39 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \
40 40 Notification, RepoGroup, UserRepoGroupToPerm, UsersGroupRepoGroupToPerm, \
41 41 UserEmailMap
42 42 from rhodecode.lib.exceptions import DefaultUserException, \
43 43 UserOwnsReposException
44 44
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48 PERM_WEIGHTS = Permission.PERM_WEIGHTS
49 49
50 50
51 51 class UserModel(BaseModel):
52 52 cls = User
53 53
54 54 def get(self, user_id, cache=False):
55 55 user = self.sa.query(User)
56 56 if cache:
57 57 user = user.options(FromCache("sql_cache_short",
58 58 "get_user_%s" % user_id))
59 59 return user.get(user_id)
60 60
61 61 def get_user(self, user):
62 62 return self._get_user(user)
63 63
64 64 def get_by_username(self, username, cache=False, case_insensitive=False):
65 65
66 66 if case_insensitive:
67 67 user = self.sa.query(User).filter(User.username.ilike(username))
68 68 else:
69 69 user = self.sa.query(User)\
70 70 .filter(User.username == username)
71 71 if cache:
72 72 user = user.options(FromCache("sql_cache_short",
73 73 "get_user_%s" % username))
74 74 return user.scalar()
75 75
76 76 def get_by_email(self, email, cache=False, case_insensitive=False):
77 77 return User.get_by_email(email, case_insensitive, cache)
78 78
79 79 def get_by_api_key(self, api_key, cache=False):
80 80 return User.get_by_api_key(api_key, cache)
81 81
82 82 def create(self, form_data):
83 83 from rhodecode.lib.auth import get_crypt_password
84 84 try:
85 85 new_user = User()
86 86 for k, v in form_data.items():
87 87 if k == 'password':
88 88 v = get_crypt_password(v)
89 89 if k == 'firstname':
90 90 k = 'name'
91 91 setattr(new_user, k, v)
92 92
93 93 new_user.api_key = generate_api_key(form_data['username'])
94 94 self.sa.add(new_user)
95 95 return new_user
96 96 except:
97 97 log.error(traceback.format_exc())
98 98 raise
99 99
100 100 def create_or_update(self, username, password, email, firstname='',
101 101 lastname='', active=True, admin=False, ldap_dn=None):
102 102 """
103 103 Creates a new instance if not found, or updates current one
104 104
105 105 :param username:
106 106 :param password:
107 107 :param email:
108 108 :param active:
109 109 :param firstname:
110 110 :param lastname:
111 111 :param active:
112 112 :param admin:
113 113 :param ldap_dn:
114 114 """
115 115
116 116 from rhodecode.lib.auth import get_crypt_password
117 117
118 118 log.debug('Checking for %s account in RhodeCode database' % username)
119 119 user = User.get_by_username(username, case_insensitive=True)
120 120 if user is None:
121 121 log.debug('creating new user %s' % username)
122 122 new_user = User()
123 123 edit = False
124 124 else:
125 125 log.debug('updating user %s' % username)
126 126 new_user = user
127 127 edit = True
128 128
129 129 try:
130 130 new_user.username = username
131 131 new_user.admin = admin
132 132 # set password only if creating an user or password is changed
133 133 if edit is False or user.password != password:
134 134 new_user.password = get_crypt_password(password)
135 135 new_user.api_key = generate_api_key(username)
136 136 new_user.email = email
137 137 new_user.active = active
138 138 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
139 139 new_user.name = firstname
140 140 new_user.lastname = lastname
141 141 self.sa.add(new_user)
142 142 return new_user
143 143 except (DatabaseError,):
144 144 log.error(traceback.format_exc())
145 145 raise
146 146
147 147 def create_for_container_auth(self, username, attrs):
148 148 """
149 149 Creates the given user if it's not already in the database
150 150
151 151 :param username:
152 152 :param attrs:
153 153 """
154 154 if self.get_by_username(username, case_insensitive=True) is None:
155 155
156 156 # autogenerate email for container account without one
157 157 generate_email = lambda usr: '%s@container_auth.account' % usr
158 158
159 159 try:
160 160 new_user = User()
161 161 new_user.username = username
162 162 new_user.password = None
163 163 new_user.api_key = generate_api_key(username)
164 164 new_user.email = attrs['email']
165 165 new_user.active = attrs.get('active', True)
166 166 new_user.name = attrs['name'] or generate_email(username)
167 167 new_user.lastname = attrs['lastname']
168 168
169 169 self.sa.add(new_user)
170 170 return new_user
171 171 except (DatabaseError,):
172 172 log.error(traceback.format_exc())
173 173 self.sa.rollback()
174 174 raise
175 175 log.debug('User %s already exists. Skipping creation of account'
176 176 ' for container auth.', username)
177 177 return None
178 178
179 179 def create_ldap(self, username, password, user_dn, attrs):
180 180 """
181 181 Checks if user is in database, if not creates this user marked
182 182 as ldap user
183 183
184 184 :param username:
185 185 :param password:
186 186 :param user_dn:
187 187 :param attrs:
188 188 """
189 189 from rhodecode.lib.auth import get_crypt_password
190 190 log.debug('Checking for such ldap account in RhodeCode database')
191 191 if self.get_by_username(username, case_insensitive=True) is None:
192 192
193 193 # autogenerate email for ldap account without one
194 194 generate_email = lambda usr: '%s@ldap.account' % usr
195 195
196 196 try:
197 197 new_user = User()
198 198 username = username.lower()
199 199 # add ldap account always lowercase
200 200 new_user.username = username
201 201 new_user.password = get_crypt_password(password)
202 202 new_user.api_key = generate_api_key(username)
203 203 new_user.email = attrs['email'] or generate_email(username)
204 204 new_user.active = attrs.get('active', True)
205 205 new_user.ldap_dn = safe_unicode(user_dn)
206 206 new_user.name = attrs['name']
207 207 new_user.lastname = attrs['lastname']
208 208
209 209 self.sa.add(new_user)
210 210 return new_user
211 211 except (DatabaseError,):
212 212 log.error(traceback.format_exc())
213 213 self.sa.rollback()
214 214 raise
215 215 log.debug('this %s user exists skipping creation of ldap account',
216 216 username)
217 217 return None
218 218
219 219 def create_registration(self, form_data):
220 220 from rhodecode.model.notification import NotificationModel
221 221
222 222 try:
223 223 form_data['admin'] = False
224 224 new_user = self.create(form_data)
225 225
226 226 self.sa.add(new_user)
227 227 self.sa.flush()
228 228
229 229 # notification to admins
230 230 subject = _('new user registration')
231 231 body = ('New user registration\n'
232 232 '---------------------\n'
233 233 '- Username: %s\n'
234 234 '- Full Name: %s\n'
235 235 '- Email: %s\n')
236 236 body = body % (new_user.username, new_user.full_name,
237 237 new_user.email)
238 238 edit_url = url('edit_user', id=new_user.user_id, qualified=True)
239 239 kw = {'registered_user_url': edit_url}
240 240 NotificationModel().create(created_by=new_user, subject=subject,
241 241 body=body, recipients=None,
242 242 type_=Notification.TYPE_REGISTRATION,
243 243 email_kwargs=kw)
244 244
245 245 except:
246 246 log.error(traceback.format_exc())
247 247 raise
248 248
249 249 def update(self, user_id, form_data):
250 250 from rhodecode.lib.auth import get_crypt_password
251 251 try:
252 252 user = self.get(user_id, cache=False)
253 253 if user.username == 'default':
254 254 raise DefaultUserException(
255 255 _("You can't Edit this user since it's"
256 256 " crucial for entire application"))
257 257
258 258 for k, v in form_data.items():
259 259 if k == 'new_password' and v:
260 260 user.password = get_crypt_password(v)
261 261 user.api_key = generate_api_key(user.username)
262 262 else:
263 263 if k == 'firstname':
264 264 k = 'name'
265 265 setattr(user, k, v)
266 266 self.sa.add(user)
267 267 except:
268 268 log.error(traceback.format_exc())
269 269 raise
270 270
271 271 def update_user(self, user, **kwargs):
272 272 from rhodecode.lib.auth import get_crypt_password
273 273 try:
274 274 user = self._get_user(user)
275 275 if user.username == 'default':
276 276 raise DefaultUserException(
277 277 _("You can't Edit this user since it's"
278 278 " crucial for entire application")
279 279 )
280 280
281 281 for k, v in kwargs.items():
282 282 if k == 'password' and v:
283 283 v = get_crypt_password(v)
284 284 user.api_key = generate_api_key(user.username)
285 285
286 286 setattr(user, k, v)
287 287 self.sa.add(user)
288 288 return user
289 289 except:
290 290 log.error(traceback.format_exc())
291 291 raise
292 292
293 293 def update_my_account(self, user_id, form_data):
294 294 from rhodecode.lib.auth import get_crypt_password
295 295 try:
296 296 user = self.get(user_id, cache=False)
297 297 if user.username == 'default':
298 298 raise DefaultUserException(
299 299 _("You can't Edit this user since it's"
300 300 " crucial for entire application")
301 301 )
302 302 for k, v in form_data.items():
303 303 if k == 'new_password' and v:
304 304 user.password = get_crypt_password(v)
305 305 user.api_key = generate_api_key(user.username)
306 306 else:
307 307 if k == 'firstname':
308 308 k = 'name'
309 309 if k not in ['admin', 'active']:
310 310 setattr(user, k, v)
311 311
312 312 self.sa.add(user)
313 313 except:
314 314 log.error(traceback.format_exc())
315 315 raise
316 316
317 317 def delete(self, user):
318 318 user = self._get_user(user)
319 319
320 320 try:
321 321 if user.username == 'default':
322 322 raise DefaultUserException(
323 323 _(u"You can't remove this user since it's"
324 324 " crucial for entire application")
325 325 )
326 326 if user.repositories:
327 327 repos = [x.repo_name for x in user.repositories]
328 328 raise UserOwnsReposException(
329 329 _(u'user "%s" still owns %s repositories and cannot be '
330 330 'removed. Switch owners or remove those repositories. %s')
331 331 % (user.username, len(repos), ', '.join(repos))
332 332 )
333 333 self.sa.delete(user)
334 334 except:
335 335 log.error(traceback.format_exc())
336 336 raise
337 337
338 338 def reset_password_link(self, data):
339 339 from rhodecode.lib.celerylib import tasks, run_task
340 340 run_task(tasks.send_password_link, data['email'])
341 341
342 342 def reset_password(self, data):
343 343 from rhodecode.lib.celerylib import tasks, run_task
344 344 run_task(tasks.reset_user_password, data['email'])
345 345
346 346 def fill_data(self, auth_user, user_id=None, api_key=None):
347 347 """
348 348 Fetches auth_user by user_id,or api_key if present.
349 349 Fills auth_user attributes with those taken from database.
350 350 Additionally set's is_authenitated if lookup fails
351 351 present in database
352 352
353 353 :param auth_user: instance of user to set attributes
354 354 :param user_id: user id to fetch by
355 355 :param api_key: api key to fetch by
356 356 """
357 357 if user_id is None and api_key is None:
358 358 raise Exception('You need to pass user_id or api_key')
359 359
360 360 try:
361 361 if api_key:
362 362 dbuser = self.get_by_api_key(api_key)
363 363 else:
364 364 dbuser = self.get(user_id)
365 365
366 366 if dbuser is not None and dbuser.active:
367 367 log.debug('filling %s data' % dbuser)
368 368 for k, v in dbuser.get_dict().items():
369 369 setattr(auth_user, k, v)
370 370 else:
371 371 return False
372 372
373 373 except:
374 374 log.error(traceback.format_exc())
375 375 auth_user.is_authenticated = False
376 376 return False
377 377
378 378 return True
379 379
380 380 def fill_perms(self, user):
381 381 """
382 382 Fills user permission attribute with permissions taken from database
383 383 works for permissions given for repositories, and for permissions that
384 384 are granted to groups
385 385
386 386 :param user: user instance to fill his perms
387 387 """
388 388 RK = 'repositories'
389 389 GK = 'repositories_groups'
390 390 GLOBAL = 'global'
391 391 user.permissions[RK] = {}
392 392 user.permissions[GK] = {}
393 393 user.permissions[GLOBAL] = set()
394 394
395 395 #======================================================================
396 396 # fetch default permissions
397 397 #======================================================================
398 398 default_user = User.get_by_username('default', cache=True)
399 399 default_user_id = default_user.user_id
400 400
401 401 default_repo_perms = Permission.get_default_perms(default_user_id)
402 402 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
403 403
404 404 if user.is_admin:
405 405 #==================================================================
406 406 # admin user have all default rights for repositories
407 407 # and groups set to admin
408 408 #==================================================================
409 409 user.permissions[GLOBAL].add('hg.admin')
410 410
411 411 # repositories
412 412 for perm in default_repo_perms:
413 413 r_k = perm.UserRepoToPerm.repository.repo_name
414 414 p = 'repository.admin'
415 415 user.permissions[RK][r_k] = p
416 416
417 417 # repositories groups
418 418 for perm in default_repo_groups_perms:
419 419 rg_k = perm.UserRepoGroupToPerm.group.group_name
420 420 p = 'group.admin'
421 421 user.permissions[GK][rg_k] = p
422 422 return user
423 423
424 424 #==================================================================
425 425 # SET DEFAULTS GLOBAL, REPOS, REPOS GROUPS
426 426 #==================================================================
427 427 uid = user.user_id
428 428
429 429 # default global permissions taken fron the default user
430 430 default_global_perms = self.sa.query(UserToPerm)\
431 431 .filter(UserToPerm.user_id == default_user_id)
432 432
433 433 for perm in default_global_perms:
434 434 user.permissions[GLOBAL].add(perm.permission.permission_name)
435 435
436 436 # defaults for repositories, taken from default user
437 437 for perm in default_repo_perms:
438 438 r_k = perm.UserRepoToPerm.repository.repo_name
439 439 if perm.Repository.private and not (perm.Repository.user_id == uid):
440 440 # disable defaults for private repos,
441 441 p = 'repository.none'
442 442 elif perm.Repository.user_id == uid:
443 443 # set admin if owner
444 444 p = 'repository.admin'
445 445 else:
446 446 p = perm.Permission.permission_name
447 447
448 448 user.permissions[RK][r_k] = p
449 449
450 450 # defaults for repositories groups taken from default user permission
451 451 # on given group
452 452 for perm in default_repo_groups_perms:
453 453 rg_k = perm.UserRepoGroupToPerm.group.group_name
454 454 p = perm.Permission.permission_name
455 455 user.permissions[GK][rg_k] = p
456 456
457 457 #======================================================================
458 458 # !! OVERRIDE GLOBALS !! with user permissions if any found
459 459 #======================================================================
460 460 # those can be configured from groups or users explicitly
461 461 _configurable = set(['hg.fork.none', 'hg.fork.repository',
462 462 'hg.create.none', 'hg.create.repository'])
463 463
464 464 # USER GROUPS comes first
465 465 # users group global permissions
466 466 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
467 467 .options(joinedload(UsersGroupToPerm.permission))\
468 468 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
469 469 UsersGroupMember.users_group_id))\
470 470 .filter(UsersGroupMember.user_id == uid)\
471 471 .order_by(UsersGroupToPerm.users_group_id)\
472 472 .all()
473 473 #need to group here by groups since user can be in more than one group
474 474 _grouped = [[x, list(y)] for x, y in
475 475 itertools.groupby(user_perms_from_users_groups,
476 476 lambda x:x.users_group)]
477 477 for gr, perms in _grouped:
478 478 # since user can be in multiple groups iterate over them and
479 479 # select the lowest permissions first (more explicit)
480 480 ##TODO: do this^^
481 481 if not gr.inherit_default_permissions:
482 482 # NEED TO IGNORE all configurable permissions and
483 483 # replace them with explicitly set
484 484 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
485 485 .difference(_configurable)
486 486 for perm in perms:
487 487 user.permissions[GLOBAL].add(perm.permission.permission_name)
488 488
489 489 # user specific global permissions
490 490 user_perms = self.sa.query(UserToPerm)\
491 491 .options(joinedload(UserToPerm.permission))\
492 492 .filter(UserToPerm.user_id == uid).all()
493 493
494 494 if not user.inherit_default_permissions:
495 495 # NEED TO IGNORE all configurable permissions and
496 496 # replace them with explicitly set
497 497 user.permissions[GLOBAL] = user.permissions[GLOBAL]\
498 498 .difference(_configurable)
499 499
500 500 for perm in user_perms:
501 501 user.permissions[GLOBAL].add(perm.permission.permission_name)
502 502
503 503 #======================================================================
504 504 # !! REPO PERMISSIONS !!
505 505 #======================================================================
506 506 #======================================================================
507 507 # check if user is part of user groups for this repository and
508 508 # fill in (or NOT replace with higher `or 1` permissions
509 509 #======================================================================
510 510 # users group for repositories permissions
511 511 user_repo_perms_from_users_groups = \
512 512 self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
513 513 .join((Repository, UsersGroupRepoToPerm.repository_id ==
514 514 Repository.repo_id))\
515 515 .join((Permission, UsersGroupRepoToPerm.permission_id ==
516 516 Permission.permission_id))\
517 517 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
518 518 UsersGroupMember.users_group_id))\
519 519 .filter(UsersGroupMember.user_id == uid)\
520 520 .all()
521 521
522 522 for perm in user_repo_perms_from_users_groups:
523 523 r_k = perm.UsersGroupRepoToPerm.repository.repo_name
524 524 p = perm.Permission.permission_name
525 525 cur_perm = user.permissions[RK][r_k]
526 526 # overwrite permission only if it's greater than permission
527 # given from other sources
527 # given from other sources - disabled with `or 1` now
528 528 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check
529 if perm.Repository.user_id == uid:
530 # set admin if owner
531 p = 'repository.admin'
532
529 533 user.permissions[RK][r_k] = p
530 534
531 535 # user explicit permissions for repositories
532 536 user_repo_perms = \
533 537 self.sa.query(UserRepoToPerm, Permission, Repository)\
534 538 .join((Repository, UserRepoToPerm.repository_id ==
535 539 Repository.repo_id))\
536 540 .join((Permission, UserRepoToPerm.permission_id ==
537 541 Permission.permission_id))\
538 542 .filter(UserRepoToPerm.user_id == uid)\
539 543 .all()
540 544
541 545 for perm in user_repo_perms:
542 546 # set admin if owner
543 547 r_k = perm.UserRepoToPerm.repository.repo_name
544 548 if perm.Repository.user_id == uid:
545 549 p = 'repository.admin'
546 550 else:
547 551 p = perm.Permission.permission_name
548 552 user.permissions[RK][r_k] = p
549 553
550 554 # REPO GROUP
551 555 #==================================================================
552 556 # get access for this user for repos group and override defaults
553 557 #==================================================================
554 558
555 559 # user explicit permissions for repository
556 560 user_repo_groups_perms = \
557 561 self.sa.query(UserRepoGroupToPerm, Permission, RepoGroup)\
558 562 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
559 563 .join((Permission, UserRepoGroupToPerm.permission_id == Permission.permission_id))\
560 564 .filter(UserRepoGroupToPerm.user_id == uid)\
561 565 .all()
562 566
563 567 for perm in user_repo_groups_perms:
564 568 rg_k = perm.UserRepoGroupToPerm.group.group_name
565 569 p = perm.Permission.permission_name
566 570 cur_perm = user.permissions[GK][rg_k]
567 571 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check
568 572 user.permissions[GK][rg_k] = p
569 573
570 574 # REPO GROUP + USER GROUP
571 575 #==================================================================
572 576 # check if user is part of user groups for this repo group and
573 577 # fill in (or replace with higher) permissions
574 578 #==================================================================
575 579
576 580 # users group for repositories permissions
577 581 user_repo_group_perms_from_users_groups = \
578 582 self.sa.query(UsersGroupRepoGroupToPerm, Permission, RepoGroup)\
579 583 .join((RepoGroup, UsersGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
580 584 .join((Permission, UsersGroupRepoGroupToPerm.permission_id == Permission.permission_id))\
581 585 .join((UsersGroupMember, UsersGroupRepoGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
582 586 .filter(UsersGroupMember.user_id == uid)\
583 587 .all()
584 588
585 589 for perm in user_repo_group_perms_from_users_groups:
586 590 g_k = perm.UsersGroupRepoGroupToPerm.group.group_name
587 591 p = perm.Permission.permission_name
588 592 cur_perm = user.permissions[GK][g_k]
589 593 # overwrite permission only if it's greater than permission
590 594 # given from other sources
591 595 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1: # disable check
592 596 user.permissions[GK][g_k] = p
593 597
594 598 return user
595 599
596 600 def has_perm(self, user, perm):
597 601 perm = self._get_perm(perm)
598 602 user = self._get_user(user)
599 603
600 604 return UserToPerm.query().filter(UserToPerm.user == user)\
601 605 .filter(UserToPerm.permission == perm).scalar() is not None
602 606
603 607 def grant_perm(self, user, perm):
604 608 """
605 609 Grant user global permissions
606 610
607 611 :param user:
608 612 :param perm:
609 613 """
610 614 user = self._get_user(user)
611 615 perm = self._get_perm(perm)
612 616 # if this permission is already granted skip it
613 617 _perm = UserToPerm.query()\
614 618 .filter(UserToPerm.user == user)\
615 619 .filter(UserToPerm.permission == perm)\
616 620 .scalar()
617 621 if _perm:
618 622 return
619 623 new = UserToPerm()
620 624 new.user = user
621 625 new.permission = perm
622 626 self.sa.add(new)
623 627
624 628 def revoke_perm(self, user, perm):
625 629 """
626 630 Revoke users global permissions
627 631
628 632 :param user:
629 633 :param perm:
630 634 """
631 635 user = self._get_user(user)
632 636 perm = self._get_perm(perm)
633 637
634 638 obj = UserToPerm.query()\
635 639 .filter(UserToPerm.user == user)\
636 640 .filter(UserToPerm.permission == perm)\
637 641 .scalar()
638 642 if obj:
639 643 self.sa.delete(obj)
640 644
641 645 def add_extra_email(self, user, email):
642 646 """
643 647 Adds email address to UserEmailMap
644 648
645 649 :param user:
646 650 :param email:
647 651 """
648 652 from rhodecode.model import forms
649 653 form = forms.UserExtraEmailForm()()
650 654 data = form.to_python(dict(email=email))
651 655 user = self._get_user(user)
652 656
653 657 obj = UserEmailMap()
654 658 obj.user = user
655 659 obj.email = data['email']
656 660 self.sa.add(obj)
657 661 return obj
658 662
659 663 def delete_extra_email(self, user, email_id):
660 664 """
661 665 Removes email address from UserEmailMap
662 666
663 667 :param user:
664 668 :param email_id:
665 669 """
666 670 user = self._get_user(user)
667 671 obj = UserEmailMap.query().get(email_id)
668 672 if obj:
669 673 self.sa.delete(obj)
@@ -1,427 +1,472 b''
1 1 import os
2 2 import unittest
3 3 from rhodecode.tests import *
4 4 from rhodecode.tests.models.common import _make_group
5 5 from rhodecode.model.repos_group import ReposGroupModel
6 6 from rhodecode.model.repo import RepoModel
7 7 from rhodecode.model.db import RepoGroup, User, UsersGroupRepoGroupToPerm
8 8 from rhodecode.model.user import UserModel
9 9
10 10 from rhodecode.model.meta import Session
11 11 from rhodecode.model.users_group import UsersGroupModel
12 12 from rhodecode.lib.auth import AuthUser
13
13 from rhodecode.tests.api.api_base import create_repo
14 14
15 15
16 16 class TestPermissions(unittest.TestCase):
17 17 def __init__(self, methodName='runTest'):
18 18 super(TestPermissions, self).__init__(methodName=methodName)
19 19
20 20 def setUp(self):
21 21 self.u1 = UserModel().create_or_update(
22 22 username=u'u1', password=u'qweqwe',
23 23 email=u'u1@rhodecode.org', firstname=u'u1', lastname=u'u1'
24 24 )
25 25 self.u2 = UserModel().create_or_update(
26 26 username=u'u2', password=u'qweqwe',
27 27 email=u'u2@rhodecode.org', firstname=u'u2', lastname=u'u2'
28 28 )
29 29 self.u3 = UserModel().create_or_update(
30 30 username=u'u3', password=u'qweqwe',
31 31 email=u'u3@rhodecode.org', firstname=u'u3', lastname=u'u3'
32 32 )
33 33 self.anon = User.get_by_username('default')
34 34 self.a1 = UserModel().create_or_update(
35 35 username=u'a1', password=u'qweqwe',
36 36 email=u'a1@rhodecode.org', firstname=u'a1', lastname=u'a1', admin=True
37 37 )
38 38 Session().commit()
39 39
40 40 def tearDown(self):
41 41 if hasattr(self, 'test_repo'):
42 42 RepoModel().delete(repo=self.test_repo)
43
43 44 UserModel().delete(self.u1)
44 45 UserModel().delete(self.u2)
45 46 UserModel().delete(self.u3)
46 47 UserModel().delete(self.a1)
47 48 if hasattr(self, 'g1'):
48 49 ReposGroupModel().delete(self.g1.group_id)
49 50 if hasattr(self, 'g2'):
50 51 ReposGroupModel().delete(self.g2.group_id)
51 52
52 53 if hasattr(self, 'ug1'):
53 54 UsersGroupModel().delete(self.ug1, force=True)
54 55
55 56 Session().commit()
56 57
57 58 def test_default_perms_set(self):
58 59 u1_auth = AuthUser(user_id=self.u1.user_id)
59 60 perms = {
60 61 'repositories_groups': {},
61 62 'global': set([u'hg.create.repository', u'repository.read',
62 63 u'hg.register.manual_activate']),
63 64 'repositories': {u'vcs_test_hg': u'repository.read'}
64 65 }
65 66 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
66 67 perms['repositories'][HG_REPO])
67 68 new_perm = 'repository.write'
68 69 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
69 70 perm=new_perm)
70 71 Session().commit()
71 72
72 73 u1_auth = AuthUser(user_id=self.u1.user_id)
73 74 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
74 75 new_perm)
75 76
76 77 def test_default_admin_perms_set(self):
77 78 a1_auth = AuthUser(user_id=self.a1.user_id)
78 79 perms = {
79 80 'repositories_groups': {},
80 81 'global': set([u'hg.admin']),
81 82 'repositories': {u'vcs_test_hg': u'repository.admin'}
82 83 }
83 84 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
84 85 perms['repositories'][HG_REPO])
85 86 new_perm = 'repository.write'
86 87 RepoModel().grant_user_permission(repo=HG_REPO, user=self.a1,
87 88 perm=new_perm)
88 89 Session().commit()
89 90 # cannot really downgrade admins permissions !? they still get's set as
90 91 # admin !
91 92 u1_auth = AuthUser(user_id=self.a1.user_id)
92 93 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
93 94 perms['repositories'][HG_REPO])
94 95
95 96 def test_default_group_perms(self):
96 97 self.g1 = _make_group('test1', skip_if_exists=True)
97 98 self.g2 = _make_group('test2', skip_if_exists=True)
98 99 u1_auth = AuthUser(user_id=self.u1.user_id)
99 100 perms = {
100 101 'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'},
101 102 'global': set([u'hg.create.repository', u'repository.read', u'hg.register.manual_activate']),
102 103 'repositories': {u'vcs_test_hg': u'repository.read'}
103 104 }
104 105 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
105 106 perms['repositories'][HG_REPO])
106 107 self.assertEqual(u1_auth.permissions['repositories_groups'],
107 108 perms['repositories_groups'])
108 109
109 110 def test_default_admin_group_perms(self):
110 111 self.g1 = _make_group('test1', skip_if_exists=True)
111 112 self.g2 = _make_group('test2', skip_if_exists=True)
112 113 a1_auth = AuthUser(user_id=self.a1.user_id)
113 114 perms = {
114 115 'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'},
115 116 'global': set(['hg.admin']),
116 117 'repositories': {u'vcs_test_hg': 'repository.admin'}
117 118 }
118 119
119 120 self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
120 121 perms['repositories'][HG_REPO])
121 122 self.assertEqual(a1_auth.permissions['repositories_groups'],
122 123 perms['repositories_groups'])
123 124
124 125 def test_propagated_permission_from_users_group_by_explicit_perms_exist(self):
125 126 # make group
126 127 self.ug1 = UsersGroupModel().create('G1')
127 128 # add user to group
128 129
129 130 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
130 131
131 132 # set permission to lower
132 133 new_perm = 'repository.none'
133 134 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
134 135 Session().commit()
135 136 u1_auth = AuthUser(user_id=self.u1.user_id)
136 137 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
137 138 new_perm)
138 139
139 140 # grant perm for group this should not override permission from user
140 141 # since it has explicitly set
141 142 new_perm_gr = 'repository.write'
142 143 RepoModel().grant_users_group_permission(repo=HG_REPO,
143 144 group_name=self.ug1,
144 145 perm=new_perm_gr)
145 146 # check perms
146 147 u1_auth = AuthUser(user_id=self.u1.user_id)
147 148 perms = {
148 149 'repositories_groups': {},
149 150 'global': set([u'hg.create.repository', u'repository.read',
150 151 u'hg.register.manual_activate']),
151 152 'repositories': {u'vcs_test_hg': u'repository.read'}
152 153 }
153 154 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
154 155 new_perm)
155 156 self.assertEqual(u1_auth.permissions['repositories_groups'],
156 157 perms['repositories_groups'])
157 158
158 159 def test_propagated_permission_from_users_group(self):
159 160 # make group
160 161 self.ug1 = UsersGroupModel().create('G1')
161 162 # add user to group
162 163
163 164 UsersGroupModel().add_user_to_group(self.ug1, self.u3)
164 165
165 166 # grant perm for group this should override default permission from user
166 167 new_perm_gr = 'repository.write'
167 168 RepoModel().grant_users_group_permission(repo=HG_REPO,
168 169 group_name=self.ug1,
169 170 perm=new_perm_gr)
170 171 # check perms
171 172 u3_auth = AuthUser(user_id=self.u3.user_id)
172 173 perms = {
173 174 'repositories_groups': {},
174 175 'global': set([u'hg.create.repository', u'repository.read',
175 176 u'hg.register.manual_activate']),
176 177 'repositories': {u'vcs_test_hg': u'repository.read'}
177 178 }
178 179 self.assertEqual(u3_auth.permissions['repositories'][HG_REPO],
179 180 new_perm_gr)
180 181 self.assertEqual(u3_auth.permissions['repositories_groups'],
181 182 perms['repositories_groups'])
182 183
183 184 def test_propagated_permission_from_users_group_lower_weight(self):
184 185 # make group
185 186 self.ug1 = UsersGroupModel().create('G1')
186 187 # add user to group
187 188 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
188 189
189 190 # set permission to lower
190 191 new_perm_h = 'repository.write'
191 192 RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
192 193 perm=new_perm_h)
193 194 Session().commit()
194 195 u1_auth = AuthUser(user_id=self.u1.user_id)
195 196 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
196 197 new_perm_h)
197 198
198 199 # grant perm for group this should NOT override permission from user
199 200 # since it's lower than granted
200 201 new_perm_l = 'repository.read'
201 202 RepoModel().grant_users_group_permission(repo=HG_REPO,
202 203 group_name=self.ug1,
203 204 perm=new_perm_l)
204 205 # check perms
205 206 u1_auth = AuthUser(user_id=self.u1.user_id)
206 207 perms = {
207 208 'repositories_groups': {},
208 209 'global': set([u'hg.create.repository', u'repository.read',
209 210 u'hg.register.manual_activate']),
210 211 'repositories': {u'vcs_test_hg': u'repository.write'}
211 212 }
212 213 self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
213 214 new_perm_h)
214 215 self.assertEqual(u1_auth.permissions['repositories_groups'],
215 216 perms['repositories_groups'])
216 217
217 218 def test_repo_in_group_permissions(self):
218 219 self.g1 = _make_group('group1', skip_if_exists=True)
219 220 self.g2 = _make_group('group2', skip_if_exists=True)
220 221 Session().commit()
221 222 # both perms should be read !
222 223 u1_auth = AuthUser(user_id=self.u1.user_id)
223 224 self.assertEqual(u1_auth.permissions['repositories_groups'],
224 225 {u'group1': u'group.read', u'group2': u'group.read'})
225 226
226 227 a1_auth = AuthUser(user_id=self.anon.user_id)
227 228 self.assertEqual(a1_auth.permissions['repositories_groups'],
228 229 {u'group1': u'group.read', u'group2': u'group.read'})
229 230
230 231 #Change perms to none for both groups
231 232 ReposGroupModel().grant_user_permission(repos_group=self.g1,
232 233 user=self.anon,
233 234 perm='group.none')
234 235 ReposGroupModel().grant_user_permission(repos_group=self.g2,
235 236 user=self.anon,
236 237 perm='group.none')
237 238
238 239 u1_auth = AuthUser(user_id=self.u1.user_id)
239 240 self.assertEqual(u1_auth.permissions['repositories_groups'],
240 241 {u'group1': u'group.none', u'group2': u'group.none'})
241 242
242 243 a1_auth = AuthUser(user_id=self.anon.user_id)
243 244 self.assertEqual(a1_auth.permissions['repositories_groups'],
244 245 {u'group1': u'group.none', u'group2': u'group.none'})
245 246
246 247 # add repo to group
247 248 name = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm'])
248 249 self.test_repo = RepoModel().create_repo(
249 250 repo_name=name,
250 251 repo_type='hg',
251 252 description='',
252 253 repos_group=self.g1,
253 254 owner=self.u1,
254 255 )
255 256 Session().commit()
256 257
257 258 u1_auth = AuthUser(user_id=self.u1.user_id)
258 259 self.assertEqual(u1_auth.permissions['repositories_groups'],
259 260 {u'group1': u'group.none', u'group2': u'group.none'})
260 261
261 262 a1_auth = AuthUser(user_id=self.anon.user_id)
262 263 self.assertEqual(a1_auth.permissions['repositories_groups'],
263 264 {u'group1': u'group.none', u'group2': u'group.none'})
264 265
265 266 #grant permission for u2 !
266 267 ReposGroupModel().grant_user_permission(repos_group=self.g1,
267 268 user=self.u2,
268 269 perm='group.read')
269 270 ReposGroupModel().grant_user_permission(repos_group=self.g2,
270 271 user=self.u2,
271 272 perm='group.read')
272 273 Session().commit()
273 274 self.assertNotEqual(self.u1, self.u2)
274 275 #u1 and anon should have not change perms while u2 should !
275 276 u1_auth = AuthUser(user_id=self.u1.user_id)
276 277 self.assertEqual(u1_auth.permissions['repositories_groups'],
277 278 {u'group1': u'group.none', u'group2': u'group.none'})
278 279
279 280 u2_auth = AuthUser(user_id=self.u2.user_id)
280 281 self.assertEqual(u2_auth.permissions['repositories_groups'],
281 282 {u'group1': u'group.read', u'group2': u'group.read'})
282 283
283 284 a1_auth = AuthUser(user_id=self.anon.user_id)
284 285 self.assertEqual(a1_auth.permissions['repositories_groups'],
285 286 {u'group1': u'group.none', u'group2': u'group.none'})
286 287
287 288 def test_repo_group_user_as_user_group_member(self):
288 289 # create Group1
289 290 self.g1 = _make_group('group1', skip_if_exists=True)
290 291 Session().commit()
291 292 a1_auth = AuthUser(user_id=self.anon.user_id)
292 293
293 294 self.assertEqual(a1_auth.permissions['repositories_groups'],
294 295 {u'group1': u'group.read'})
295 296
296 297 # set default permission to none
297 298 ReposGroupModel().grant_user_permission(repos_group=self.g1,
298 299 user=self.anon,
299 300 perm='group.none')
300 301 # make group
301 302 self.ug1 = UsersGroupModel().create('G1')
302 303 # add user to group
303 304 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
304 305 Session().commit()
305 306
306 307 # check if user is in the group
307 308 membrs = [x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members]
308 309 self.assertEqual(membrs, [self.u1.user_id])
309 310 # add some user to that group
310 311
311 312 # check his permissions
312 313 a1_auth = AuthUser(user_id=self.anon.user_id)
313 314 self.assertEqual(a1_auth.permissions['repositories_groups'],
314 315 {u'group1': u'group.none'})
315 316
316 317 u1_auth = AuthUser(user_id=self.u1.user_id)
317 318 self.assertEqual(u1_auth.permissions['repositories_groups'],
318 319 {u'group1': u'group.none'})
319 320
320 321 # grant ug1 read permissions for
321 322 ReposGroupModel().grant_users_group_permission(repos_group=self.g1,
322 323 group_name=self.ug1,
323 324 perm='group.read')
324 325 Session().commit()
325 326 # check if the
326 327 obj = Session().query(UsersGroupRepoGroupToPerm)\
327 328 .filter(UsersGroupRepoGroupToPerm.group == self.g1)\
328 329 .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\
329 330 .scalar()
330 331 self.assertEqual(obj.permission.permission_name, 'group.read')
331 332
332 333 a1_auth = AuthUser(user_id=self.anon.user_id)
333 334
334 335 self.assertEqual(a1_auth.permissions['repositories_groups'],
335 336 {u'group1': u'group.none'})
336 337
337 338 u1_auth = AuthUser(user_id=self.u1.user_id)
338 339 self.assertEqual(u1_auth.permissions['repositories_groups'],
339 340 {u'group1': u'group.read'})
340 341
341 342 def test_inherited_permissions_from_default_on_user_enabled(self):
342 343 user_model = UserModel()
343 344 # enable fork and create on default user
344 345 usr = 'default'
345 346 user_model.revoke_perm(usr, 'hg.create.none')
346 347 user_model.grant_perm(usr, 'hg.create.repository')
347 348 user_model.revoke_perm(usr, 'hg.fork.none')
348 349 user_model.grant_perm(usr, 'hg.fork.repository')
349 350 # make sure inherit flag is turned on
350 351 self.u1.inherit_default_permissions = True
351 352 Session().commit()
352 353 u1_auth = AuthUser(user_id=self.u1.user_id)
353 354 # this user will have inherited permissions from default user
354 355 self.assertEqual(u1_auth.permissions['global'],
355 356 set(['hg.create.repository', 'hg.fork.repository',
356 357 'hg.register.manual_activate',
357 358 'repository.read']))
358 359
359 360 def test_inherited_permissions_from_default_on_user_disabled(self):
360 361 user_model = UserModel()
361 362 # disable fork and create on default user
362 363 usr = 'default'
363 364 user_model.revoke_perm(usr, 'hg.create.repository')
364 365 user_model.grant_perm(usr, 'hg.create.none')
365 366 user_model.revoke_perm(usr, 'hg.fork.repository')
366 367 user_model.grant_perm(usr, 'hg.fork.none')
367 368 # make sure inherit flag is turned on
368 369 self.u1.inherit_default_permissions = True
369 370 Session().commit()
370 371 u1_auth = AuthUser(user_id=self.u1.user_id)
371 372 # this user will have inherited permissions from default user
372 373 self.assertEqual(u1_auth.permissions['global'],
373 374 set(['hg.create.none', 'hg.fork.none',
374 375 'hg.register.manual_activate',
375 376 'repository.read']))
376 377
377 378 def test_non_inherited_permissions_from_default_on_user_enabled(self):
378 379 user_model = UserModel()
379 380 # enable fork and create on default user
380 381 usr = 'default'
381 382 user_model.revoke_perm(usr, 'hg.create.none')
382 383 user_model.grant_perm(usr, 'hg.create.repository')
383 384 user_model.revoke_perm(usr, 'hg.fork.none')
384 385 user_model.grant_perm(usr, 'hg.fork.repository')
385 386
386 387 #disable global perms on specific user
387 388 user_model.revoke_perm(self.u1, 'hg.create.repository')
388 389 user_model.grant_perm(self.u1, 'hg.create.none')
389 390 user_model.revoke_perm(self.u1, 'hg.fork.repository')
390 391 user_model.grant_perm(self.u1, 'hg.fork.none')
391 392
392 393 # make sure inherit flag is turned off
393 394 self.u1.inherit_default_permissions = False
394 395 Session().commit()
395 396 u1_auth = AuthUser(user_id=self.u1.user_id)
396 397 # this user will have non inherited permissions from he's
397 398 # explicitly set permissions
398 399 self.assertEqual(u1_auth.permissions['global'],
399 400 set(['hg.create.none', 'hg.fork.none',
400 401 'hg.register.manual_activate',
401 402 'repository.read']))
402 403
403 404 def test_non_inherited_permissions_from_default_on_user_disabled(self):
404 405 user_model = UserModel()
405 406 # disable fork and create on default user
406 407 usr = 'default'
407 408 user_model.revoke_perm(usr, 'hg.create.repository')
408 409 user_model.grant_perm(usr, 'hg.create.none')
409 410 user_model.revoke_perm(usr, 'hg.fork.repository')
410 411 user_model.grant_perm(usr, 'hg.fork.none')
411 412
412 413 #enable global perms on specific user
413 414 user_model.revoke_perm(self.u1, 'hg.create.none')
414 415 user_model.grant_perm(self.u1, 'hg.create.repository')
415 416 user_model.revoke_perm(self.u1, 'hg.fork.none')
416 417 user_model.grant_perm(self.u1, 'hg.fork.repository')
417 418
418 419 # make sure inherit flag is turned off
419 420 self.u1.inherit_default_permissions = False
420 421 Session().commit()
421 422 u1_auth = AuthUser(user_id=self.u1.user_id)
422 423 # this user will have non inherited permissions from he's
423 424 # explicitly set permissions
424 425 self.assertEqual(u1_auth.permissions['global'],
425 426 set(['hg.create.repository', 'hg.fork.repository',
426 427 'hg.register.manual_activate',
427 428 'repository.read']))
429
430 def test_owner_permissions_doesnot_get_overwritten_by_group(self):
431 #create repo as USER,
432 self.test_repo = repo = RepoModel().create_repo(repo_name='myownrepo',
433 repo_type='hg',
434 description='desc',
435 owner=self.u1)
436
437 Session().commit()
438 #he has permissions of admin as owner
439 u1_auth = AuthUser(user_id=self.u1.user_id)
440 self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
441 'repository.admin')
442 #set his permission as users group, he should still be admin
443 self.ug1 = UsersGroupModel().create('G1')
444 # add user to group
445 UsersGroupModel().add_user_to_group(self.ug1, self.u1)
446 RepoModel().grant_users_group_permission(repo, group_name=self.ug1,
447 perm='repository.none')
448
449 Session().commit()
450 u1_auth = AuthUser(user_id=self.u1.user_id)
451 self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
452 'repository.admin')
453
454 def test_owner_permissions_doesnot_get_overwritten_by_others(self):
455 #create repo as USER,
456 self.test_repo = repo = RepoModel().create_repo(repo_name='myownrepo',
457 repo_type='hg',
458 description='desc',
459 owner=self.u1)
460
461 Session().commit()
462 #he has permissions of admin as owner
463 u1_auth = AuthUser(user_id=self.u1.user_id)
464 self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
465 'repository.admin')
466 #set his permission as user, he should still be admin
467 RepoModel().grant_user_permission(repo, user=self.u1,
468 perm='repository.none')
469 Session().commit()
470 u1_auth = AuthUser(user_id=self.u1.user_id)
471 self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
472 'repository.admin')
General Comments 0
You need to be logged in to leave comments. Login now