Files @ aaa7c3331186
Branch filter:

Location: kallithea/rhodecode/lib/auth.py - annotation

Bradley M. Kuhn
Rename paster command setup-rhodecode to setup-db
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
62c04c5cc971
a671db5bdd58
a671db5bdd58
a671db5bdd58
a671db5bdd58
6832ef664673
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
6832ef664673
1e757ac98988
a671db5bdd58
ffd45b185016
ffd45b185016
ffd45b185016
1e757ac98988
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
62c04c5cc971
62c04c5cc971
62c04c5cc971
716911af91e1
ffd45b185016
ffd45b185016
b0e2c949c34b
716911af91e1
62c04c5cc971
62c04c5cc971
ffd45b185016
1e757ac98988
520d27f40b51
ffd45b185016
6c28533d122c
ffd45b185016
62c04c5cc971
4b17216f2110
ffd45b185016
ffd45b185016
8ecc6b8229a5
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
b0e2c949c34b
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
62c04c5cc971
ffd45b185016
62c04c5cc971
9365a893ad4e
1e757ac98988
1e757ac98988
1e757ac98988
7d1fc253549e
cf51bbfb120e
7d1fc253549e
7d1fc253549e
7d1fc253549e
1e757ac98988
9365a893ad4e
9365a893ad4e
24095abde696
1e757ac98988
9365a893ad4e
9365a893ad4e
9365a893ad4e
9365a893ad4e
9365a893ad4e
9365a893ad4e
9365a893ad4e
1e757ac98988
9365a893ad4e
9365a893ad4e
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
4d3179d2adfe
4d3179d2adfe
4d3179d2adfe
87f0800abc7b
1e757ac98988
1e757ac98988
9365a893ad4e
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
6832ef664673
b0e2c949c34b
b0e2c949c34b
4b17216f2110
9225597688f4
b0e2c949c34b
4b17216f2110
9225597688f4
b0e2c949c34b
b0e2c949c34b
9365a893ad4e
9365a893ad4e
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
6832ef664673
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
b0e2c949c34b
4b17216f2110
9225597688f4
b0e2c949c34b
4b17216f2110
9225597688f4
b0e2c949c34b
b0e2c949c34b
9365a893ad4e
9365a893ad4e
b0e2c949c34b
dd532af216d9
1e757ac98988
b0e2c949c34b
b0e2c949c34b
9365a893ad4e
b0e2c949c34b
b0e2c949c34b
1e757ac98988
4ae17f819ee8
de71a4bde097
de71a4bde097
de71a4bde097
cf51bbfb120e
de71a4bde097
de71a4bde097
de71a4bde097
f78bee8eec78
716911af91e1
716911af91e1
716911af91e1
de71a4bde097
716911af91e1
9365a893ad4e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
6eb5bb24a948
6eb5bb24a948
6832ef664673
6eb5bb24a948
6832ef664673
ffd45b185016
1e757ac98988
3790279d2538
9b92cf5a0cca
6eb5bb24a948
6eb5bb24a948
ffd45b185016
ffd45b185016
a8d759613d8f
cf128ced8c85
9b92cf5a0cca
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
6eb5bb24a948
a2eaa0054430
ffd45b185016
6eb5bb24a948
4ae17f819ee8
6eb5bb24a948
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
6eb5bb24a948
6eb5bb24a948
ffd45b185016
6cab36e31f09
f78bee8eec78
cf51bbfb120e
ffd45b185016
a76e9bacbedc
9353189b7675
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ff788e390497
ffd45b185016
a76e9bacbedc
ffd45b185016
5b12cbae0b50
5b12cbae0b50
6cab36e31f09
6cab36e31f09
de71a4bde097
260a7a01b054
f78bee8eec78
de71a4bde097
6cab36e31f09
6eb5bb24a948
9353189b7675
9353189b7675
6cab36e31f09
6eb5bb24a948
cf128ced8c85
cf128ced8c85
cf128ced8c85
a76e9bacbedc
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
1e757ac98988
c5169e445fb8
100be6988bb0
199fd214b213
199fd214b213
199fd214b213
199fd214b213
199fd214b213
199fd214b213
199fd214b213
7e3d89d9d3a2
199fd214b213
b8f929bff7e3
199fd214b213
199fd214b213
199fd214b213
199fd214b213
199fd214b213
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
c5169e445fb8
c5169e445fb8
c5169e445fb8
c5169e445fb8
c5169e445fb8
c5169e445fb8
c5169e445fb8
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
c5169e445fb8
c5169e445fb8
c5169e445fb8
ffd45b185016
c5169e445fb8
c5169e445fb8
dd532af216d9
ddd05df2aced
ddd05df2aced
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
f78bee8eec78
4ae17f819ee8
f78bee8eec78
4ae17f819ee8
f78bee8eec78
f78bee8eec78
f78bee8eec78
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
61f9aeb2129e
f78bee8eec78
f78bee8eec78
f78bee8eec78
f78bee8eec78
1e757ac98988
9b92cf5a0cca
ffd45b185016
9b92cf5a0cca
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
c5169e445fb8
c5169e445fb8
c5169e445fb8
c5169e445fb8
ffd45b185016
9b92cf5a0cca
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
9b92cf5a0cca
4ae17f819ee8
1e757ac98988
de71a4bde097
de71a4bde097
6832ef664673
1e757ac98988
1e757ac98988
6832ef664673
62c04c5cc971
6832ef664673
1e757ac98988
1e757ac98988
1e757ac98988
8ecc6b8229a5
1e757ac98988
669721d1fe65
4ae17f819ee8
669721d1fe65
1e757ac98988
1e757ac98988
dd532af216d9
9365a893ad4e
9365a893ad4e
1e757ac98988
9365a893ad4e
1e757ac98988
6eb5bb24a948
6832ef664673
6eb5bb24a948
6832ef664673
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
6eb5bb24a948
dd532af216d9
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
6eb5bb24a948
6eb5bb24a948
c5169e445fb8
ffd45b185016
ffd45b185016
ffd45b185016
c5169e445fb8
c5169e445fb8
c5169e445fb8
c5169e445fb8
ffd45b185016
6eb5bb24a948
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
a76e9bacbedc
ffd45b185016
ffd45b185016
ffd45b185016
6eb5bb24a948
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
c5169e445fb8
7e979933ffec
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
7e979933ffec
1e757ac98988
1e757ac98988
ffd45b185016
ffd45b185016
ffd45b185016
7e979933ffec
e61b7ba293db
dd532af216d9
a76e9bacbedc
1e757ac98988
1e757ac98988
9365a893ad4e
389d02a5df52
7d1fc253549e
7d1fc253549e
389d02a5df52
389d02a5df52
389d02a5df52
389d02a5df52
389d02a5df52
389d02a5df52
6eb5bb24a948
6eb5bb24a948
389d02a5df52
a76e9bacbedc
6eb5bb24a948
ffd45b185016
389d02a5df52
389d02a5df52
40c8d18102a9
520d27f40b51
520d27f40b51
9365a893ad4e
9365a893ad4e
520d27f40b51
389d02a5df52
389d02a5df52
389d02a5df52
389d02a5df52
9365a893ad4e
1e757ac98988
6eb5bb24a948
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
6eb5bb24a948
6eb5bb24a948
dd532af216d9
dd532af216d9
097327aaf2ad
1e757ac98988
1e757ac98988
a76e9bacbedc
1e757ac98988
dd532af216d9
1e757ac98988
7e979933ffec
ffd45b185016
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
e9fe4ff57cbb
de71a4bde097
e9fe4ff57cbb
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
9365a893ad4e
1e757ac98988
7d1fc253549e
7d1fc253549e
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
7d1fc253549e
7d1fc253549e
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
9365a893ad4e
1e757ac98988
7d1fc253549e
7d1fc253549e
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
7d1fc253549e
7d1fc253549e
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
097327aaf2ad
1e757ac98988
1e757ac98988
1e757ac98988
9365a893ad4e
9365a893ad4e
ffd45b185016
87f0800abc7b
87f0800abc7b
7e3d89d9d3a2
87f0800abc7b
87f0800abc7b
87f0800abc7b
ffd45b185016
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
b4daef4cc26d
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
ffd45b185016
87f0800abc7b
87f0800abc7b
7e3d89d9d3a2
87f0800abc7b
87f0800abc7b
87f0800abc7b
ffd45b185016
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
b4daef4cc26d
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
9365a893ad4e
1e757ac98988
9365a893ad4e
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
097327aaf2ad
dd532af216d9
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
097327aaf2ad
097327aaf2ad
097327aaf2ad
097327aaf2ad
097327aaf2ad
097327aaf2ad
ffd45b185016
ffd45b185016
097327aaf2ad
097327aaf2ad
097327aaf2ad
14697de1598f
1e757ac98988
5b12cbae0b50
1e757ac98988
1e757ac98988
1e757ac98988
ffd45b185016
ffd45b185016
ffd45b185016
1e757ac98988
dd532af216d9
1e757ac98988
ffd45b185016
ffd45b185016
ffd45b185016
dd532af216d9
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
dd532af216d9
9365a893ad4e
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
9365a893ad4e
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
9365a893ad4e
1e757ac98988
ffd45b185016
1e757ac98988
ffd45b185016
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
097327aaf2ad
87f0800abc7b
87f0800abc7b
1e757ac98988
1e757ac98988
097327aaf2ad
1e757ac98988
1e757ac98988
dd532af216d9
9365a893ad4e
1e757ac98988
ffd45b185016
1e757ac98988
ffd45b185016
dd532af216d9
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
1e757ac98988
097327aaf2ad
87f0800abc7b
87f0800abc7b
1e757ac98988
1e757ac98988
097327aaf2ad
1e757ac98988
1e757ac98988
1e757ac98988
9365a893ad4e
ffd45b185016
ffd45b185016
87f0800abc7b
ffd45b185016
87f0800abc7b
87f0800abc7b
87f0800abc7b
097327aaf2ad
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
097327aaf2ad
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
ffd45b185016
ffd45b185016
87f0800abc7b
ffd45b185016
87f0800abc7b
87f0800abc7b
87f0800abc7b
097327aaf2ad
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
097327aaf2ad
87f0800abc7b
87f0800abc7b
87f0800abc7b
87f0800abc7b
7e3d89d9d3a2
ffd45b185016
7e3d89d9d3a2
ffd45b185016
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
ffd45b185016
7e3d89d9d3a2
ffd45b185016
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
7e3d89d9d3a2
ffd45b185016
9365a893ad4e
1e757ac98988
9365a893ad4e
1e757ac98988
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
f0649c7cf94a
f0649c7cf94a
f0649c7cf94a
6eb5bb24a948
1e757ac98988
6eb5bb24a948
f0649c7cf94a
8ecfed1d8f8b
f0649c7cf94a
1e757ac98988
1e757ac98988
dd532af216d9
1e757ac98988
dd532af216d9
1e757ac98988
aa17c7a1b8a5
8e49b6ceffe1
1e757ac98988
1e757ac98988
ffd45b185016
ffd45b185016
1e757ac98988
ffd45b185016
ffd45b185016
1e757ac98988
9b92cf5a0cca
9b92cf5a0cca
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
ffd45b185016
3563c47e52fd
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
ffd45b185016
3563c47e52fd
3563c47e52fd
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
3563c47e52fd
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
3563c47e52fd
ffd45b185016
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
3563c47e52fd
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
9b92cf5a0cca
6c28533d122c
6c28533d122c
ffd45b185016
ffd45b185016
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
6c28533d122c
9b92cf5a0cca
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
rhodecode.lib.auth
~~~~~~~~~~~~~~~~~~

authentication and permission libraries

:created_on: Apr 4, 2010
:author: marcink
:copyright: (c) 2013 RhodeCode GmbH.
:license: GPLv3, see LICENSE for more details.
"""
from __future__ import with_statement
import time
import random
import logging
import traceback
import hashlib
import itertools
import collections

from tempfile import _RandomNameSequence
from decorator import decorator

from pylons import url, request
from pylons.controllers.util import abort, redirect
from pylons.i18n.translation import _
from sqlalchemy import or_
from sqlalchemy.orm.exc import ObjectDeletedError
from sqlalchemy.orm import joinedload

from rhodecode import __platform__, is_windows, is_unix
from rhodecode.lib.vcs.utils.lazy import LazyProperty
from rhodecode.model import meta
from rhodecode.model.meta import Session
from rhodecode.model.user import UserModel
from rhodecode.model.db import User, Repository, Permission, \
    UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
    RepoGroup, UserGroupRepoGroupToPerm, UserIpMap, UserGroupUserGroupToPerm, \
    UserGroup, UserApiKeys

from rhodecode.lib.utils2 import safe_unicode, aslist
from rhodecode.lib.utils import get_repo_slug, get_repo_group_slug, \
    get_user_group_slug, conditional_cache
from rhodecode.lib.caching_query import FromCache

from beaker.cache import cache_region

log = logging.getLogger(__name__)


class PasswordGenerator(object):
    """
    This is a simple class for generating password from different sets of
    characters
    usage::

        passwd_gen = PasswordGenerator()
        #print 8-letter password containing only big and small letters
            of alphabet
        passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
    """
    ALPHABETS_NUM = r'''1234567890'''
    ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''
    ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''
    ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''
    ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL \
        + ALPHABETS_NUM + ALPHABETS_SPECIAL
    ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM
    ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
    ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM
    ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM

    def __init__(self, passwd=''):
        self.passwd = passwd

    def gen_password(self, length, type_=None):
        if type_ is None:
            type_ = self.ALPHABETS_FULL
        self.passwd = ''.join([random.choice(type_) for _ in xrange(length)])
        return self.passwd


class RhodeCodeCrypto(object):

    @classmethod
    def hash_string(cls, str_):
        """
        Cryptographic function used for password hashing based on pybcrypt
        or pycrypto in windows

        :param password: password to hash
        """
        if is_windows:
            from hashlib import sha256
            return sha256(str_).hexdigest()
        elif is_unix:
            import bcrypt
            return bcrypt.hashpw(str_, bcrypt.gensalt(10))
        else:
            raise Exception('Unknown or unsupported platform %s' \
                            % __platform__)

    @classmethod
    def hash_check(cls, password, hashed):
        """
        Checks matching password with it's hashed value, runs different
        implementation based on platform it runs on

        :param password: password
        :param hashed: password in hashed form
        """

        if is_windows:
            from hashlib import sha256
            return sha256(password).hexdigest() == hashed
        elif is_unix:
            import bcrypt
            return bcrypt.hashpw(password, hashed) == hashed
        else:
            raise Exception('Unknown or unsupported platform %s' \
                            % __platform__)


def get_crypt_password(password):
    return RhodeCodeCrypto.hash_string(password)


def check_password(password, hashed):
    return RhodeCodeCrypto.hash_check(password, hashed)


def generate_api_key(str_, salt=None):
    """
    Generates API KEY from given string

    :param str_:
    :param salt:
    """

    if salt is None:
        salt = _RandomNameSequence().next()

    return hashlib.sha1(str_ + salt).hexdigest()


class CookieStoreWrapper(object):

    def __init__(self, cookie_store):
        self.cookie_store = cookie_store

    def __repr__(self):
        return 'CookieStore<%s>' % (self.cookie_store)

    def get(self, key, other=None):
        if isinstance(self.cookie_store, dict):
            return self.cookie_store.get(key, other)
        elif isinstance(self.cookie_store, AuthUser):
            return self.cookie_store.__dict__.get(key, other)



def _cached_perms_data(user_id, user_is_admin, user_inherit_default_permissions,
                       explicit, algo):
    RK = 'repositories'
    GK = 'repositories_groups'
    UK = 'user_groups'
    GLOBAL = 'global'
    PERM_WEIGHTS = Permission.PERM_WEIGHTS
    permissions = {RK: {}, GK: {}, UK: {}, GLOBAL: set()}

    def _choose_perm(new_perm, cur_perm):
        new_perm_val = PERM_WEIGHTS[new_perm]
        cur_perm_val = PERM_WEIGHTS[cur_perm]
        if algo == 'higherwin':
            if new_perm_val > cur_perm_val:
                return new_perm
            return cur_perm
        elif algo == 'lowerwin':
            if new_perm_val < cur_perm_val:
                return new_perm
            return cur_perm

    #======================================================================
    # fetch default permissions
    #======================================================================
    default_user = User.get_by_username('default', cache=True)
    default_user_id = default_user.user_id

    default_repo_perms = Permission.get_default_perms(default_user_id)
    default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
    default_user_group_perms = Permission.get_default_user_group_perms(default_user_id)

    if user_is_admin:
        #==================================================================
        # admin user have all default rights for repositories
        # and groups set to admin
        #==================================================================
        permissions[GLOBAL].add('hg.admin')
        permissions[GLOBAL].add('hg.create.write_on_repogroup.true')

        # repositories
        for perm in default_repo_perms:
            r_k = perm.UserRepoToPerm.repository.repo_name
            p = 'repository.admin'
            permissions[RK][r_k] = p

        # repository groups
        for perm in default_repo_groups_perms:
            rg_k = perm.UserRepoGroupToPerm.group.group_name
            p = 'group.admin'
            permissions[GK][rg_k] = p

        # user groups
        for perm in default_user_group_perms:
            u_k = perm.UserUserGroupToPerm.user_group.users_group_name
            p = 'usergroup.admin'
            permissions[UK][u_k] = p
        return permissions

    #==================================================================
    # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS
    #==================================================================
    uid = user_id

    # default global permissions taken fron the default user
    default_global_perms = UserToPerm.query()\
        .filter(UserToPerm.user_id == default_user_id)\
        .options(joinedload(UserToPerm.permission))

    for perm in default_global_perms:
        permissions[GLOBAL].add(perm.permission.permission_name)

    # defaults for repositories, taken from default user
    for perm in default_repo_perms:
        r_k = perm.UserRepoToPerm.repository.repo_name
        if perm.Repository.private and not (perm.Repository.user_id == uid):
            # disable defaults for private repos,
            p = 'repository.none'
        elif perm.Repository.user_id == uid:
            # set admin if owner
            p = 'repository.admin'
        else:
            p = perm.Permission.permission_name

        permissions[RK][r_k] = p

    # defaults for repository groups taken from default user permission
    # on given group
    for perm in default_repo_groups_perms:
        rg_k = perm.UserRepoGroupToPerm.group.group_name
        p = perm.Permission.permission_name
        permissions[GK][rg_k] = p

    # defaults for user groups taken from default user permission
    # on given user group
    for perm in default_user_group_perms:
        u_k = perm.UserUserGroupToPerm.user_group.users_group_name
        p = perm.Permission.permission_name
        permissions[UK][u_k] = p

    #======================================================================
    # !! OVERRIDE GLOBALS !! with user permissions if any found
    #======================================================================
    # those can be configured from groups or users explicitly
    _configurable = set([
        'hg.fork.none', 'hg.fork.repository',
        'hg.create.none', 'hg.create.repository',
        'hg.usergroup.create.false', 'hg.usergroup.create.true'
    ])

    # USER GROUPS comes first
    # user group global permissions
    user_perms_from_users_groups = Session().query(UserGroupToPerm)\
        .options(joinedload(UserGroupToPerm.permission))\
        .join((UserGroupMember, UserGroupToPerm.users_group_id ==
               UserGroupMember.users_group_id))\
        .filter(UserGroupMember.user_id == uid)\
        .order_by(UserGroupToPerm.users_group_id)\
        .all()
    # need to group here by groups since user can be in more than
    # one group
    _grouped = [[x, list(y)] for x, y in
                itertools.groupby(user_perms_from_users_groups,
                                  lambda x:x.users_group)]
    for gr, perms in _grouped:
        # since user can be in multiple groups iterate over them and
        # select the lowest permissions first (more explicit)
        ##TODO: do this^^
        if not gr.inherit_default_permissions:
            # NEED TO IGNORE all configurable permissions and
            # replace them with explicitly set
            permissions[GLOBAL] = permissions[GLOBAL]\
                                            .difference(_configurable)
        for perm in perms:
            permissions[GLOBAL].add(perm.permission.permission_name)

    # user specific global permissions
    user_perms = Session().query(UserToPerm)\
            .options(joinedload(UserToPerm.permission))\
            .filter(UserToPerm.user_id == uid).all()

    if not user_inherit_default_permissions:
        # NEED TO IGNORE all configurable permissions and
        # replace them with explicitly set
        permissions[GLOBAL] = permissions[GLOBAL]\
                                        .difference(_configurable)

        for perm in user_perms:
            permissions[GLOBAL].add(perm.permission.permission_name)
    ## END GLOBAL PERMISSIONS

    #======================================================================
    # !! PERMISSIONS FOR REPOSITORIES !!
    #======================================================================
    #======================================================================
    # check if user is part of user groups for this repository and
    # fill in his permission from it. _choose_perm decides of which
    # permission should be selected based on selected method
    #======================================================================

    # user group for repositories permissions
    user_repo_perms_from_users_groups = \
     Session().query(UserGroupRepoToPerm, Permission, Repository,)\
        .join((Repository, UserGroupRepoToPerm.repository_id ==
               Repository.repo_id))\
        .join((Permission, UserGroupRepoToPerm.permission_id ==
               Permission.permission_id))\
        .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
               UserGroupMember.users_group_id))\
        .filter(UserGroupMember.user_id == uid)\
        .all()

    multiple_counter = collections.defaultdict(int)
    for perm in user_repo_perms_from_users_groups:
        r_k = perm.UserGroupRepoToPerm.repository.repo_name
        multiple_counter[r_k] += 1
        p = perm.Permission.permission_name
        cur_perm = permissions[RK][r_k]

        if perm.Repository.user_id == uid:
            # set admin if owner
            p = 'repository.admin'
        else:
            if multiple_counter[r_k] > 1:
                p = _choose_perm(p, cur_perm)
        permissions[RK][r_k] = p

    # user explicit permissions for repositories, overrides any specified
    # by the group permission
    user_repo_perms = Permission.get_default_perms(uid)
    for perm in user_repo_perms:
        r_k = perm.UserRepoToPerm.repository.repo_name
        cur_perm = permissions[RK][r_k]
        # set admin if owner
        if perm.Repository.user_id == uid:
            p = 'repository.admin'
        else:
            p = perm.Permission.permission_name
            if not explicit:
                p = _choose_perm(p, cur_perm)
        permissions[RK][r_k] = p

    #======================================================================
    # !! PERMISSIONS FOR REPOSITORY GROUPS !!
    #======================================================================
    #======================================================================
    # check if user is part of user groups for this repository groups and
    # fill in his permission from it. _choose_perm decides of which
    # permission should be selected based on selected method
    #======================================================================
    # user group for repo groups permissions
    user_repo_group_perms_from_users_groups = \
     Session().query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
     .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
     .join((Permission, UserGroupRepoGroupToPerm.permission_id
            == Permission.permission_id))\
     .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
            == UserGroupMember.users_group_id))\
     .filter(UserGroupMember.user_id == uid)\
     .all()

    multiple_counter = collections.defaultdict(int)
    for perm in user_repo_group_perms_from_users_groups:
        g_k = perm.UserGroupRepoGroupToPerm.group.group_name
        multiple_counter[g_k] += 1
        p = perm.Permission.permission_name
        cur_perm = permissions[GK][g_k]
        if multiple_counter[g_k] > 1:
            p = _choose_perm(p, cur_perm)
        permissions[GK][g_k] = p

    # user explicit permissions for repository groups
    user_repo_groups_perms = Permission.get_default_group_perms(uid)
    for perm in user_repo_groups_perms:
        rg_k = perm.UserRepoGroupToPerm.group.group_name
        p = perm.Permission.permission_name
        cur_perm = permissions[GK][rg_k]
        if not explicit:
            p = _choose_perm(p, cur_perm)
        permissions[GK][rg_k] = p

    #======================================================================
    # !! PERMISSIONS FOR USER GROUPS !!
    #======================================================================
    # user group for user group permissions
    user_group_user_groups_perms = \
     Session().query(UserGroupUserGroupToPerm, Permission, UserGroup)\
     .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id
            == UserGroup.users_group_id))\
     .join((Permission, UserGroupUserGroupToPerm.permission_id
            == Permission.permission_id))\
     .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id
            == UserGroupMember.users_group_id))\
     .filter(UserGroupMember.user_id == uid)\
     .all()

    multiple_counter = collections.defaultdict(int)
    for perm in user_group_user_groups_perms:
        g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name
        multiple_counter[g_k] += 1
        p = perm.Permission.permission_name
        cur_perm = permissions[UK][g_k]
        if multiple_counter[g_k] > 1:
            p = _choose_perm(p, cur_perm)
        permissions[UK][g_k] = p

    #user explicit permission for user groups
    user_user_groups_perms = Permission.get_default_user_group_perms(uid)
    for perm in user_user_groups_perms:
        u_k = perm.UserUserGroupToPerm.user_group.users_group_name
        p = perm.Permission.permission_name
        cur_perm = permissions[UK][u_k]
        if not explicit:
            p = _choose_perm(p, cur_perm)
        permissions[UK][u_k] = p

    return permissions


def allowed_api_access(controller_name, whitelist=None, api_key=None):
    """
    Check if given controller_name is in whitelist API access
    """
    if not whitelist:
        from rhodecode import CONFIG
        whitelist = aslist(CONFIG.get('api_access_controllers_whitelist'),
                           sep=',')
        log.debug('whitelist of API access is: %s' % (whitelist))
    api_access_valid = controller_name in whitelist
    if api_access_valid:
        log.debug('controller:%s is in API whitelist' % (controller_name))
    else:
        msg = 'controller: %s is *NOT* in API whitelist' % (controller_name)
        if api_key:
            #if we use API key and don't have access it's a warning
            log.warning(msg)
        else:
            log.debug(msg)
    return api_access_valid


class AuthUser(object):
    """
    A simple object that handles all attributes of user in RhodeCode

    It does lookup based on API key,given user, or user present in session
    Then it fills all required information for such user. It also checks if
    anonymous access is enabled and if so, it returns default user as logged in
    """

    def __init__(self, user_id=None, api_key=None, username=None, ip_addr=None):

        self.user_id = user_id
        self._api_key = api_key

        self.api_key = None
        self.username = username
        self.ip_addr = ip_addr
        self.name = ''
        self.lastname = ''
        self.email = ''
        self.is_authenticated = False
        self.admin = False
        self.inherit_default_permissions = False

        self.propagate_data()
        self._instance = None

    @LazyProperty
    def permissions(self):
        return self.get_perms(user=self, cache=False)

    @property
    def api_keys(self):
        return self.get_api_keys()

    def propagate_data(self):
        user_model = UserModel()
        self.anonymous_user = User.get_default_user(cache=True)
        is_user_loaded = False

        # lookup by userid
        if self.user_id is not None and self.user_id != self.anonymous_user.user_id:
            log.debug('Auth User lookup by USER ID %s' % self.user_id)
            is_user_loaded = user_model.fill_data(self, user_id=self.user_id)

        # try go get user by api key
        elif self._api_key and self._api_key != self.anonymous_user.api_key:
            log.debug('Auth User lookup by API KEY %s' % self._api_key)
            is_user_loaded = user_model.fill_data(self, api_key=self._api_key)

        # lookup by username
        elif self.username:
            log.debug('Auth User lookup by USER NAME %s' % self.username)
            is_user_loaded = user_model.fill_data(self, username=self.username)
        else:
            log.debug('No data in %s that could been used to log in' % self)

        if not is_user_loaded:
            # if we cannot authenticate user try anonymous
            if self.anonymous_user.active:
                user_model.fill_data(self, user_id=self.anonymous_user.user_id)
                # then we set this user is logged in
                self.is_authenticated = True
            else:
                self.user_id = None
                self.username = None
                self.is_authenticated = False

        if not self.username:
            self.username = 'None'

        log.debug('Auth User is now %s' % self)

    def get_perms(self, user, explicit=True, algo='higherwin', cache=False):
        """
        Fills user permission attribute with permissions taken from database
        works for permissions given for repositories, and for permissions that
        are granted to groups

        :param user: instance of User object from database
        :param explicit: In case there are permissions both for user and a group
            that user is part of, explicit flag will defiine if user will
            explicitly override permissions from group, if it's False it will
            make decision based on the algo
        :param algo: algorithm to decide what permission should be choose if
            it's multiple defined, eg user in two different groups. It also
            decides if explicit flag is turned off how to specify the permission
            for case when user is in a group + have defined separate permission
        """
        user_id = user.user_id
        user_is_admin = user.is_admin
        user_inherit_default_permissions = user.inherit_default_permissions

        log.debug('Getting PERMISSION tree')
        compute = conditional_cache('short_term', 'cache_desc',
                                    condition=cache, func=_cached_perms_data)
        return compute(user_id, user_is_admin,
                       user_inherit_default_permissions, explicit, algo)

    def get_api_keys(self):
        api_keys = [self.api_key]
        for api_key in UserApiKeys.query()\
                .filter(UserApiKeys.user_id == self.user_id)\
                .filter(or_(UserApiKeys.expires == -1,
                            UserApiKeys.expires >= time.time())).all():
            api_keys.append(api_key.api_key)

        return api_keys

    @property
    def is_admin(self):
        return self.admin

    @property
    def repositories_admin(self):
        """
        Returns list of repositories you're an admin of
        """
        return [x[0] for x in self.permissions['repositories'].iteritems()
                if x[1] == 'repository.admin']

    @property
    def repository_groups_admin(self):
        """
        Returns list of repository groups you're an admin of
        """
        return [x[0] for x in self.permissions['repositories_groups'].iteritems()
                if x[1] == 'group.admin']

    @property
    def user_groups_admin(self):
        """
        Returns list of user groups you're an admin of
        """
        return [x[0] for x in self.permissions['user_groups'].iteritems()
                if x[1] == 'usergroup.admin']

    @property
    def ip_allowed(self):
        """
        Checks if ip_addr used in constructor is allowed from defined list of
        allowed ip_addresses for user

        :returns: boolean, True if ip is in allowed ip range
        """
        # check IP
        inherit = self.inherit_default_permissions
        return AuthUser.check_ip_allowed(self.user_id, self.ip_addr,
                                         inherit_from_default=inherit)

    @classmethod
    def check_ip_allowed(cls, user_id, ip_addr, inherit_from_default):
        allowed_ips = AuthUser.get_allowed_ips(user_id, cache=True,
                        inherit_from_default=inherit_from_default)
        if check_ip_access(source_ip=ip_addr, allowed_ips=allowed_ips):
            log.debug('IP:%s is in range of %s' % (ip_addr, allowed_ips))
            return True
        else:
            log.info('Access for IP:%s forbidden, '
                     'not in %s' % (ip_addr, allowed_ips))
            return False

    def __repr__(self):
        return "<AuthUser('id:%s[%s] ip:%s auth:%s')>"\
            % (self.user_id, self.username, self.ip_addr, self.is_authenticated)

    def set_authenticated(self, authenticated=True):
        if self.user_id != self.anonymous_user.user_id:
            self.is_authenticated = authenticated

    def get_cookie_store(self):
        return {'username': self.username,
                'user_id': self.user_id,
                'is_authenticated': self.is_authenticated}

    @classmethod
    def from_cookie_store(cls, cookie_store):
        """
        Creates AuthUser from a cookie store

        :param cls:
        :param cookie_store:
        """
        user_id = cookie_store.get('user_id')
        username = cookie_store.get('username')
        api_key = cookie_store.get('api_key')
        return AuthUser(user_id, api_key, username)

    @classmethod
    def get_allowed_ips(cls, user_id, cache=False, inherit_from_default=False):
        _set = set()

        if inherit_from_default:
            default_ips = UserIpMap.query().filter(UserIpMap.user ==
                                            User.get_default_user(cache=True))
            if cache:
                default_ips = default_ips.options(FromCache("sql_cache_short",
                                                  "get_user_ips_default"))

            # populate from default user
            for ip in default_ips:
                try:
                    _set.add(ip.ip_addr)
                except ObjectDeletedError:
                    # since we use heavy caching sometimes it happens that we get
                    # deleted objects here, we just skip them
                    pass

        user_ips = UserIpMap.query().filter(UserIpMap.user_id == user_id)
        if cache:
            user_ips = user_ips.options(FromCache("sql_cache_short",
                                                  "get_user_ips_%s" % user_id))

        for ip in user_ips:
            try:
                _set.add(ip.ip_addr)
            except ObjectDeletedError:
                # since we use heavy caching sometimes it happens that we get
                # deleted objects here, we just skip them
                pass
        return _set or set(['0.0.0.0/0', '::/0'])


def set_available_permissions(config):
    """
    This function will propagate pylons globals with all available defined
    permission given in db. We don't want to check each time from db for new
    permissions since adding a new permission also requires application restart
    ie. to decorate new views with the newly created permission

    :param config: current pylons config instance

    """
    log.info('getting information about all available permissions')
    try:
        sa = meta.Session
        all_perms = sa.query(Permission).all()
        config['available_permissions'] = [x.permission_name for x in all_perms]
    except Exception:
        log.error(traceback.format_exc())
    finally:
        meta.Session.remove()


#==============================================================================
# CHECK DECORATORS
#==============================================================================
class LoginRequired(object):
    """
    Must be logged in to execute this function else
    redirect to login page

    :param api_access: if enabled this checks only for valid auth token
        and grants access based on valid token
    """

    def __init__(self, api_access=False):
        self.api_access = api_access

    def __call__(self, func):
        return decorator(self.__wrapper, func)

    def __wrapper(self, func, *fargs, **fkwargs):
        cls = fargs[0]
        user = cls.rhodecode_user
        loc = "%s:%s" % (cls.__class__.__name__, func.__name__)

        # check if our IP is allowed
        ip_access_valid = True
        if not user.ip_allowed:
            from rhodecode.lib import helpers as h
            h.flash(h.literal(_('IP %s not allowed' % (user.ip_addr))),
                    category='warning')
            ip_access_valid = False

        # check if we used an APIKEY and it's a valid one
        # defined whitelist of controllers which API access will be enabled
        _api_key = request.GET.get('api_key', '')
        api_access_valid = allowed_api_access(loc, api_key=_api_key)

        # explicit controller is enabled or API is in our whitelist
        if self.api_access or api_access_valid:
            log.debug('Checking API KEY access for %s' % cls)
            if _api_key and _api_key in user.api_keys:
                api_access_valid = True
                log.debug('API KEY ****%s is VALID' % _api_key[-4:])
            else:
                api_access_valid = False
                if not _api_key:
                    log.debug("API KEY *NOT* present in request")
                else:
                    log.warn("API KEY ****%s *NOT* valid" % _api_key[-4:])

        log.debug('Checking if %s is authenticated @ %s' % (user.username, loc))
        reason = 'RegularAuth' if user.is_authenticated else 'APIAuth'

        if ip_access_valid and (user.is_authenticated or api_access_valid):
            log.info('user %s authenticating with:%s IS authenticated on func %s '
                     % (user, reason, loc)
            )
            return func(*fargs, **fkwargs)
        else:
            log.warn('user %s authenticating with:%s NOT authenticated on func: %s: '
                     'IP_ACCESS:%s API_ACCESS:%s'
                     % (user, reason, loc, ip_access_valid, api_access_valid)
            )
            p = url.current()

            log.debug('redirecting to login page with %s' % p)
            return redirect(url('login_home', came_from=p))


class NotAnonymous(object):
    """
    Must be logged in to execute this function else
    redirect to login page"""

    def __call__(self, func):
        return decorator(self.__wrapper, func)

    def __wrapper(self, func, *fargs, **fkwargs):
        cls = fargs[0]
        self.user = cls.rhodecode_user

        log.debug('Checking if user is not anonymous @%s' % cls)

        anonymous = self.user.username == User.DEFAULT_USER

        if anonymous:
            p = url.current()

            import rhodecode.lib.helpers as h
            h.flash(_('You need to be a registered user to '
                      'perform this action'),
                    category='warning')
            return redirect(url('login_home', came_from=p))
        else:
            return func(*fargs, **fkwargs)


class PermsDecorator(object):
    """Base class for controller decorators"""

    def __init__(self, *required_perms):
        self.required_perms = set(required_perms)
        self.user_perms = None

    def __call__(self, func):
        return decorator(self.__wrapper, func)

    def __wrapper(self, func, *fargs, **fkwargs):
        cls = fargs[0]
        self.user = cls.rhodecode_user
        self.user_perms = self.user.permissions
        log.debug('checking %s permissions %s for %s %s',
           self.__class__.__name__, self.required_perms, cls, self.user)

        if self.check_permissions():
            log.debug('Permission granted for %s %s' % (cls, self.user))
            return func(*fargs, **fkwargs)

        else:
            log.debug('Permission denied for %s %s' % (cls, self.user))
            anonymous = self.user.username == User.DEFAULT_USER

            if anonymous:
                p = url.current()

                import rhodecode.lib.helpers as h
                h.flash(_('You need to be a signed in to '
                          'view this page'),
                        category='warning')
                return redirect(url('login_home', came_from=p))

            else:
                # redirect with forbidden ret code
                return abort(403)

    def check_permissions(self):
        """Dummy function for overriding"""
        raise Exception('You have to write this function in child class')


class HasPermissionAllDecorator(PermsDecorator):
    """
    Checks for access permission for all given predicates. All of them
    have to be meet in order to fulfill the request
    """

    def check_permissions(self):
        if self.required_perms.issubset(self.user_perms.get('global')):
            return True
        return False


class HasPermissionAnyDecorator(PermsDecorator):
    """
    Checks for access permission for any of given predicates. In order to
    fulfill the request any of predicates must be meet
    """

    def check_permissions(self):
        if self.required_perms.intersection(self.user_perms.get('global')):
            return True
        return False


class HasRepoPermissionAllDecorator(PermsDecorator):
    """
    Checks for access permission for all given predicates for specific
    repository. All of them have to be meet in order to fulfill the request
    """

    def check_permissions(self):
        repo_name = get_repo_slug(request)
        try:
            user_perms = set([self.user_perms['repositories'][repo_name]])
        except KeyError:
            return False
        if self.required_perms.issubset(user_perms):
            return True
        return False


class HasRepoPermissionAnyDecorator(PermsDecorator):
    """
    Checks for access permission for any of given predicates for specific
    repository. In order to fulfill the request any of predicates must be meet
    """

    def check_permissions(self):
        repo_name = get_repo_slug(request)
        try:
            user_perms = set([self.user_perms['repositories'][repo_name]])
        except KeyError:
            return False

        if self.required_perms.intersection(user_perms):
            return True
        return False


class HasRepoGroupPermissionAllDecorator(PermsDecorator):
    """
    Checks for access permission for all given predicates for specific
    repository group. All of them have to be meet in order to fulfill the request
    """

    def check_permissions(self):
        group_name = get_repo_group_slug(request)
        try:
            user_perms = set([self.user_perms['repositories_groups'][group_name]])
        except KeyError:
            return False

        if self.required_perms.issubset(user_perms):
            return True
        return False


class HasRepoGroupPermissionAnyDecorator(PermsDecorator):
    """
    Checks for access permission for any of given predicates for specific
    repository group. In order to fulfill the request any of predicates must be meet
    """

    def check_permissions(self):
        group_name = get_repo_group_slug(request)
        try:
            user_perms = set([self.user_perms['repositories_groups'][group_name]])
        except KeyError:
            return False

        if self.required_perms.intersection(user_perms):
            return True
        return False


class HasUserGroupPermissionAllDecorator(PermsDecorator):
    """
    Checks for access permission for all given predicates for specific
    user group. All of them have to be meet in order to fulfill the request
    """

    def check_permissions(self):
        group_name = get_user_group_slug(request)
        try:
            user_perms = set([self.user_perms['user_groups'][group_name]])
        except KeyError:
            return False

        if self.required_perms.issubset(user_perms):
            return True
        return False


class HasUserGroupPermissionAnyDecorator(PermsDecorator):
    """
    Checks for access permission for any of given predicates for specific
    user group. In order to fulfill the request any of predicates must be meet
    """

    def check_permissions(self):
        group_name = get_user_group_slug(request)
        try:
            user_perms = set([self.user_perms['user_groups'][group_name]])
        except KeyError:
            return False

        if self.required_perms.intersection(user_perms):
            return True
        return False


#==============================================================================
# CHECK FUNCTIONS
#==============================================================================
class PermsFunction(object):
    """Base function for other check functions"""

    def __init__(self, *perms):
        self.required_perms = set(perms)
        self.user_perms = None
        self.repo_name = None
        self.group_name = None

    def __call__(self, check_location='', user=None):
        if not user:
            #TODO: remove this someday,put as user as attribute here
            user = request.user

        # init auth user if not already given
        if not isinstance(user, AuthUser):
            user = AuthUser(user.user_id)

        cls_name = self.__class__.__name__
        check_scope = {
            'HasPermissionAll': '',
            'HasPermissionAny': '',
            'HasRepoPermissionAll': 'repo:%s' % self.repo_name,
            'HasRepoPermissionAny': 'repo:%s' % self.repo_name,
            'HasRepoGroupPermissionAll': 'group:%s' % self.group_name,
            'HasRepoGroupPermissionAny': 'group:%s' % self.group_name,
        }.get(cls_name, '?')
        log.debug('checking cls:%s %s usr:%s %s @ %s', cls_name,
                  self.required_perms, user, check_scope,
                  check_location or 'unspecified location')
        if not user:
            log.debug('Empty request user')
            return False
        self.user_perms = user.permissions
        if self.check_permissions():
            log.debug('Permission to %s granted for user: %s @ %s'
                      % (check_scope, user,
                         check_location or 'unspecified location'))
            return True

        else:
            log.debug('Permission to %s denied for user: %s @ %s'
                      % (check_scope, user,
                         check_location or 'unspecified location'))
            return False

    def check_permissions(self):
        """Dummy function for overriding"""
        raise Exception('You have to write this function in child class')


class HasPermissionAll(PermsFunction):
    def check_permissions(self):
        if self.required_perms.issubset(self.user_perms.get('global')):
            return True
        return False


class HasPermissionAny(PermsFunction):
    def check_permissions(self):
        if self.required_perms.intersection(self.user_perms.get('global')):
            return True
        return False


class HasRepoPermissionAll(PermsFunction):
    def __call__(self, repo_name=None, check_location='', user=None):
        self.repo_name = repo_name
        return super(HasRepoPermissionAll, self).__call__(check_location, user)

    def check_permissions(self):
        if not self.repo_name:
            self.repo_name = get_repo_slug(request)

        try:
            self._user_perms = set(
                [self.user_perms['repositories'][self.repo_name]]
            )
        except KeyError:
            return False
        if self.required_perms.issubset(self._user_perms):
            return True
        return False


class HasRepoPermissionAny(PermsFunction):
    def __call__(self, repo_name=None, check_location='', user=None):
        self.repo_name = repo_name
        return super(HasRepoPermissionAny, self).__call__(check_location, user)

    def check_permissions(self):
        if not self.repo_name:
            self.repo_name = get_repo_slug(request)

        try:
            self._user_perms = set(
                [self.user_perms['repositories'][self.repo_name]]
            )
        except KeyError:
            return False
        if self.required_perms.intersection(self._user_perms):
            return True
        return False


class HasRepoGroupPermissionAny(PermsFunction):
    def __call__(self, group_name=None, check_location='', user=None):
        self.group_name = group_name
        return super(HasRepoGroupPermissionAny, self).__call__(check_location, user)

    def check_permissions(self):
        try:
            self._user_perms = set(
                [self.user_perms['repositories_groups'][self.group_name]]
            )
        except KeyError:
            return False
        if self.required_perms.intersection(self._user_perms):
            return True
        return False


class HasRepoGroupPermissionAll(PermsFunction):
    def __call__(self, group_name=None, check_location='', user=None):
        self.group_name = group_name
        return super(HasRepoGroupPermissionAll, self).__call__(check_location, user)

    def check_permissions(self):
        try:
            self._user_perms = set(
                [self.user_perms['repositories_groups'][self.group_name]]
            )
        except KeyError:
            return False
        if self.required_perms.issubset(self._user_perms):
            return True
        return False


class HasUserGroupPermissionAny(PermsFunction):
    def __call__(self, user_group_name=None, check_location='', user=None):
        self.user_group_name = user_group_name
        return super(HasUserGroupPermissionAny, self).__call__(check_location, user)

    def check_permissions(self):
        try:
            self._user_perms = set(
                [self.user_perms['user_groups'][self.user_group_name]]
            )
        except KeyError:
            return False
        if self.required_perms.intersection(self._user_perms):
            return True
        return False


class HasUserGroupPermissionAll(PermsFunction):
    def __call__(self, user_group_name=None, check_location='', user=None):
        self.user_group_name = user_group_name
        return super(HasUserGroupPermissionAll, self).__call__(check_location, user)

    def check_permissions(self):
        try:
            self._user_perms = set(
                [self.user_perms['user_groups'][self.user_group_name]]
            )
        except KeyError:
            return False
        if self.required_perms.issubset(self._user_perms):
            return True
        return False


#==============================================================================
# SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
#==============================================================================
class HasPermissionAnyMiddleware(object):
    def __init__(self, *perms):
        self.required_perms = set(perms)

    def __call__(self, user, repo_name):
        # repo_name MUST be unicode, since we handle keys in permission
        # dict by unicode
        repo_name = safe_unicode(repo_name)
        usr = AuthUser(user.user_id)
        try:
            self.user_perms = set([usr.permissions['repositories'][repo_name]])
        except Exception:
            log.error('Exception while accessing permissions %s' %
                      traceback.format_exc())
            self.user_perms = set()
        self.username = user.username
        self.repo_name = repo_name
        return self.check_permissions()

    def check_permissions(self):
        log.debug('checking VCS protocol '
                  'permissions %s for user:%s repository:%s', self.user_perms,
                                                self.username, self.repo_name)
        if self.required_perms.intersection(self.user_perms):
            log.debug('Permission to repo: %s granted for user: %s @ %s'
                      % (self.repo_name, self.username, 'PermissionMiddleware'))
            return True
        log.debug('Permission to repo: %s denied for user: %s @ %s'
                  % (self.repo_name, self.username, 'PermissionMiddleware'))
        return False


#==============================================================================
# SPECIAL VERSION TO HANDLE API AUTH
#==============================================================================
class _BaseApiPerm(object):
    def __init__(self, *perms):
        self.required_perms = set(perms)

    def __call__(self, check_location=None, user=None, repo_name=None,
                 group_name=None):
        cls_name = self.__class__.__name__
        check_scope = 'user:%s' % (user)
        if repo_name:
            check_scope += ', repo:%s' % (repo_name)

        if group_name:
            check_scope += ', repo group:%s' % (group_name)

        log.debug('checking cls:%s %s %s @ %s'
                  % (cls_name, self.required_perms, check_scope, check_location))
        if not user:
            log.debug('Empty User passed into arguments')
            return False

        ## process user
        if not isinstance(user, AuthUser):
            user = AuthUser(user.user_id)
        if not check_location:
            check_location = 'unspecified'
        if self.check_permissions(user.permissions, repo_name, group_name):
            log.debug('Permission to %s granted for user: %s @ %s'
                      % (check_scope, user, check_location))
            return True

        else:
            log.debug('Permission to %s denied for user: %s @ %s'
                      % (check_scope, user, check_location))
            return False

    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        """
        implement in child class should return True if permissions are ok,
        False otherwise

        :param perm_defs: dict with permission definitions
        :param repo_name: repo name
        """
        raise NotImplementedError()


class HasPermissionAllApi(_BaseApiPerm):
    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        if self.required_perms.issubset(perm_defs.get('global')):
            return True
        return False


class HasPermissionAnyApi(_BaseApiPerm):
    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        if self.required_perms.intersection(perm_defs.get('global')):
            return True
        return False


class HasRepoPermissionAllApi(_BaseApiPerm):
    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        try:
            _user_perms = set([perm_defs['repositories'][repo_name]])
        except KeyError:
            log.warning(traceback.format_exc())
            return False
        if self.required_perms.issubset(_user_perms):
            return True
        return False


class HasRepoPermissionAnyApi(_BaseApiPerm):
    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        try:
            _user_perms = set([perm_defs['repositories'][repo_name]])
        except KeyError:
            log.warning(traceback.format_exc())
            return False
        if self.required_perms.intersection(_user_perms):
            return True
        return False


class HasRepoGroupPermissionAnyApi(_BaseApiPerm):
    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        try:
            _user_perms = set([perm_defs['repositories_groups'][group_name]])
        except KeyError:
            log.warning(traceback.format_exc())
            return False
        if self.required_perms.intersection(_user_perms):
            return True
        return False

class HasRepoGroupPermissionAllApi(_BaseApiPerm):
    def check_permissions(self, perm_defs, repo_name=None, group_name=None):
        try:
            _user_perms = set([perm_defs['repositories_groups'][group_name]])
        except KeyError:
            log.warning(traceback.format_exc())
            return False
        if self.required_perms.issubset(_user_perms):
            return True
        return False

def check_ip_access(source_ip, allowed_ips=None):
    """
    Checks if source_ip is a subnet of any of allowed_ips.

    :param source_ip:
    :param allowed_ips: list of allowed ips together with mask
    """
    from rhodecode.lib import ipaddr
    log.debug('checking if ip:%s is subnet of %s' % (source_ip, allowed_ips))
    if isinstance(allowed_ips, (tuple, list, set)):
        for ip in allowed_ips:
            try:
                if ipaddr.IPAddress(source_ip) in ipaddr.IPNetwork(ip):
                    log.debug('IP %s is network %s' %
                              (ipaddr.IPAddress(source_ip), ipaddr.IPNetwork(ip)))
                    return True
                # for any case we cannot determine the IP, don't crash just
                # skip it and log as error, we want to say forbidden still when
                # sending bad IP
            except Exception:
                log.error(traceback.format_exc())
                continue
    return False