##// END OF EJS Templates
Some code cleanups and fixes
marcink -
r1628:de71a4bd beta
parent child Browse files
Show More
@@ -1,241 +1,243 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode - Pylons environment configuration #
3 # RhodeCode - Pylons environment configuration #
4 # #
4 # #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10 pdebug = false
10 pdebug = false
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the address which should receive ##
12 ## Uncomment and replace with the address which should receive ##
13 ## any error reports after application crash ##
13 ## any error reports after application crash ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 #smtp_auth =
28 #smtp_auth =
29
29
30 [server:main]
30 [server:main]
31 ##nr of threads to spawn
31 ##nr of threads to spawn
32 threadpool_workers = 5
32 threadpool_workers = 5
33
33
34 ##max request before thread respawn
34 ##max request before thread respawn
35 threadpool_max_requests = 6
35 threadpool_max_requests = 6
36
36
37 ##option to use threads of process
37 ##option to use threads of process
38 use_threadpool = true
38 use_threadpool = true
39
39
40 use = egg:Paste#http
40 use = egg:Paste#http
41 host = 0.0.0.0
41 host = 0.0.0.0
42 port = 5000
42 port = 5000
43
43
44 [app:main]
44 [app:main]
45 use = egg:rhodecode
45 use = egg:rhodecode
46 full_stack = true
46 full_stack = true
47 static_files = true
47 static_files = true
48 lang=en
48 lang=en
49 cache_dir = %(here)s/data
49 cache_dir = %(here)s/data
50 index_dir = %(here)s/data/index
50 index_dir = %(here)s/data/index
51 app_instance_uuid = develop
51 app_instance_uuid = develop
52 cut_off_limit = 256000
52 cut_off_limit = 256000
53 force_https = false
53 force_https = false
54 commit_parse_limit = 25
54 commit_parse_limit = 25
55 use_gravatar = true
55 use_gravatar = true
56 container_auth_enabled = false
57 proxypass_auth_enabled = false
56
58
57 ####################################
59 ####################################
58 ### CELERY CONFIG ####
60 ### CELERY CONFIG ####
59 ####################################
61 ####################################
60 use_celery = false
62 use_celery = false
61 broker.host = localhost
63 broker.host = localhost
62 broker.vhost = rabbitmqhost
64 broker.vhost = rabbitmqhost
63 broker.port = 5672
65 broker.port = 5672
64 broker.user = rabbitmq
66 broker.user = rabbitmq
65 broker.password = qweqwe
67 broker.password = qweqwe
66
68
67 celery.imports = rhodecode.lib.celerylib.tasks
69 celery.imports = rhodecode.lib.celerylib.tasks
68
70
69 celery.result.backend = amqp
71 celery.result.backend = amqp
70 celery.result.dburi = amqp://
72 celery.result.dburi = amqp://
71 celery.result.serialier = json
73 celery.result.serialier = json
72
74
73 #celery.send.task.error.emails = true
75 #celery.send.task.error.emails = true
74 #celery.amqp.task.result.expires = 18000
76 #celery.amqp.task.result.expires = 18000
75
77
76 celeryd.concurrency = 2
78 celeryd.concurrency = 2
77 #celeryd.log.file = celeryd.log
79 #celeryd.log.file = celeryd.log
78 celeryd.log.level = debug
80 celeryd.log.level = debug
79 celeryd.max.tasks.per.child = 1
81 celeryd.max.tasks.per.child = 1
80
82
81 #tasks will never be sent to the queue, but executed locally instead.
83 #tasks will never be sent to the queue, but executed locally instead.
82 celery.always.eager = false
84 celery.always.eager = false
83
85
84 ####################################
86 ####################################
85 ### BEAKER CACHE ####
87 ### BEAKER CACHE ####
86 ####################################
88 ####################################
87 beaker.cache.data_dir=%(here)s/data/cache/data
89 beaker.cache.data_dir=%(here)s/data/cache/data
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
90 beaker.cache.lock_dir=%(here)s/data/cache/lock
89
91
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
92 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
91
93
92 beaker.cache.super_short_term.type=memory
94 beaker.cache.super_short_term.type=memory
93 beaker.cache.super_short_term.expire=10
95 beaker.cache.super_short_term.expire=10
94 beaker.cache.super_short_term.key_length = 256
96 beaker.cache.super_short_term.key_length = 256
95
97
96 beaker.cache.short_term.type=memory
98 beaker.cache.short_term.type=memory
97 beaker.cache.short_term.expire=60
99 beaker.cache.short_term.expire=60
98 beaker.cache.short_term.key_length = 256
100 beaker.cache.short_term.key_length = 256
99
101
100 beaker.cache.long_term.type=memory
102 beaker.cache.long_term.type=memory
101 beaker.cache.long_term.expire=36000
103 beaker.cache.long_term.expire=36000
102 beaker.cache.long_term.key_length = 256
104 beaker.cache.long_term.key_length = 256
103
105
104 beaker.cache.sql_cache_short.type=memory
106 beaker.cache.sql_cache_short.type=memory
105 beaker.cache.sql_cache_short.expire=10
107 beaker.cache.sql_cache_short.expire=10
106 beaker.cache.sql_cache_short.key_length = 256
108 beaker.cache.sql_cache_short.key_length = 256
107
109
108 beaker.cache.sql_cache_med.type=memory
110 beaker.cache.sql_cache_med.type=memory
109 beaker.cache.sql_cache_med.expire=360
111 beaker.cache.sql_cache_med.expire=360
110 beaker.cache.sql_cache_med.key_length = 256
112 beaker.cache.sql_cache_med.key_length = 256
111
113
112 beaker.cache.sql_cache_long.type=file
114 beaker.cache.sql_cache_long.type=file
113 beaker.cache.sql_cache_long.expire=3600
115 beaker.cache.sql_cache_long.expire=3600
114 beaker.cache.sql_cache_long.key_length = 256
116 beaker.cache.sql_cache_long.key_length = 256
115
117
116 ####################################
118 ####################################
117 ### BEAKER SESSION ####
119 ### BEAKER SESSION ####
118 ####################################
120 ####################################
119 ## Type of storage used for the session, current types are
121 ## Type of storage used for the session, current types are
120 ## dbm, file, memcached, database, and memory.
122 ## dbm, file, memcached, database, and memory.
121 ## The storage uses the Container API
123 ## The storage uses the Container API
122 ##that is also used by the cache system.
124 ##that is also used by the cache system.
123 beaker.session.type = file
125 beaker.session.type = file
124
126
125 beaker.session.key = rhodecode
127 beaker.session.key = rhodecode
126 beaker.session.secret = g654dcno0-9873jhgfreyu
128 beaker.session.secret = g654dcno0-9873jhgfreyu
127 beaker.session.timeout = 36000
129 beaker.session.timeout = 36000
128
130
129 ##auto save the session to not to use .save()
131 ##auto save the session to not to use .save()
130 beaker.session.auto = False
132 beaker.session.auto = False
131
133
132 ##true exire at browser close
134 ##true exire at browser close
133 #beaker.session.cookie_expires = 3600
135 #beaker.session.cookie_expires = 3600
134
136
135
137
136 ################################################################################
138 ################################################################################
137 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
139 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
138 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
140 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
139 ## execute malicious code after an exception is raised. ##
141 ## execute malicious code after an exception is raised. ##
140 ################################################################################
142 ################################################################################
141 #set debug = false
143 #set debug = false
142
144
143 ##################################
145 ##################################
144 ### LOGVIEW CONFIG ###
146 ### LOGVIEW CONFIG ###
145 ##################################
147 ##################################
146 logview.sqlalchemy = #faa
148 logview.sqlalchemy = #faa
147 logview.pylons.templating = #bfb
149 logview.pylons.templating = #bfb
148 logview.pylons.util = #eee
150 logview.pylons.util = #eee
149
151
150 #########################################################
152 #########################################################
151 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
153 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
152 #########################################################
154 #########################################################
153 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
155 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
154 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
156 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
155 sqlalchemy.db1.echo = false
157 sqlalchemy.db1.echo = false
156 sqlalchemy.db1.pool_recycle = 3600
158 sqlalchemy.db1.pool_recycle = 3600
157 sqlalchemy.convert_unicode = true
159 sqlalchemy.convert_unicode = true
158
160
159 ################################
161 ################################
160 ### LOGGING CONFIGURATION ####
162 ### LOGGING CONFIGURATION ####
161 ################################
163 ################################
162 [loggers]
164 [loggers]
163 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
165 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
164
166
165 [handlers]
167 [handlers]
166 keys = console, console_sql
168 keys = console, console_sql
167
169
168 [formatters]
170 [formatters]
169 keys = generic, color_formatter, color_formatter_sql
171 keys = generic, color_formatter, color_formatter_sql
170
172
171 #############
173 #############
172 ## LOGGERS ##
174 ## LOGGERS ##
173 #############
175 #############
174 [logger_root]
176 [logger_root]
175 level = NOTSET
177 level = NOTSET
176 handlers = console
178 handlers = console
177
179
178 [logger_routes]
180 [logger_routes]
179 level = DEBUG
181 level = DEBUG
180 handlers =
182 handlers =
181 qualname = routes.middleware
183 qualname = routes.middleware
182 # "level = DEBUG" logs the route matched and routing variables.
184 # "level = DEBUG" logs the route matched and routing variables.
183 propagate = 1
185 propagate = 1
184
186
185 [logger_beaker]
187 [logger_beaker]
186 level = DEBUG
188 level = DEBUG
187 handlers =
189 handlers =
188 qualname = beaker.container
190 qualname = beaker.container
189 propagate = 1
191 propagate = 1
190
192
191 [logger_templates]
193 [logger_templates]
192 level = INFO
194 level = INFO
193 handlers =
195 handlers =
194 qualname = pylons.templating
196 qualname = pylons.templating
195 propagate = 1
197 propagate = 1
196
198
197 [logger_rhodecode]
199 [logger_rhodecode]
198 level = DEBUG
200 level = DEBUG
199 handlers =
201 handlers =
200 qualname = rhodecode
202 qualname = rhodecode
201 propagate = 1
203 propagate = 1
202
204
203 [logger_sqlalchemy]
205 [logger_sqlalchemy]
204 level = INFO
206 level = INFO
205 handlers = console_sql
207 handlers = console_sql
206 qualname = sqlalchemy.engine
208 qualname = sqlalchemy.engine
207 propagate = 0
209 propagate = 0
208
210
209 ##############
211 ##############
210 ## HANDLERS ##
212 ## HANDLERS ##
211 ##############
213 ##############
212
214
213 [handler_console]
215 [handler_console]
214 class = StreamHandler
216 class = StreamHandler
215 args = (sys.stderr,)
217 args = (sys.stderr,)
216 level = DEBUG
218 level = DEBUG
217 formatter = color_formatter
219 formatter = color_formatter
218
220
219 [handler_console_sql]
221 [handler_console_sql]
220 class = StreamHandler
222 class = StreamHandler
221 args = (sys.stderr,)
223 args = (sys.stderr,)
222 level = DEBUG
224 level = DEBUG
223 formatter = color_formatter_sql
225 formatter = color_formatter_sql
224
226
225 ################
227 ################
226 ## FORMATTERS ##
228 ## FORMATTERS ##
227 ################
229 ################
228
230
229 [formatter_generic]
231 [formatter_generic]
230 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
232 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
231 datefmt = %Y-%m-%d %H:%M:%S
233 datefmt = %Y-%m-%d %H:%M:%S
232
234
233 [formatter_color_formatter]
235 [formatter_color_formatter]
234 class=rhodecode.lib.colored_formatter.ColorFormatter
236 class=rhodecode.lib.colored_formatter.ColorFormatter
235 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
237 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
236 datefmt = %Y-%m-%d %H:%M:%S
238 datefmt = %Y-%m-%d %H:%M:%S
237
239
238 [formatter_color_formatter_sql]
240 [formatter_color_formatter_sql]
239 class=rhodecode.lib.colored_formatter.ColorFormatterSql
241 class=rhodecode.lib.colored_formatter.ColorFormatterSql
240 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
242 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
241 datefmt = %Y-%m-%d %H:%M:%S
243 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,241 +1,243 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode - Pylons environment configuration #
3 # RhodeCode - Pylons environment configuration #
4 # #
4 # #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10 pdebug = false
10 pdebug = false
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the address which should receive ##
12 ## Uncomment and replace with the address which should receive ##
13 ## any error reports after application crash ##
13 ## any error reports after application crash ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
27 # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
28 #smtp_auth =
28 #smtp_auth =
29
29
30 [server:main]
30 [server:main]
31 ##nr of threads to spawn
31 ##nr of threads to spawn
32 threadpool_workers = 5
32 threadpool_workers = 5
33
33
34 ##max request before thread respawn
34 ##max request before thread respawn
35 threadpool_max_requests = 10
35 threadpool_max_requests = 10
36
36
37 ##option to use threads of process
37 ##option to use threads of process
38 use_threadpool = true
38 use_threadpool = true
39
39
40 use = egg:Paste#http
40 use = egg:Paste#http
41 host = 127.0.0.1
41 host = 127.0.0.1
42 port = 8001
42 port = 8001
43
43
44 [app:main]
44 [app:main]
45 use = egg:rhodecode
45 use = egg:rhodecode
46 full_stack = true
46 full_stack = true
47 static_files = true
47 static_files = true
48 lang=en
48 lang=en
49 cache_dir = %(here)s/data
49 cache_dir = %(here)s/data
50 index_dir = %(here)s/data/index
50 index_dir = %(here)s/data/index
51 app_instance_uuid = prod1234
51 app_instance_uuid = prod1234
52 cut_off_limit = 256000
52 cut_off_limit = 256000
53 force_https = false
53 force_https = false
54 commit_parse_limit = 50
54 commit_parse_limit = 50
55 use_gravatar = true
55 use_gravatar = true
56 container_auth_enabled = false
57 proxypass_auth_enabled = false
56
58
57 ####################################
59 ####################################
58 ### CELERY CONFIG ####
60 ### CELERY CONFIG ####
59 ####################################
61 ####################################
60 use_celery = false
62 use_celery = false
61 broker.host = localhost
63 broker.host = localhost
62 broker.vhost = rabbitmqhost
64 broker.vhost = rabbitmqhost
63 broker.port = 5672
65 broker.port = 5672
64 broker.user = rabbitmq
66 broker.user = rabbitmq
65 broker.password = qweqwe
67 broker.password = qweqwe
66
68
67 celery.imports = rhodecode.lib.celerylib.tasks
69 celery.imports = rhodecode.lib.celerylib.tasks
68
70
69 celery.result.backend = amqp
71 celery.result.backend = amqp
70 celery.result.dburi = amqp://
72 celery.result.dburi = amqp://
71 celery.result.serialier = json
73 celery.result.serialier = json
72
74
73 #celery.send.task.error.emails = true
75 #celery.send.task.error.emails = true
74 #celery.amqp.task.result.expires = 18000
76 #celery.amqp.task.result.expires = 18000
75
77
76 celeryd.concurrency = 2
78 celeryd.concurrency = 2
77 #celeryd.log.file = celeryd.log
79 #celeryd.log.file = celeryd.log
78 celeryd.log.level = debug
80 celeryd.log.level = debug
79 celeryd.max.tasks.per.child = 1
81 celeryd.max.tasks.per.child = 1
80
82
81 #tasks will never be sent to the queue, but executed locally instead.
83 #tasks will never be sent to the queue, but executed locally instead.
82 celery.always.eager = false
84 celery.always.eager = false
83
85
84 ####################################
86 ####################################
85 ### BEAKER CACHE ####
87 ### BEAKER CACHE ####
86 ####################################
88 ####################################
87 beaker.cache.data_dir=%(here)s/data/cache/data
89 beaker.cache.data_dir=%(here)s/data/cache/data
88 beaker.cache.lock_dir=%(here)s/data/cache/lock
90 beaker.cache.lock_dir=%(here)s/data/cache/lock
89
91
90 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
92 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
91
93
92 beaker.cache.super_short_term.type=memory
94 beaker.cache.super_short_term.type=memory
93 beaker.cache.super_short_term.expire=10
95 beaker.cache.super_short_term.expire=10
94 beaker.cache.super_short_term.key_length = 256
96 beaker.cache.super_short_term.key_length = 256
95
97
96 beaker.cache.short_term.type=memory
98 beaker.cache.short_term.type=memory
97 beaker.cache.short_term.expire=60
99 beaker.cache.short_term.expire=60
98 beaker.cache.short_term.key_length = 256
100 beaker.cache.short_term.key_length = 256
99
101
100 beaker.cache.long_term.type=memory
102 beaker.cache.long_term.type=memory
101 beaker.cache.long_term.expire=36000
103 beaker.cache.long_term.expire=36000
102 beaker.cache.long_term.key_length = 256
104 beaker.cache.long_term.key_length = 256
103
105
104 beaker.cache.sql_cache_short.type=memory
106 beaker.cache.sql_cache_short.type=memory
105 beaker.cache.sql_cache_short.expire=10
107 beaker.cache.sql_cache_short.expire=10
106 beaker.cache.sql_cache_short.key_length = 256
108 beaker.cache.sql_cache_short.key_length = 256
107
109
108 beaker.cache.sql_cache_med.type=memory
110 beaker.cache.sql_cache_med.type=memory
109 beaker.cache.sql_cache_med.expire=360
111 beaker.cache.sql_cache_med.expire=360
110 beaker.cache.sql_cache_med.key_length = 256
112 beaker.cache.sql_cache_med.key_length = 256
111
113
112 beaker.cache.sql_cache_long.type=file
114 beaker.cache.sql_cache_long.type=file
113 beaker.cache.sql_cache_long.expire=3600
115 beaker.cache.sql_cache_long.expire=3600
114 beaker.cache.sql_cache_long.key_length = 256
116 beaker.cache.sql_cache_long.key_length = 256
115
117
116 ####################################
118 ####################################
117 ### BEAKER SESSION ####
119 ### BEAKER SESSION ####
118 ####################################
120 ####################################
119 ## Type of storage used for the session, current types are
121 ## Type of storage used for the session, current types are
120 ## dbm, file, memcached, database, and memory.
122 ## dbm, file, memcached, database, and memory.
121 ## The storage uses the Container API
123 ## The storage uses the Container API
122 ##that is also used by the cache system.
124 ##that is also used by the cache system.
123 beaker.session.type = file
125 beaker.session.type = file
124
126
125 beaker.session.key = rhodecode
127 beaker.session.key = rhodecode
126 beaker.session.secret = g654dcno0-9873jhgfreyu
128 beaker.session.secret = g654dcno0-9873jhgfreyu
127 beaker.session.timeout = 36000
129 beaker.session.timeout = 36000
128
130
129 ##auto save the session to not to use .save()
131 ##auto save the session to not to use .save()
130 beaker.session.auto = False
132 beaker.session.auto = False
131
133
132 ##true exire at browser close
134 ##true exire at browser close
133 #beaker.session.cookie_expires = 3600
135 #beaker.session.cookie_expires = 3600
134
136
135
137
136 ################################################################################
138 ################################################################################
137 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
139 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
138 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
140 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
139 ## execute malicious code after an exception is raised. ##
141 ## execute malicious code after an exception is raised. ##
140 ################################################################################
142 ################################################################################
141 set debug = false
143 set debug = false
142
144
143 ##################################
145 ##################################
144 ### LOGVIEW CONFIG ###
146 ### LOGVIEW CONFIG ###
145 ##################################
147 ##################################
146 logview.sqlalchemy = #faa
148 logview.sqlalchemy = #faa
147 logview.pylons.templating = #bfb
149 logview.pylons.templating = #bfb
148 logview.pylons.util = #eee
150 logview.pylons.util = #eee
149
151
150 #########################################################
152 #########################################################
151 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
153 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
152 #########################################################
154 #########################################################
153 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
155 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
154 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
156 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
155 sqlalchemy.db1.echo = false
157 sqlalchemy.db1.echo = false
156 sqlalchemy.db1.pool_recycle = 3600
158 sqlalchemy.db1.pool_recycle = 3600
157 sqlalchemy.convert_unicode = true
159 sqlalchemy.convert_unicode = true
158
160
159 ################################
161 ################################
160 ### LOGGING CONFIGURATION ####
162 ### LOGGING CONFIGURATION ####
161 ################################
163 ################################
162 [loggers]
164 [loggers]
163 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
165 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
164
166
165 [handlers]
167 [handlers]
166 keys = console, console_sql
168 keys = console, console_sql
167
169
168 [formatters]
170 [formatters]
169 keys = generic, color_formatter, color_formatter_sql
171 keys = generic, color_formatter, color_formatter_sql
170
172
171 #############
173 #############
172 ## LOGGERS ##
174 ## LOGGERS ##
173 #############
175 #############
174 [logger_root]
176 [logger_root]
175 level = NOTSET
177 level = NOTSET
176 handlers = console
178 handlers = console
177
179
178 [logger_routes]
180 [logger_routes]
179 level = DEBUG
181 level = DEBUG
180 handlers =
182 handlers =
181 qualname = routes.middleware
183 qualname = routes.middleware
182 # "level = DEBUG" logs the route matched and routing variables.
184 # "level = DEBUG" logs the route matched and routing variables.
183 propagate = 1
185 propagate = 1
184
186
185 [logger_beaker]
187 [logger_beaker]
186 level = DEBUG
188 level = DEBUG
187 handlers =
189 handlers =
188 qualname = beaker.container
190 qualname = beaker.container
189 propagate = 1
191 propagate = 1
190
192
191 [logger_templates]
193 [logger_templates]
192 level = INFO
194 level = INFO
193 handlers =
195 handlers =
194 qualname = pylons.templating
196 qualname = pylons.templating
195 propagate = 1
197 propagate = 1
196
198
197 [logger_rhodecode]
199 [logger_rhodecode]
198 level = DEBUG
200 level = DEBUG
199 handlers =
201 handlers =
200 qualname = rhodecode
202 qualname = rhodecode
201 propagate = 1
203 propagate = 1
202
204
203 [logger_sqlalchemy]
205 [logger_sqlalchemy]
204 level = INFO
206 level = INFO
205 handlers = console_sql
207 handlers = console_sql
206 qualname = sqlalchemy.engine
208 qualname = sqlalchemy.engine
207 propagate = 0
209 propagate = 0
208
210
209 ##############
211 ##############
210 ## HANDLERS ##
212 ## HANDLERS ##
211 ##############
213 ##############
212
214
213 [handler_console]
215 [handler_console]
214 class = StreamHandler
216 class = StreamHandler
215 args = (sys.stderr,)
217 args = (sys.stderr,)
216 level = INFO
218 level = INFO
217 formatter = generic
219 formatter = generic
218
220
219 [handler_console_sql]
221 [handler_console_sql]
220 class = StreamHandler
222 class = StreamHandler
221 args = (sys.stderr,)
223 args = (sys.stderr,)
222 level = WARN
224 level = WARN
223 formatter = generic
225 formatter = generic
224
226
225 ################
227 ################
226 ## FORMATTERS ##
228 ## FORMATTERS ##
227 ################
229 ################
228
230
229 [formatter_generic]
231 [formatter_generic]
230 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
232 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
231 datefmt = %Y-%m-%d %H:%M:%S
233 datefmt = %Y-%m-%d %H:%M:%S
232
234
233 [formatter_color_formatter]
235 [formatter_color_formatter]
234 class=rhodecode.lib.colored_formatter.ColorFormatter
236 class=rhodecode.lib.colored_formatter.ColorFormatter
235 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
237 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
236 datefmt = %Y-%m-%d %H:%M:%S
238 datefmt = %Y-%m-%d %H:%M:%S
237
239
238 [formatter_color_formatter_sql]
240 [formatter_color_formatter_sql]
239 class=rhodecode.lib.colored_formatter.ColorFormatterSql
241 class=rhodecode.lib.colored_formatter.ColorFormatterSql
240 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
242 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
241 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
243 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,663 +1,677 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.auth
3 rhodecode.lib.auth
4 ~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~
5
5
6 authentication and permission libraries
6 authentication and permission libraries
7
7
8 :created_on: Apr 4, 2010
8 :created_on: Apr 4, 2010
9 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
9 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :license: GPLv3, see COPYING for more details.
10 :license: GPLv3, see COPYING for more details.
11 """
11 """
12 # This program is free software: you can redistribute it and/or modify
12 # This program is free software: you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation, either version 3 of the License, or
14 # the Free Software Foundation, either version 3 of the License, or
15 # (at your option) any later version.
15 # (at your option) any later version.
16 #
16 #
17 # This program is distributed in the hope that it will be useful,
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU General Public License for more details.
20 # GNU General Public License for more details.
21 #
21 #
22 # You should have received a copy of the GNU General Public License
22 # You should have received a copy of the GNU General Public License
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24
24
25 import random
25 import random
26 import logging
26 import logging
27 import traceback
27 import traceback
28 import hashlib
28 import hashlib
29
29
30 from tempfile import _RandomNameSequence
30 from tempfile import _RandomNameSequence
31 from decorator import decorator
31 from decorator import decorator
32
32
33 from pylons import config, session, url, request
33 from pylons import config, session, url, request
34 from pylons.controllers.util import abort, redirect
34 from pylons.controllers.util import abort, redirect
35 from pylons.i18n.translation import _
35 from pylons.i18n.translation import _
36
36
37 from rhodecode import __platform__, PLATFORM_WIN, PLATFORM_OTHERS
37 from rhodecode import __platform__, PLATFORM_WIN, PLATFORM_OTHERS
38
38
39 if __platform__ in PLATFORM_WIN:
39 if __platform__ in PLATFORM_WIN:
40 from hashlib import sha256
40 from hashlib import sha256
41 if __platform__ in PLATFORM_OTHERS:
41 if __platform__ in PLATFORM_OTHERS:
42 import bcrypt
42 import bcrypt
43
43
44 from rhodecode.lib import str2bool, safe_unicode
44 from rhodecode.lib import str2bool, safe_unicode
45 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
45 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
46 from rhodecode.lib.utils import get_repo_slug
46 from rhodecode.lib.utils import get_repo_slug
47 from rhodecode.lib.auth_ldap import AuthLdap
47 from rhodecode.lib.auth_ldap import AuthLdap
48
48
49 from rhodecode.model import meta
49 from rhodecode.model import meta
50 from rhodecode.model.user import UserModel
50 from rhodecode.model.user import UserModel
51 from rhodecode.model.db import Permission, RhodeCodeSettings, User
51 from rhodecode.model.db import Permission, RhodeCodeSettings, User
52
52
53 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
54
54
55
55
56 class PasswordGenerator(object):
56 class PasswordGenerator(object):
57 """This is a simple class for generating password from
57 """This is a simple class for generating password from
58 different sets of characters
58 different sets of characters
59 usage:
59 usage:
60 passwd_gen = PasswordGenerator()
60 passwd_gen = PasswordGenerator()
61 #print 8-letter password containing only big and small letters
61 #print 8-letter password containing only big and small letters
62 of alphabet
62 of alphabet
63 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
63 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
64 """
64 """
65 ALPHABETS_NUM = r'''1234567890'''
65 ALPHABETS_NUM = r'''1234567890'''
66 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''
66 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''
67 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''
67 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''
68 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''
68 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''
69 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL \
69 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL \
70 + ALPHABETS_NUM + ALPHABETS_SPECIAL
70 + ALPHABETS_NUM + ALPHABETS_SPECIAL
71 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM
71 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM
72 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
72 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
73 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM
73 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM
74 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM
74 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM
75
75
76 def __init__(self, passwd=''):
76 def __init__(self, passwd=''):
77 self.passwd = passwd
77 self.passwd = passwd
78
78
79 def gen_password(self, len, type):
79 def gen_password(self, len, type):
80 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
80 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
81 return self.passwd
81 return self.passwd
82
82
83
83
84 class RhodeCodeCrypto(object):
84 class RhodeCodeCrypto(object):
85
85
86 @classmethod
86 @classmethod
87 def hash_string(cls, str_):
87 def hash_string(cls, str_):
88 """
88 """
89 Cryptographic function used for password hashing based on pybcrypt
89 Cryptographic function used for password hashing based on pybcrypt
90 or pycrypto in windows
90 or pycrypto in windows
91
91
92 :param password: password to hash
92 :param password: password to hash
93 """
93 """
94 if __platform__ in PLATFORM_WIN:
94 if __platform__ in PLATFORM_WIN:
95 return sha256(str_).hexdigest()
95 return sha256(str_).hexdigest()
96 elif __platform__ in PLATFORM_OTHERS:
96 elif __platform__ in PLATFORM_OTHERS:
97 return bcrypt.hashpw(str_, bcrypt.gensalt(10))
97 return bcrypt.hashpw(str_, bcrypt.gensalt(10))
98 else:
98 else:
99 raise Exception('Unknown or unsupported platform %s' \
99 raise Exception('Unknown or unsupported platform %s' \
100 % __platform__)
100 % __platform__)
101
101
102 @classmethod
102 @classmethod
103 def hash_check(cls, password, hashed):
103 def hash_check(cls, password, hashed):
104 """
104 """
105 Checks matching password with it's hashed value, runs different
105 Checks matching password with it's hashed value, runs different
106 implementation based on platform it runs on
106 implementation based on platform it runs on
107
107
108 :param password: password
108 :param password: password
109 :param hashed: password in hashed form
109 :param hashed: password in hashed form
110 """
110 """
111
111
112 if __platform__ in PLATFORM_WIN:
112 if __platform__ in PLATFORM_WIN:
113 return sha256(password).hexdigest() == hashed
113 return sha256(password).hexdigest() == hashed
114 elif __platform__ in PLATFORM_OTHERS:
114 elif __platform__ in PLATFORM_OTHERS:
115 return bcrypt.hashpw(password, hashed) == hashed
115 return bcrypt.hashpw(password, hashed) == hashed
116 else:
116 else:
117 raise Exception('Unknown or unsupported platform %s' \
117 raise Exception('Unknown or unsupported platform %s' \
118 % __platform__)
118 % __platform__)
119
119
120
120
121 def get_crypt_password(password):
121 def get_crypt_password(password):
122 return RhodeCodeCrypto.hash_string(password)
122 return RhodeCodeCrypto.hash_string(password)
123
123
124
124
125 def check_password(password, hashed):
125 def check_password(password, hashed):
126 return RhodeCodeCrypto.hash_check(password, hashed)
126 return RhodeCodeCrypto.hash_check(password, hashed)
127
127
128 def generate_api_key(str_, salt=None):
129 """
130 Generates API KEY from given string
128
131
129 def generate_api_key(username, salt=None):
132 :param str_:
133 :param salt:
134 """
135
130 if salt is None:
136 if salt is None:
131 salt = _RandomNameSequence().next()
137 salt = _RandomNameSequence().next()
132
138
133 return hashlib.sha1(username + salt).hexdigest()
139 return hashlib.sha1(str_ + salt).hexdigest()
134
140
135
141
136 def authfunc(environ, username, password):
142 def authfunc(environ, username, password):
137 """Dummy authentication function used in Mercurial/Git/ and access control,
143 """
144 Dummy authentication function used in Mercurial/Git/ and access control,
138
145
139 :param environ: needed only for using in Basic auth
146 :param environ: needed only for using in Basic auth
140 """
147 """
141 return authenticate(username, password)
148 return authenticate(username, password)
142
149
143
150
144 def authenticate(username, password):
151 def authenticate(username, password):
145 """Authentication function used for access control,
152 """
153 Authentication function used for access control,
146 firstly checks for db authentication then if ldap is enabled for ldap
154 firstly checks for db authentication then if ldap is enabled for ldap
147 authentication, also creates ldap user if not in database
155 authentication, also creates ldap user if not in database
148
156
149 :param username: username
157 :param username: username
150 :param password: password
158 :param password: password
151 """
159 """
152
160
153 user_model = UserModel()
161 user_model = UserModel()
154 user = User.get_by_username(username)
162 user = User.get_by_username(username)
155
163
156 log.debug('Authenticating user using RhodeCode account')
164 log.debug('Authenticating user using RhodeCode account')
157 if user is not None and not user.ldap_dn:
165 if user is not None and not user.ldap_dn:
158 if user.active:
166 if user.active:
159 if user.username == 'default' and user.active:
167 if user.username == 'default' and user.active:
160 log.info('user %s authenticated correctly as anonymous user',
168 log.info('user %s authenticated correctly as anonymous user',
161 username)
169 username)
162 return True
170 return True
163
171
164 elif user.username == username and check_password(password,
172 elif user.username == username and check_password(password,
165 user.password):
173 user.password):
166 log.info('user %s authenticated correctly', username)
174 log.info('user %s authenticated correctly', username)
167 return True
175 return True
168 else:
176 else:
169 log.warning('user %s is disabled', username)
177 log.warning('user %s is disabled', username)
170
178
171 else:
179 else:
172 log.debug('Regular authentication failed')
180 log.debug('Regular authentication failed')
173 user_obj = User.get_by_username(username, case_insensitive=True)
181 user_obj = User.get_by_username(username, case_insensitive=True)
174
182
175 if user_obj is not None and not user_obj.ldap_dn:
183 if user_obj is not None and not user_obj.ldap_dn:
176 log.debug('this user already exists as non ldap')
184 log.debug('this user already exists as non ldap')
177 return False
185 return False
178
186
179 ldap_settings = RhodeCodeSettings.get_ldap_settings()
187 ldap_settings = RhodeCodeSettings.get_ldap_settings()
180 #======================================================================
188 #======================================================================
181 # FALLBACK TO LDAP AUTH IF ENABLE
189 # FALLBACK TO LDAP AUTH IF ENABLE
182 #======================================================================
190 #======================================================================
183 if str2bool(ldap_settings.get('ldap_active')):
191 if str2bool(ldap_settings.get('ldap_active')):
184 log.debug("Authenticating user using ldap")
192 log.debug("Authenticating user using ldap")
185 kwargs = {
193 kwargs = {
186 'server': ldap_settings.get('ldap_host', ''),
194 'server': ldap_settings.get('ldap_host', ''),
187 'base_dn': ldap_settings.get('ldap_base_dn', ''),
195 'base_dn': ldap_settings.get('ldap_base_dn', ''),
188 'port': ldap_settings.get('ldap_port'),
196 'port': ldap_settings.get('ldap_port'),
189 'bind_dn': ldap_settings.get('ldap_dn_user'),
197 'bind_dn': ldap_settings.get('ldap_dn_user'),
190 'bind_pass': ldap_settings.get('ldap_dn_pass'),
198 'bind_pass': ldap_settings.get('ldap_dn_pass'),
191 'tls_kind': ldap_settings.get('ldap_tls_kind'),
199 'tls_kind': ldap_settings.get('ldap_tls_kind'),
192 'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'),
200 'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'),
193 'ldap_filter': ldap_settings.get('ldap_filter'),
201 'ldap_filter': ldap_settings.get('ldap_filter'),
194 'search_scope': ldap_settings.get('ldap_search_scope'),
202 'search_scope': ldap_settings.get('ldap_search_scope'),
195 'attr_login': ldap_settings.get('ldap_attr_login'),
203 'attr_login': ldap_settings.get('ldap_attr_login'),
196 'ldap_version': 3,
204 'ldap_version': 3,
197 }
205 }
198 log.debug('Checking for ldap authentication')
206 log.debug('Checking for ldap authentication')
199 try:
207 try:
200 aldap = AuthLdap(**kwargs)
208 aldap = AuthLdap(**kwargs)
201 (user_dn, ldap_attrs) = aldap.authenticate_ldap(username,
209 (user_dn, ldap_attrs) = aldap.authenticate_ldap(username,
202 password)
210 password)
203 log.debug('Got ldap DN response %s', user_dn)
211 log.debug('Got ldap DN response %s', user_dn)
204
212
205 get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\
213 get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\
206 .get(k), [''])[0]
214 .get(k), [''])[0]
207
215
208 user_attrs = {
216 user_attrs = {
209 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')),
217 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')),
210 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')),
218 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')),
211 'email': get_ldap_attr('ldap_attr_email'),
219 'email': get_ldap_attr('ldap_attr_email'),
212 }
220 }
213
221
214 if user_model.create_ldap(username, password, user_dn,
222 if user_model.create_ldap(username, password, user_dn,
215 user_attrs):
223 user_attrs):
216 log.info('created new ldap user %s', username)
224 log.info('created new ldap user %s', username)
217
225
218 return True
226 return True
219 except (LdapUsernameError, LdapPasswordError,):
227 except (LdapUsernameError, LdapPasswordError,):
220 pass
228 pass
221 except (Exception,):
229 except (Exception,):
222 log.error(traceback.format_exc())
230 log.error(traceback.format_exc())
223 pass
231 pass
224 return False
232 return False
225
233
226 def login_container_auth(username):
234 def login_container_auth(username):
227 user = User.get_by_username(username)
235 user = User.get_by_username(username)
228 if user is None:
236 if user is None:
229 user_model = UserModel()
237 user_model = UserModel()
230 user_attrs = {
238 user_attrs = {
231 'name': username,
239 'name': username,
232 'lastname': None,
240 'lastname': None,
233 'email': None,
241 'email': None,
234 }
242 }
235 if not user_model.create_for_container_auth(username, user_attrs):
243 user = user_model.create_for_container_auth(username, user_attrs)
244 if not user:
236 return None
245 return None
237 user = User.get_by_username(username)
238 log.info('User %s was created by container authentication', username)
246 log.info('User %s was created by container authentication', username)
239
247
240 if not user.active:
248 if not user.active:
241 return None
249 return None
242
250
243 user.update_lastlogin()
251 user.update_lastlogin()
244 log.debug('User %s is now logged in by container authentication', user.username)
252 log.debug('User %s is now logged in by container authentication',
253 user.username)
245 return user
254 return user
246
255
247 def get_container_username(environ, cfg=config):
256 def get_container_username(environ, cfg):
248 from paste.httpheaders import REMOTE_USER
257 from paste.httpheaders import REMOTE_USER
249 from paste.deploy.converters import asbool
258 from paste.deploy.converters import asbool
250
259
260 proxy_pass_enabled = asbool(cfg.get('proxypass_auth_enabled', False))
251 username = REMOTE_USER(environ)
261 username = REMOTE_USER(environ)
252
262
253 if not username and asbool(cfg.get('proxypass_auth_enabled', False)):
263 if not username and proxy_pass_enabled:
254 username = environ.get('HTTP_X_FORWARDED_USER')
264 username = environ.get('HTTP_X_FORWARDED_USER')
255
265
256 if username:
266 if username and proxy_pass_enabled:
257 #Removing realm and domain from username
267 # Removing realm and domain from username
258 username = username.partition('@')[0]
268 username = username.partition('@')[0]
259 username = username.rpartition('\\')[2]
269 username = username.rpartition('\\')[2]
260 log.debug('Received username %s from container', username)
270 log.debug('Received username %s from container', username)
261
271
262 return username
272 return username
263
273
264 class AuthUser(object):
274 class AuthUser(object):
265 """
275 """
266 A simple object that handles all attributes of user in RhodeCode
276 A simple object that handles all attributes of user in RhodeCode
267
277
268 It does lookup based on API key,given user, or user present in session
278 It does lookup based on API key,given user, or user present in session
269 Then it fills all required information for such user. It also checks if
279 Then it fills all required information for such user. It also checks if
270 anonymous access is enabled and if so, it returns default user as logged
280 anonymous access is enabled and if so, it returns default user as logged
271 in
281 in
272 """
282 """
273
283
274 def __init__(self, user_id=None, api_key=None, username=None):
284 def __init__(self, user_id=None, api_key=None, username=None):
275
285
276 self.user_id = user_id
286 self.user_id = user_id
277 self.api_key = None
287 self.api_key = None
278 self.username = username
288 self.username = username
279
289
280 self.name = ''
290 self.name = ''
281 self.lastname = ''
291 self.lastname = ''
282 self.email = ''
292 self.email = ''
283 self.is_authenticated = False
293 self.is_authenticated = False
284 self.admin = False
294 self.admin = False
285 self.permissions = {}
295 self.permissions = {}
286 self._api_key = api_key
296 self._api_key = api_key
287 self.propagate_data()
297 self.propagate_data()
288
298
289 def propagate_data(self):
299 def propagate_data(self):
290 user_model = UserModel()
300 user_model = UserModel()
291 self.anonymous_user = User.get_by_username('default')
301 self.anonymous_user = User.get_by_username('default')
292 is_user_loaded = False
302 is_user_loaded = False
303
304 # try go get user by api key
293 if self._api_key and self._api_key != self.anonymous_user.api_key:
305 if self._api_key and self._api_key != self.anonymous_user.api_key:
294 #try go get user by api key
295 log.debug('Auth User lookup by API KEY %s', self._api_key)
306 log.debug('Auth User lookup by API KEY %s', self._api_key)
296 is_user_loaded = user_model.fill_data(self, api_key=self._api_key)
307 is_user_loaded = user_model.fill_data(self, api_key=self._api_key)
297 elif self.user_id is not None \
308 # lookup by userid
298 and self.user_id != self.anonymous_user.user_id:
309 elif (self.user_id is not None and
310 self.user_id != self.anonymous_user.user_id):
299 log.debug('Auth User lookup by USER ID %s', self.user_id)
311 log.debug('Auth User lookup by USER ID %s', self.user_id)
300 is_user_loaded = user_model.fill_data(self, user_id=self.user_id)
312 is_user_loaded = user_model.fill_data(self, user_id=self.user_id)
313 # lookup by username
301 elif self.username:
314 elif self.username:
302 log.debug('Auth User lookup by USER NAME %s', self.username)
315 log.debug('Auth User lookup by USER NAME %s', self.username)
303 dbuser = login_container_auth(self.username)
316 dbuser = login_container_auth(self.username)
304 if dbuser is not None:
317 if dbuser is not None:
305 for k, v in dbuser.get_dict().items():
318 for k, v in dbuser.get_dict().items():
306 setattr(self, k, v)
319 setattr(self, k, v)
307 self.set_authenticated()
320 self.set_authenticated()
308 is_user_loaded = True
321 is_user_loaded = True
309
322
310 if not is_user_loaded:
323 if not is_user_loaded:
324 # if we cannot authenticate user try anonymous
311 if self.anonymous_user.active is True:
325 if self.anonymous_user.active is True:
312 user_model.fill_data(self,
326 user_model.fill_data(self,user_id=self.anonymous_user.user_id)
313 user_id=self.anonymous_user.user_id)
314 #then we set this user is logged in
327 # then we set this user is logged in
315 self.is_authenticated = True
328 self.is_authenticated = True
316 else:
329 else:
317 self.user_id = None
330 self.user_id = None
318 self.username = None
331 self.username = None
319 self.is_authenticated = False
332 self.is_authenticated = False
320
333
321 if not self.username:
334 if not self.username:
322 self.username = 'None'
335 self.username = 'None'
323
336
324 log.debug('Auth User is now %s', self)
337 log.debug('Auth User is now %s', self)
325 user_model.fill_perms(self)
338 user_model.fill_perms(self)
326
339
327 @property
340 @property
328 def is_admin(self):
341 def is_admin(self):
329 return self.admin
342 return self.admin
330
343
331 @property
344 @property
332 def full_contact(self):
345 def full_contact(self):
333 return '%s %s <%s>' % (self.name, self.lastname, self.email)
346 return '%s %s <%s>' % (self.name, self.lastname, self.email)
334
347
335 def __repr__(self):
348 def __repr__(self):
336 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
349 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
337 self.is_authenticated)
350 self.is_authenticated)
338
351
339 def set_authenticated(self, authenticated=True):
352 def set_authenticated(self, authenticated=True):
340
341 if self.user_id != self.anonymous_user.user_id:
353 if self.user_id != self.anonymous_user.user_id:
342 self.is_authenticated = authenticated
354 self.is_authenticated = authenticated
343
355
344
356
345 def set_available_permissions(config):
357 def set_available_permissions(config):
346 """This function will propagate pylons globals with all available defined
358 """
359 This function will propagate pylons globals with all available defined
347 permission given in db. We don't want to check each time from db for new
360 permission given in db. We don't want to check each time from db for new
348 permissions since adding a new permission also requires application restart
361 permissions since adding a new permission also requires application restart
349 ie. to decorate new views with the newly created permission
362 ie. to decorate new views with the newly created permission
350
363
351 :param config: current pylons config instance
364 :param config: current pylons config instance
352
365
353 """
366 """
354 log.info('getting information about all available permissions')
367 log.info('getting information about all available permissions')
355 try:
368 try:
356 sa = meta.Session()
369 sa = meta.Session()
357 all_perms = sa.query(Permission).all()
370 all_perms = sa.query(Permission).all()
358 except:
371 except:
359 pass
372 pass
360 finally:
373 finally:
361 meta.Session.remove()
374 meta.Session.remove()
362
375
363 config['available_permissions'] = [x.permission_name for x in all_perms]
376 config['available_permissions'] = [x.permission_name for x in all_perms]
364
377
365
378
366 #==============================================================================
379 #==============================================================================
367 # CHECK DECORATORS
380 # CHECK DECORATORS
368 #==============================================================================
381 #==============================================================================
369 class LoginRequired(object):
382 class LoginRequired(object):
370 """
383 """
371 Must be logged in to execute this function else
384 Must be logged in to execute this function else
372 redirect to login page
385 redirect to login page
373
386
374 :param api_access: if enabled this checks only for valid auth token
387 :param api_access: if enabled this checks only for valid auth token
375 and grants access based on valid token
388 and grants access based on valid token
376 """
389 """
377
390
378 def __init__(self, api_access=False):
391 def __init__(self, api_access=False):
379 self.api_access = api_access
392 self.api_access = api_access
380
393
381 def __call__(self, func):
394 def __call__(self, func):
382 return decorator(self.__wrapper, func)
395 return decorator(self.__wrapper, func)
383
396
384 def __wrapper(self, func, *fargs, **fkwargs):
397 def __wrapper(self, func, *fargs, **fkwargs):
385 cls = fargs[0]
398 cls = fargs[0]
386 user = cls.rhodecode_user
399 user = cls.rhodecode_user
387
400
388 api_access_ok = False
401 api_access_ok = False
389 if self.api_access:
402 if self.api_access:
390 log.debug('Checking API KEY access for %s', cls)
403 log.debug('Checking API KEY access for %s', cls)
391 if user.api_key == request.GET.get('api_key'):
404 if user.api_key == request.GET.get('api_key'):
392 api_access_ok = True
405 api_access_ok = True
393 else:
406 else:
394 log.debug("API KEY token not valid")
407 log.debug("API KEY token not valid")
395
408
396 log.debug('Checking if %s is authenticated @ %s', user.username, cls)
409 log.debug('Checking if %s is authenticated @ %s', user.username, cls)
397 if user.is_authenticated or api_access_ok:
410 if user.is_authenticated or api_access_ok:
398 log.debug('user %s is authenticated', user.username)
411 log.debug('user %s is authenticated', user.username)
399 return func(*fargs, **fkwargs)
412 return func(*fargs, **fkwargs)
400 else:
413 else:
401 log.warn('user %s NOT authenticated', user.username)
414 log.warn('user %s NOT authenticated', user.username)
402 p = url.current()
415 p = url.current()
403
416
404 log.debug('redirecting to login page with %s', p)
417 log.debug('redirecting to login page with %s', p)
405 return redirect(url('login_home', came_from=p))
418 return redirect(url('login_home', came_from=p))
406
419
407
420
408 class NotAnonymous(object):
421 class NotAnonymous(object):
409 """Must be logged in to execute this function else
422 """Must be logged in to execute this function else
410 redirect to login page"""
423 redirect to login page"""
411
424
412 def __call__(self, func):
425 def __call__(self, func):
413 return decorator(self.__wrapper, func)
426 return decorator(self.__wrapper, func)
414
427
415 def __wrapper(self, func, *fargs, **fkwargs):
428 def __wrapper(self, func, *fargs, **fkwargs):
416 cls = fargs[0]
429 cls = fargs[0]
417 self.user = cls.rhodecode_user
430 self.user = cls.rhodecode_user
418
431
419 log.debug('Checking if user is not anonymous @%s', cls)
432 log.debug('Checking if user is not anonymous @%s', cls)
420
433
421 anonymous = self.user.username == 'default'
434 anonymous = self.user.username == 'default'
422
435
423 if anonymous:
436 if anonymous:
424 p = url.current()
437 p = url.current()
425
438
426 import rhodecode.lib.helpers as h
439 import rhodecode.lib.helpers as h
427 h.flash(_('You need to be a registered user to '
440 h.flash(_('You need to be a registered user to '
428 'perform this action'),
441 'perform this action'),
429 category='warning')
442 category='warning')
430 return redirect(url('login_home', came_from=p))
443 return redirect(url('login_home', came_from=p))
431 else:
444 else:
432 return func(*fargs, **fkwargs)
445 return func(*fargs, **fkwargs)
433
446
434
447
435 class PermsDecorator(object):
448 class PermsDecorator(object):
436 """Base class for controller decorators"""
449 """Base class for controller decorators"""
437
450
438 def __init__(self, *required_perms):
451 def __init__(self, *required_perms):
439 available_perms = config['available_permissions']
452 available_perms = config['available_permissions']
440 for perm in required_perms:
453 for perm in required_perms:
441 if perm not in available_perms:
454 if perm not in available_perms:
442 raise Exception("'%s' permission is not defined" % perm)
455 raise Exception("'%s' permission is not defined" % perm)
443 self.required_perms = set(required_perms)
456 self.required_perms = set(required_perms)
444 self.user_perms = None
457 self.user_perms = None
445
458
446 def __call__(self, func):
459 def __call__(self, func):
447 return decorator(self.__wrapper, func)
460 return decorator(self.__wrapper, func)
448
461
449 def __wrapper(self, func, *fargs, **fkwargs):
462 def __wrapper(self, func, *fargs, **fkwargs):
450 cls = fargs[0]
463 cls = fargs[0]
451 self.user = cls.rhodecode_user
464 self.user = cls.rhodecode_user
452 self.user_perms = self.user.permissions
465 self.user_perms = self.user.permissions
453 log.debug('checking %s permissions %s for %s %s',
466 log.debug('checking %s permissions %s for %s %s',
454 self.__class__.__name__, self.required_perms, cls,
467 self.__class__.__name__, self.required_perms, cls,
455 self.user)
468 self.user)
456
469
457 if self.check_permissions():
470 if self.check_permissions():
458 log.debug('Permission granted for %s %s', cls, self.user)
471 log.debug('Permission granted for %s %s', cls, self.user)
459 return func(*fargs, **fkwargs)
472 return func(*fargs, **fkwargs)
460
473
461 else:
474 else:
462 log.warning('Permission denied for %s %s', cls, self.user)
475 log.warning('Permission denied for %s %s', cls, self.user)
463
476
464
477
465 anonymous = self.user.username == 'default'
478 anonymous = self.user.username == 'default'
466
479
467 if anonymous:
480 if anonymous:
468 p = url.current()
481 p = url.current()
469
482
470 import rhodecode.lib.helpers as h
483 import rhodecode.lib.helpers as h
471 h.flash(_('You need to be a signed in to '
484 h.flash(_('You need to be a signed in to '
472 'view this page'),
485 'view this page'),
473 category='warning')
486 category='warning')
474 return redirect(url('login_home', came_from=p))
487 return redirect(url('login_home', came_from=p))
475
488
476 else:
489 else:
477 #redirect with forbidden ret code
490 # redirect with forbidden ret code
478 return abort(403)
491 return abort(403)
479
492
480 def check_permissions(self):
493 def check_permissions(self):
481 """Dummy function for overriding"""
494 """Dummy function for overriding"""
482 raise Exception('You have to write this function in child class')
495 raise Exception('You have to write this function in child class')
483
496
484
497
485 class HasPermissionAllDecorator(PermsDecorator):
498 class HasPermissionAllDecorator(PermsDecorator):
486 """Checks for access permission for all given predicates. All of them
499 """Checks for access permission for all given predicates. All of them
487 have to be meet in order to fulfill the request
500 have to be meet in order to fulfill the request
488 """
501 """
489
502
490 def check_permissions(self):
503 def check_permissions(self):
491 if self.required_perms.issubset(self.user_perms.get('global')):
504 if self.required_perms.issubset(self.user_perms.get('global')):
492 return True
505 return True
493 return False
506 return False
494
507
495
508
496 class HasPermissionAnyDecorator(PermsDecorator):
509 class HasPermissionAnyDecorator(PermsDecorator):
497 """Checks for access permission for any of given predicates. In order to
510 """Checks for access permission for any of given predicates. In order to
498 fulfill the request any of predicates must be meet
511 fulfill the request any of predicates must be meet
499 """
512 """
500
513
501 def check_permissions(self):
514 def check_permissions(self):
502 if self.required_perms.intersection(self.user_perms.get('global')):
515 if self.required_perms.intersection(self.user_perms.get('global')):
503 return True
516 return True
504 return False
517 return False
505
518
506
519
507 class HasRepoPermissionAllDecorator(PermsDecorator):
520 class HasRepoPermissionAllDecorator(PermsDecorator):
508 """Checks for access permission for all given predicates for specific
521 """Checks for access permission for all given predicates for specific
509 repository. All of them have to be meet in order to fulfill the request
522 repository. All of them have to be meet in order to fulfill the request
510 """
523 """
511
524
512 def check_permissions(self):
525 def check_permissions(self):
513 repo_name = get_repo_slug(request)
526 repo_name = get_repo_slug(request)
514 try:
527 try:
515 user_perms = set([self.user_perms['repositories'][repo_name]])
528 user_perms = set([self.user_perms['repositories'][repo_name]])
516 except KeyError:
529 except KeyError:
517 return False
530 return False
518 if self.required_perms.issubset(user_perms):
531 if self.required_perms.issubset(user_perms):
519 return True
532 return True
520 return False
533 return False
521
534
522
535
523 class HasRepoPermissionAnyDecorator(PermsDecorator):
536 class HasRepoPermissionAnyDecorator(PermsDecorator):
524 """Checks for access permission for any of given predicates for specific
537 """Checks for access permission for any of given predicates for specific
525 repository. In order to fulfill the request any of predicates must be meet
538 repository. In order to fulfill the request any of predicates must be meet
526 """
539 """
527
540
528 def check_permissions(self):
541 def check_permissions(self):
529 repo_name = get_repo_slug(request)
542 repo_name = get_repo_slug(request)
530
543
531 try:
544 try:
532 user_perms = set([self.user_perms['repositories'][repo_name]])
545 user_perms = set([self.user_perms['repositories'][repo_name]])
533 except KeyError:
546 except KeyError:
534 return False
547 return False
535 if self.required_perms.intersection(user_perms):
548 if self.required_perms.intersection(user_perms):
536 return True
549 return True
537 return False
550 return False
538
551
539
552
540 #==============================================================================
553 #==============================================================================
541 # CHECK FUNCTIONS
554 # CHECK FUNCTIONS
542 #==============================================================================
555 #==============================================================================
543 class PermsFunction(object):
556 class PermsFunction(object):
544 """Base function for other check functions"""
557 """Base function for other check functions"""
545
558
546 def __init__(self, *perms):
559 def __init__(self, *perms):
547 available_perms = config['available_permissions']
560 available_perms = config['available_permissions']
548
561
549 for perm in perms:
562 for perm in perms:
550 if perm not in available_perms:
563 if perm not in available_perms:
551 raise Exception("'%s' permission in not defined" % perm)
564 raise Exception("'%s' permission in not defined" % perm)
552 self.required_perms = set(perms)
565 self.required_perms = set(perms)
553 self.user_perms = None
566 self.user_perms = None
554 self.granted_for = ''
567 self.granted_for = ''
555 self.repo_name = None
568 self.repo_name = None
556
569
557 def __call__(self, check_Location=''):
570 def __call__(self, check_Location=''):
558 user = session.get('rhodecode_user', False)
571 user = session.get('rhodecode_user', False)
559 if not user:
572 if not user:
560 return False
573 return False
561 self.user_perms = user.permissions
574 self.user_perms = user.permissions
562 self.granted_for = user
575 self.granted_for = user
563 log.debug('checking %s %s %s', self.__class__.__name__,
576 log.debug('checking %s %s %s', self.__class__.__name__,
564 self.required_perms, user)
577 self.required_perms, user)
565
578
566 if self.check_permissions():
579 if self.check_permissions():
567 log.debug('Permission granted %s @ %s', self.granted_for,
580 log.debug('Permission granted %s @ %s', self.granted_for,
568 check_Location or 'unspecified location')
581 check_Location or 'unspecified location')
569 return True
582 return True
570
583
571 else:
584 else:
572 log.warning('Permission denied for %s @ %s', self.granted_for,
585 log.warning('Permission denied for %s @ %s', self.granted_for,
573 check_Location or 'unspecified location')
586 check_Location or 'unspecified location')
574 return False
587 return False
575
588
576 def check_permissions(self):
589 def check_permissions(self):
577 """Dummy function for overriding"""
590 """Dummy function for overriding"""
578 raise Exception('You have to write this function in child class')
591 raise Exception('You have to write this function in child class')
579
592
580
593
581 class HasPermissionAll(PermsFunction):
594 class HasPermissionAll(PermsFunction):
582 def check_permissions(self):
595 def check_permissions(self):
583 if self.required_perms.issubset(self.user_perms.get('global')):
596 if self.required_perms.issubset(self.user_perms.get('global')):
584 return True
597 return True
585 return False
598 return False
586
599
587
600
588 class HasPermissionAny(PermsFunction):
601 class HasPermissionAny(PermsFunction):
589 def check_permissions(self):
602 def check_permissions(self):
590 if self.required_perms.intersection(self.user_perms.get('global')):
603 if self.required_perms.intersection(self.user_perms.get('global')):
591 return True
604 return True
592 return False
605 return False
593
606
594
607
595 class HasRepoPermissionAll(PermsFunction):
608 class HasRepoPermissionAll(PermsFunction):
596
609
597 def __call__(self, repo_name=None, check_Location=''):
610 def __call__(self, repo_name=None, check_Location=''):
598 self.repo_name = repo_name
611 self.repo_name = repo_name
599 return super(HasRepoPermissionAll, self).__call__(check_Location)
612 return super(HasRepoPermissionAll, self).__call__(check_Location)
600
613
601 def check_permissions(self):
614 def check_permissions(self):
602 if not self.repo_name:
615 if not self.repo_name:
603 self.repo_name = get_repo_slug(request)
616 self.repo_name = get_repo_slug(request)
604
617
605 try:
618 try:
606 self.user_perms = set([self.user_perms['reposit'
619 self.user_perms = set([self.user_perms['reposit'
607 'ories'][self.repo_name]])
620 'ories'][self.repo_name]])
608 except KeyError:
621 except KeyError:
609 return False
622 return False
610 self.granted_for = self.repo_name
623 self.granted_for = self.repo_name
611 if self.required_perms.issubset(self.user_perms):
624 if self.required_perms.issubset(self.user_perms):
612 return True
625 return True
613 return False
626 return False
614
627
615
628
616 class HasRepoPermissionAny(PermsFunction):
629 class HasRepoPermissionAny(PermsFunction):
617
630
618 def __call__(self, repo_name=None, check_Location=''):
631 def __call__(self, repo_name=None, check_Location=''):
619 self.repo_name = repo_name
632 self.repo_name = repo_name
620 return super(HasRepoPermissionAny, self).__call__(check_Location)
633 return super(HasRepoPermissionAny, self).__call__(check_Location)
621
634
622 def check_permissions(self):
635 def check_permissions(self):
623 if not self.repo_name:
636 if not self.repo_name:
624 self.repo_name = get_repo_slug(request)
637 self.repo_name = get_repo_slug(request)
625
638
626 try:
639 try:
627 self.user_perms = set([self.user_perms['reposi'
640 self.user_perms = set([self.user_perms['reposi'
628 'tories'][self.repo_name]])
641 'tories'][self.repo_name]])
629 except KeyError:
642 except KeyError:
630 return False
643 return False
631 self.granted_for = self.repo_name
644 self.granted_for = self.repo_name
632 if self.required_perms.intersection(self.user_perms):
645 if self.required_perms.intersection(self.user_perms):
633 return True
646 return True
634 return False
647 return False
635
648
636
649
637 #==============================================================================
650 #==============================================================================
638 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
651 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
639 #==============================================================================
652 #==============================================================================
640 class HasPermissionAnyMiddleware(object):
653 class HasPermissionAnyMiddleware(object):
641 def __init__(self, *perms):
654 def __init__(self, *perms):
642 self.required_perms = set(perms)
655 self.required_perms = set(perms)
643
656
644 def __call__(self, user, repo_name):
657 def __call__(self, user, repo_name):
645 usr = AuthUser(user.user_id)
658 usr = AuthUser(user.user_id)
646 try:
659 try:
647 self.user_perms = set([usr.permissions['repositories'][repo_name]])
660 self.user_perms = set([usr.permissions['repositories'][repo_name]])
648 except:
661 except:
649 self.user_perms = set()
662 self.user_perms = set()
650 self.granted_for = ''
663 self.granted_for = ''
651 self.username = user.username
664 self.username = user.username
652 self.repo_name = repo_name
665 self.repo_name = repo_name
653 return self.check_permissions()
666 return self.check_permissions()
654
667
655 def check_permissions(self):
668 def check_permissions(self):
656 log.debug('checking mercurial protocol '
669 log.debug('checking mercurial protocol '
657 'permissions %s for user:%s repository:%s', self.user_perms,
670 'permissions %s for user:%s repository:%s', self.user_perms,
658 self.username, self.repo_name)
671 self.username, self.repo_name)
659 if self.required_perms.intersection(self.user_perms):
672 if self.required_perms.intersection(self.user_perms):
660 log.debug('permission granted')
673 log.debug('permission granted')
661 return True
674 return True
662 log.debug('permission denied')
675 log.debug('permission denied')
663 return False
676 return False
677
@@ -1,92 +1,91 b''
1 """The base Controller API
1 """The base Controller API
2
2
3 Provides the BaseController class for subclassing.
3 Provides the BaseController class for subclassing.
4 """
4 """
5 import logging
5 import logging
6 import time
6 import time
7 from pylons import config, tmpl_context as c, request, session, url
7 from pylons import config, tmpl_context as c, request, session, url
8 from pylons.controllers import WSGIController
8 from pylons.controllers import WSGIController
9 from pylons.controllers.util import redirect
9 from pylons.controllers.util import redirect
10 from pylons.templating import render_mako as render
10 from pylons.templating import render_mako as render
11 from paste.deploy.converters import asbool
11 from paste.deploy.converters import asbool
12
12
13 from rhodecode import __version__
13 from rhodecode import __version__
14 from rhodecode.lib.auth import AuthUser, get_container_username
14 from rhodecode.lib.auth import AuthUser, get_container_username
15 from rhodecode.lib.utils import get_repo_slug
15 from rhodecode.lib.utils import get_repo_slug
16 from rhodecode.model import meta
16 from rhodecode.model import meta
17 from rhodecode.model.scm import ScmModel
17 from rhodecode.model.scm import ScmModel
18 from rhodecode import BACKENDS
18 from rhodecode import BACKENDS
19 from rhodecode.model.db import Repository
19 from rhodecode.model.db import Repository
20
20
21 log = logging.getLogger(__name__)
21 log = logging.getLogger(__name__)
22
22
23 class BaseController(WSGIController):
23 class BaseController(WSGIController):
24
24
25 def __before__(self):
25 def __before__(self):
26 c.rhodecode_version = __version__
26 c.rhodecode_version = __version__
27 c.rhodecode_name = config.get('rhodecode_title')
27 c.rhodecode_name = config.get('rhodecode_title')
28 c.ga_code = config.get('rhodecode_ga_code')
28 c.ga_code = config.get('rhodecode_ga_code')
29 c.repo_name = get_repo_slug(request)
29 c.repo_name = get_repo_slug(request)
30 c.backends = BACKENDS.keys()
30 c.backends = BACKENDS.keys()
31 self.cut_off_limit = int(config.get('cut_off_limit'))
31 self.cut_off_limit = int(config.get('cut_off_limit'))
32
32
33 self.sa = meta.Session()
33 self.sa = meta.Session()
34 self.scm_model = ScmModel(self.sa)
34 self.scm_model = ScmModel(self.sa)
35
35
36 #c.unread_journal = scm_model.get_unread_journal()
37
38 def __call__(self, environ, start_response):
36 def __call__(self, environ, start_response):
39 """Invoke the Controller"""
37 """Invoke the Controller"""
40 # WSGIController.__call__ dispatches to the Controller method
38 # WSGIController.__call__ dispatches to the Controller method
41 # the request is routed to. This routing information is
39 # the request is routed to. This routing information is
42 # available in environ['pylons.routes_dict']
40 # available in environ['pylons.routes_dict']
43 start = time.time()
41 start = time.time()
44 try:
42 try:
45 # putting this here makes sure that we update permissions each time
43 # make sure that we update permissions each time we call controller
46 api_key = request.GET.get('api_key')
44 api_key = request.GET.get('api_key')
47 user_id = getattr(session.get('rhodecode_user'), 'user_id', None)
45 user_id = getattr(session.get('rhodecode_user'), 'user_id', None)
48 if asbool(config.get('container_auth_enabled', False)):
46 if asbool(config.get('container_auth_enabled', False)):
49 username = get_container_username(environ)
47 username = get_container_username(environ)
50 else:
48 else:
51 username = None
49 username = None
52
50 auth_user = AuthUser(user_id, api_key, username)
53 self.rhodecode_user = c.rhodecode_user = AuthUser(user_id, api_key, username)
51 self.rhodecode_user = c.rhodecode_user = auth_user
54 if not self.rhodecode_user.is_authenticated and \
52 if not self.rhodecode_user.is_authenticated and \
55 self.rhodecode_user.user_id is not None:
53 self.rhodecode_user.user_id is not None:
56 self.rhodecode_user.set_authenticated(
54 self.rhodecode_user.set_authenticated(
57 getattr(session.get('rhodecode_user'),
55 getattr(session.get('rhodecode_user'),
58 'is_authenticated', False))
56 'is_authenticated', False))
59 session['rhodecode_user'] = self.rhodecode_user
57 session['rhodecode_user'] = self.rhodecode_user
60 session.save()
58 session.save()
61 return WSGIController.__call__(self, environ, start_response)
59 return WSGIController.__call__(self, environ, start_response)
62 finally:
60 finally:
63 log.debug('Request time: %.3fs' % (time.time()-start))
61 log.debug('Request time: %.3fs' % (time.time()-start))
64 meta.Session.remove()
62 meta.Session.remove()
65
63
66
64
67 class BaseRepoController(BaseController):
65 class BaseRepoController(BaseController):
68 """
66 """
69 Base class for controllers responsible for loading all needed data
67 Base class for controllers responsible for loading all needed data for
70 for those controllers, loaded items are
68 repository loaded items are
71
69
72 c.rhodecode_repo: instance of scm repository (taken from cache)
70 c.rhodecode_repo: instance of scm repository
73
71 c.rhodecode_db_repo: instance of db
72 c.repository_followers: number of followers
73 c.repository_forks: number of forks
74 """
74 """
75
75
76 def __before__(self):
76 def __before__(self):
77 super(BaseRepoController, self).__before__()
77 super(BaseRepoController, self).__before__()
78 if c.repo_name:
78 if c.repo_name:
79
79
80 c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
80 c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
81 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
81 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
82
82
83 if c.rhodecode_repo is None:
83 if c.rhodecode_repo is None:
84 log.error('%s this repository is present in database but it '
84 log.error('%s this repository is present in database but it '
85 'cannot be created as an scm instance', c.repo_name)
85 'cannot be created as an scm instance', c.repo_name)
86
86
87 redirect(url('home'))
87 redirect(url('home'))
88
88
89 c.repository_followers = \
89 c.repository_followers = self.scm_model.get_followers(c.repo_name)
90 self.scm_model.get_followers(c.repo_name)
91 c.repository_forks = self.scm_model.get_forks(c.repo_name)
90 c.repository_forks = self.scm_model.get_forks(c.repo_name)
92
91
@@ -1,422 +1,422 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.user
3 rhodecode.model.user
4 ~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~
5
5
6 users model for RhodeCode
6 users model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from pylons.i18n.translation import _
29 from pylons.i18n.translation import _
30
30
31 from rhodecode.lib import safe_unicode
31 from rhodecode.lib import safe_unicode
32 from rhodecode.model import BaseModel
32 from rhodecode.model import BaseModel
33 from rhodecode.model.caching_query import FromCache
33 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
34 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
35 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember
35 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember
36 from rhodecode.lib.exceptions import DefaultUserException, \
36 from rhodecode.lib.exceptions import DefaultUserException, \
37 UserOwnsReposException
37 UserOwnsReposException
38
38
39 from sqlalchemy.exc import DatabaseError
39 from sqlalchemy.exc import DatabaseError
40 from rhodecode.lib import generate_api_key
40 from rhodecode.lib import generate_api_key
41 from sqlalchemy.orm import joinedload
41 from sqlalchemy.orm import joinedload
42
42
43 log = logging.getLogger(__name__)
43 log = logging.getLogger(__name__)
44
44
45 PERM_WEIGHTS = {'repository.none': 0,
45 PERM_WEIGHTS = {'repository.none': 0,
46 'repository.read': 1,
46 'repository.read': 1,
47 'repository.write': 3,
47 'repository.write': 3,
48 'repository.admin': 3}
48 'repository.admin': 3}
49
49
50
50
51 class UserModel(BaseModel):
51 class UserModel(BaseModel):
52 def get(self, user_id, cache=False):
52 def get(self, user_id, cache=False):
53 user = self.sa.query(User)
53 user = self.sa.query(User)
54 if cache:
54 if cache:
55 user = user.options(FromCache("sql_cache_short",
55 user = user.options(FromCache("sql_cache_short",
56 "get_user_%s" % user_id))
56 "get_user_%s" % user_id))
57 return user.get(user_id)
57 return user.get(user_id)
58
58
59 def get_by_username(self, username, cache=False, case_insensitive=False):
59 def get_by_username(self, username, cache=False, case_insensitive=False):
60
60
61 if case_insensitive:
61 if case_insensitive:
62 user = self.sa.query(User).filter(User.username.ilike(username))
62 user = self.sa.query(User).filter(User.username.ilike(username))
63 else:
63 else:
64 user = self.sa.query(User)\
64 user = self.sa.query(User)\
65 .filter(User.username == username)
65 .filter(User.username == username)
66 if cache:
66 if cache:
67 user = user.options(FromCache("sql_cache_short",
67 user = user.options(FromCache("sql_cache_short",
68 "get_user_%s" % username))
68 "get_user_%s" % username))
69 return user.scalar()
69 return user.scalar()
70
70
71 def get_by_api_key(self, api_key, cache=False):
71 def get_by_api_key(self, api_key, cache=False):
72
72
73 user = self.sa.query(User)\
73 user = self.sa.query(User)\
74 .filter(User.api_key == api_key)
74 .filter(User.api_key == api_key)
75 if cache:
75 if cache:
76 user = user.options(FromCache("sql_cache_short",
76 user = user.options(FromCache("sql_cache_short",
77 "get_user_%s" % api_key))
77 "get_user_%s" % api_key))
78 return user.scalar()
78 return user.scalar()
79
79
80 def create(self, form_data):
80 def create(self, form_data):
81 try:
81 try:
82 new_user = User()
82 new_user = User()
83 for k, v in form_data.items():
83 for k, v in form_data.items():
84 setattr(new_user, k, v)
84 setattr(new_user, k, v)
85
85
86 new_user.api_key = generate_api_key(form_data['username'])
86 new_user.api_key = generate_api_key(form_data['username'])
87 self.sa.add(new_user)
87 self.sa.add(new_user)
88 self.sa.commit()
88 self.sa.commit()
89 return new_user
89 return new_user
90 except:
90 except:
91 log.error(traceback.format_exc())
91 log.error(traceback.format_exc())
92 self.sa.rollback()
92 self.sa.rollback()
93 raise
93 raise
94
94
95 def create_for_container_auth(self, username, attrs):
95 def create_for_container_auth(self, username, attrs):
96 """
96 """
97 Creates the given user if it's not already in the database
97 Creates the given user if it's not already in the database
98
98
99 :param username:
99 :param username:
100 :param attrs:
100 :param attrs:
101 """
101 """
102 if self.get_by_username(username, case_insensitive=True) is None:
102 if self.get_by_username(username, case_insensitive=True) is None:
103 try:
103 try:
104 new_user = User()
104 new_user = User()
105 new_user.username = username
105 new_user.username = username
106 new_user.password = None
106 new_user.password = None
107 new_user.api_key = generate_api_key(username)
107 new_user.api_key = generate_api_key(username)
108 new_user.email = attrs['email']
108 new_user.email = attrs['email']
109 new_user.active = True
109 new_user.active = attrs.get('active', True)
110 new_user.name = attrs['name']
110 new_user.name = attrs['name']
111 new_user.lastname = attrs['lastname']
111 new_user.lastname = attrs['lastname']
112
112
113 self.sa.add(new_user)
113 self.sa.add(new_user)
114 self.sa.commit()
114 self.sa.commit()
115 return True
115 return new_user
116 except (DatabaseError,):
116 except (DatabaseError,):
117 log.error(traceback.format_exc())
117 log.error(traceback.format_exc())
118 self.sa.rollback()
118 self.sa.rollback()
119 raise
119 raise
120 log.debug('User %s already exists. Skipping creation of account for container auth.',
120 log.debug('User %s already exists. Skipping creation of account'
121 username)
121 ' for container auth.', username)
122 return False
122 return None
123
123
124 def create_ldap(self, username, password, user_dn, attrs):
124 def create_ldap(self, username, password, user_dn, attrs):
125 """
125 """
126 Checks if user is in database, if not creates this user marked
126 Checks if user is in database, if not creates this user marked
127 as ldap user
127 as ldap user
128
128
129 :param username:
129 :param username:
130 :param password:
130 :param password:
131 :param user_dn:
131 :param user_dn:
132 :param attrs:
132 :param attrs:
133 """
133 """
134 from rhodecode.lib.auth import get_crypt_password
134 from rhodecode.lib.auth import get_crypt_password
135 log.debug('Checking for such ldap account in RhodeCode database')
135 log.debug('Checking for such ldap account in RhodeCode database')
136 if self.get_by_username(username, case_insensitive=True) is None:
136 if self.get_by_username(username, case_insensitive=True) is None:
137 try:
137 try:
138 new_user = User()
138 new_user = User()
139 # add ldap account always lowercase
139 # add ldap account always lowercase
140 new_user.username = username.lower()
140 new_user.username = username.lower()
141 new_user.password = get_crypt_password(password)
141 new_user.password = get_crypt_password(password)
142 new_user.api_key = generate_api_key(username)
142 new_user.api_key = generate_api_key(username)
143 new_user.email = attrs['email']
143 new_user.email = attrs['email']
144 new_user.active = attrs.get('active',True)
144 new_user.active = attrs.get('active', True)
145 new_user.ldap_dn = safe_unicode(user_dn)
145 new_user.ldap_dn = safe_unicode(user_dn)
146 new_user.name = attrs['name']
146 new_user.name = attrs['name']
147 new_user.lastname = attrs['lastname']
147 new_user.lastname = attrs['lastname']
148
148
149 self.sa.add(new_user)
149 self.sa.add(new_user)
150 self.sa.commit()
150 self.sa.commit()
151 return True
151 return new_user
152 except (DatabaseError,):
152 except (DatabaseError,):
153 log.error(traceback.format_exc())
153 log.error(traceback.format_exc())
154 self.sa.rollback()
154 self.sa.rollback()
155 raise
155 raise
156 log.debug('this %s user exists skipping creation of ldap account',
156 log.debug('this %s user exists skipping creation of ldap account',
157 username)
157 username)
158 return False
158 return None
159
159
160 def create_registration(self, form_data):
160 def create_registration(self, form_data):
161 from rhodecode.lib.celerylib import tasks, run_task
161 from rhodecode.lib.celerylib import tasks, run_task
162 try:
162 try:
163 new_user = User()
163 new_user = User()
164 for k, v in form_data.items():
164 for k, v in form_data.items():
165 if k != 'admin':
165 if k != 'admin':
166 setattr(new_user, k, v)
166 setattr(new_user, k, v)
167
167
168 self.sa.add(new_user)
168 self.sa.add(new_user)
169 self.sa.commit()
169 self.sa.commit()
170 body = ('New user registration\n'
170 body = ('New user registration\n'
171 'username: %s\n'
171 'username: %s\n'
172 'email: %s\n')
172 'email: %s\n')
173 body = body % (form_data['username'], form_data['email'])
173 body = body % (form_data['username'], form_data['email'])
174
174
175 run_task(tasks.send_email, None,
175 run_task(tasks.send_email, None,
176 _('[RhodeCode] New User registration'),
176 _('[RhodeCode] New User registration'),
177 body)
177 body)
178 except:
178 except:
179 log.error(traceback.format_exc())
179 log.error(traceback.format_exc())
180 self.sa.rollback()
180 self.sa.rollback()
181 raise
181 raise
182
182
183 def update(self, user_id, form_data):
183 def update(self, user_id, form_data):
184 try:
184 try:
185 user = self.get(user_id, cache=False)
185 user = self.get(user_id, cache=False)
186 if user.username == 'default':
186 if user.username == 'default':
187 raise DefaultUserException(
187 raise DefaultUserException(
188 _("You can't Edit this user since it's"
188 _("You can't Edit this user since it's"
189 " crucial for entire application"))
189 " crucial for entire application"))
190
190
191 for k, v in form_data.items():
191 for k, v in form_data.items():
192 if k == 'new_password' and v != '':
192 if k == 'new_password' and v != '':
193 user.password = v
193 user.password = v
194 user.api_key = generate_api_key(user.username)
194 user.api_key = generate_api_key(user.username)
195 else:
195 else:
196 setattr(user, k, v)
196 setattr(user, k, v)
197
197
198 self.sa.add(user)
198 self.sa.add(user)
199 self.sa.commit()
199 self.sa.commit()
200 except:
200 except:
201 log.error(traceback.format_exc())
201 log.error(traceback.format_exc())
202 self.sa.rollback()
202 self.sa.rollback()
203 raise
203 raise
204
204
205 def update_my_account(self, user_id, form_data):
205 def update_my_account(self, user_id, form_data):
206 try:
206 try:
207 user = self.get(user_id, cache=False)
207 user = self.get(user_id, cache=False)
208 if user.username == 'default':
208 if user.username == 'default':
209 raise DefaultUserException(
209 raise DefaultUserException(
210 _("You can't Edit this user since it's"
210 _("You can't Edit this user since it's"
211 " crucial for entire application"))
211 " crucial for entire application"))
212 for k, v in form_data.items():
212 for k, v in form_data.items():
213 if k == 'new_password' and v != '':
213 if k == 'new_password' and v != '':
214 user.password = v
214 user.password = v
215 user.api_key = generate_api_key(user.username)
215 user.api_key = generate_api_key(user.username)
216 else:
216 else:
217 if k not in ['admin', 'active']:
217 if k not in ['admin', 'active']:
218 setattr(user, k, v)
218 setattr(user, k, v)
219
219
220 self.sa.add(user)
220 self.sa.add(user)
221 self.sa.commit()
221 self.sa.commit()
222 except:
222 except:
223 log.error(traceback.format_exc())
223 log.error(traceback.format_exc())
224 self.sa.rollback()
224 self.sa.rollback()
225 raise
225 raise
226
226
227 def delete(self, user_id):
227 def delete(self, user_id):
228 try:
228 try:
229 user = self.get(user_id, cache=False)
229 user = self.get(user_id, cache=False)
230 if user.username == 'default':
230 if user.username == 'default':
231 raise DefaultUserException(
231 raise DefaultUserException(
232 _("You can't remove this user since it's"
232 _("You can't remove this user since it's"
233 " crucial for entire application"))
233 " crucial for entire application"))
234 if user.repositories:
234 if user.repositories:
235 raise UserOwnsReposException(_('This user still owns %s '
235 raise UserOwnsReposException(_('This user still owns %s '
236 'repositories and cannot be '
236 'repositories and cannot be '
237 'removed. Switch owners or '
237 'removed. Switch owners or '
238 'remove those repositories') \
238 'remove those repositories') \
239 % user.repositories)
239 % user.repositories)
240 self.sa.delete(user)
240 self.sa.delete(user)
241 self.sa.commit()
241 self.sa.commit()
242 except:
242 except:
243 log.error(traceback.format_exc())
243 log.error(traceback.format_exc())
244 self.sa.rollback()
244 self.sa.rollback()
245 raise
245 raise
246
246
247 def reset_password_link(self, data):
247 def reset_password_link(self, data):
248 from rhodecode.lib.celerylib import tasks, run_task
248 from rhodecode.lib.celerylib import tasks, run_task
249 run_task(tasks.send_password_link, data['email'])
249 run_task(tasks.send_password_link, data['email'])
250
250
251 def reset_password(self, data):
251 def reset_password(self, data):
252 from rhodecode.lib.celerylib import tasks, run_task
252 from rhodecode.lib.celerylib import tasks, run_task
253 run_task(tasks.reset_user_password, data['email'])
253 run_task(tasks.reset_user_password, data['email'])
254
254
255 def fill_data(self, auth_user, user_id=None, api_key=None):
255 def fill_data(self, auth_user, user_id=None, api_key=None):
256 """
256 """
257 Fetches auth_user by user_id,or api_key if present.
257 Fetches auth_user by user_id,or api_key if present.
258 Fills auth_user attributes with those taken from database.
258 Fills auth_user attributes with those taken from database.
259 Additionally set's is_authenitated if lookup fails
259 Additionally set's is_authenitated if lookup fails
260 present in database
260 present in database
261
261
262 :param auth_user: instance of user to set attributes
262 :param auth_user: instance of user to set attributes
263 :param user_id: user id to fetch by
263 :param user_id: user id to fetch by
264 :param api_key: api key to fetch by
264 :param api_key: api key to fetch by
265 """
265 """
266 if user_id is None and api_key is None:
266 if user_id is None and api_key is None:
267 raise Exception('You need to pass user_id or api_key')
267 raise Exception('You need to pass user_id or api_key')
268
268
269 try:
269 try:
270 if api_key:
270 if api_key:
271 dbuser = self.get_by_api_key(api_key)
271 dbuser = self.get_by_api_key(api_key)
272 else:
272 else:
273 dbuser = self.get(user_id)
273 dbuser = self.get(user_id)
274
274
275 if dbuser is not None and dbuser.active:
275 if dbuser is not None and dbuser.active:
276 log.debug('filling %s data', dbuser)
276 log.debug('filling %s data', dbuser)
277 for k, v in dbuser.get_dict().items():
277 for k, v in dbuser.get_dict().items():
278 setattr(auth_user, k, v)
278 setattr(auth_user, k, v)
279 else:
279 else:
280 return False
280 return False
281
281
282 except:
282 except:
283 log.error(traceback.format_exc())
283 log.error(traceback.format_exc())
284 auth_user.is_authenticated = False
284 auth_user.is_authenticated = False
285 return False
285 return False
286
286
287 return True
287 return True
288
288
289 def fill_perms(self, user):
289 def fill_perms(self, user):
290 """
290 """
291 Fills user permission attribute with permissions taken from database
291 Fills user permission attribute with permissions taken from database
292 works for permissions given for repositories, and for permissions that
292 works for permissions given for repositories, and for permissions that
293 are granted to groups
293 are granted to groups
294
294
295 :param user: user instance to fill his perms
295 :param user: user instance to fill his perms
296 """
296 """
297
297
298 user.permissions['repositories'] = {}
298 user.permissions['repositories'] = {}
299 user.permissions['global'] = set()
299 user.permissions['global'] = set()
300
300
301 #======================================================================
301 #======================================================================
302 # fetch default permissions
302 # fetch default permissions
303 #======================================================================
303 #======================================================================
304 default_user = self.get_by_username('default', cache=True)
304 default_user = self.get_by_username('default', cache=True)
305
305
306 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
306 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\
307 .join((Repository, RepoToPerm.repository_id ==
307 .join((Repository, RepoToPerm.repository_id ==
308 Repository.repo_id))\
308 Repository.repo_id))\
309 .join((Permission, RepoToPerm.permission_id ==
309 .join((Permission, RepoToPerm.permission_id ==
310 Permission.permission_id))\
310 Permission.permission_id))\
311 .filter(RepoToPerm.user == default_user).all()
311 .filter(RepoToPerm.user == default_user).all()
312
312
313 if user.is_admin:
313 if user.is_admin:
314 #==================================================================
314 #==================================================================
315 # #admin have all default rights set to admin
315 # #admin have all default rights set to admin
316 #==================================================================
316 #==================================================================
317 user.permissions['global'].add('hg.admin')
317 user.permissions['global'].add('hg.admin')
318
318
319 for perm in default_perms:
319 for perm in default_perms:
320 p = 'repository.admin'
320 p = 'repository.admin'
321 user.permissions['repositories'][perm.RepoToPerm.
321 user.permissions['repositories'][perm.RepoToPerm.
322 repository.repo_name] = p
322 repository.repo_name] = p
323
323
324 else:
324 else:
325 #==================================================================
325 #==================================================================
326 # set default permissions
326 # set default permissions
327 #==================================================================
327 #==================================================================
328 uid = user.user_id
328 uid = user.user_id
329
329
330 #default global
330 #default global
331 default_global_perms = self.sa.query(UserToPerm)\
331 default_global_perms = self.sa.query(UserToPerm)\
332 .filter(UserToPerm.user == default_user)
332 .filter(UserToPerm.user == default_user)
333
333
334 for perm in default_global_perms:
334 for perm in default_global_perms:
335 user.permissions['global'].add(perm.permission.permission_name)
335 user.permissions['global'].add(perm.permission.permission_name)
336
336
337 #default for repositories
337 #default for repositories
338 for perm in default_perms:
338 for perm in default_perms:
339 if perm.Repository.private and not (perm.Repository.user_id ==
339 if perm.Repository.private and not (perm.Repository.user_id ==
340 uid):
340 uid):
341 #diself.sable defaults for private repos,
341 #diself.sable defaults for private repos,
342 p = 'repository.none'
342 p = 'repository.none'
343 elif perm.Repository.user_id == uid:
343 elif perm.Repository.user_id == uid:
344 #set admin if owner
344 #set admin if owner
345 p = 'repository.admin'
345 p = 'repository.admin'
346 else:
346 else:
347 p = perm.Permission.permission_name
347 p = perm.Permission.permission_name
348
348
349 user.permissions['repositories'][perm.RepoToPerm.
349 user.permissions['repositories'][perm.RepoToPerm.
350 repository.repo_name] = p
350 repository.repo_name] = p
351
351
352 #==================================================================
352 #==================================================================
353 # overwrite default with user permissions if any
353 # overwrite default with user permissions if any
354 #==================================================================
354 #==================================================================
355
355
356 #user global
356 #user global
357 user_perms = self.sa.query(UserToPerm)\
357 user_perms = self.sa.query(UserToPerm)\
358 .options(joinedload(UserToPerm.permission))\
358 .options(joinedload(UserToPerm.permission))\
359 .filter(UserToPerm.user_id == uid).all()
359 .filter(UserToPerm.user_id == uid).all()
360
360
361 for perm in user_perms:
361 for perm in user_perms:
362 user.permissions['global'].add(perm.permission.
362 user.permissions['global'].add(perm.permission.
363 permission_name)
363 permission_name)
364
364
365 #user repositories
365 #user repositories
366 user_repo_perms = self.sa.query(RepoToPerm, Permission,
366 user_repo_perms = self.sa.query(RepoToPerm, Permission,
367 Repository)\
367 Repository)\
368 .join((Repository, RepoToPerm.repository_id ==
368 .join((Repository, RepoToPerm.repository_id ==
369 Repository.repo_id))\
369 Repository.repo_id))\
370 .join((Permission, RepoToPerm.permission_id ==
370 .join((Permission, RepoToPerm.permission_id ==
371 Permission.permission_id))\
371 Permission.permission_id))\
372 .filter(RepoToPerm.user_id == uid).all()
372 .filter(RepoToPerm.user_id == uid).all()
373
373
374 for perm in user_repo_perms:
374 for perm in user_repo_perms:
375 # set admin if owner
375 # set admin if owner
376 if perm.Repository.user_id == uid:
376 if perm.Repository.user_id == uid:
377 p = 'repository.admin'
377 p = 'repository.admin'
378 else:
378 else:
379 p = perm.Permission.permission_name
379 p = perm.Permission.permission_name
380 user.permissions['repositories'][perm.RepoToPerm.
380 user.permissions['repositories'][perm.RepoToPerm.
381 repository.repo_name] = p
381 repository.repo_name] = p
382
382
383 #==================================================================
383 #==================================================================
384 # check if user is part of groups for this repository and fill in
384 # check if user is part of groups for this repository and fill in
385 # (or replace with higher) permissions
385 # (or replace with higher) permissions
386 #==================================================================
386 #==================================================================
387
387
388 #users group global
388 #users group global
389 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
389 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
390 .options(joinedload(UsersGroupToPerm.permission))\
390 .options(joinedload(UsersGroupToPerm.permission))\
391 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
391 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
392 UsersGroupMember.users_group_id))\
392 UsersGroupMember.users_group_id))\
393 .filter(UsersGroupMember.user_id == uid).all()
393 .filter(UsersGroupMember.user_id == uid).all()
394
394
395 for perm in user_perms_from_users_groups:
395 for perm in user_perms_from_users_groups:
396 user.permissions['global'].add(perm.permission.permission_name)
396 user.permissions['global'].add(perm.permission.permission_name)
397
397
398 #users group repositories
398 #users group repositories
399 user_repo_perms_from_users_groups = self.sa.query(
399 user_repo_perms_from_users_groups = self.sa.query(
400 UsersGroupRepoToPerm,
400 UsersGroupRepoToPerm,
401 Permission, Repository,)\
401 Permission, Repository,)\
402 .join((Repository, UsersGroupRepoToPerm.repository_id ==
402 .join((Repository, UsersGroupRepoToPerm.repository_id ==
403 Repository.repo_id))\
403 Repository.repo_id))\
404 .join((Permission, UsersGroupRepoToPerm.permission_id ==
404 .join((Permission, UsersGroupRepoToPerm.permission_id ==
405 Permission.permission_id))\
405 Permission.permission_id))\
406 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
406 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
407 UsersGroupMember.users_group_id))\
407 UsersGroupMember.users_group_id))\
408 .filter(UsersGroupMember.user_id == uid).all()
408 .filter(UsersGroupMember.user_id == uid).all()
409
409
410 for perm in user_repo_perms_from_users_groups:
410 for perm in user_repo_perms_from_users_groups:
411 p = perm.Permission.permission_name
411 p = perm.Permission.permission_name
412 cur_perm = user.permissions['repositories'][perm.
412 cur_perm = user.permissions['repositories'][perm.
413 UsersGroupRepoToPerm.
413 UsersGroupRepoToPerm.
414 repository.repo_name]
414 repository.repo_name]
415 #overwrite permission only if it's greater than permission
415 #overwrite permission only if it's greater than permission
416 # given from other sources
416 # given from other sources
417 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
417 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
418 user.permissions['repositories'][perm.UsersGroupRepoToPerm.
418 user.permissions['repositories'][perm.UsersGroupRepoToPerm.
419 repository.repo_name] = p
419 repository.repo_name] = p
420
420
421 return user
421 return user
422
422
@@ -1,83 +1,82 b''
1 """Pylons application test package
1 """Pylons application test package
2
2
3 This package assumes the Pylons environment is already loaded, such as
3 This package assumes the Pylons environment is already loaded, such as
4 when this script is imported from the `nosetests --with-pylons=test.ini`
4 when this script is imported from the `nosetests --with-pylons=test.ini`
5 command.
5 command.
6
6
7 This module initializes the application via ``websetup`` (`paster
7 This module initializes the application via ``websetup`` (`paster
8 setup-app`) and provides the base testing objects.
8 setup-app`) and provides the base testing objects.
9 """
9 """
10 import os
10 import os
11 from os.path import join as jn
11 from os.path import join as jn
12
12
13 from unittest import TestCase
13 from unittest import TestCase
14
14
15 from paste.deploy import loadapp
15 from paste.deploy import loadapp
16 from paste.script.appinstall import SetupCommand
16 from paste.script.appinstall import SetupCommand
17 from pylons import config, url
17 from pylons import config, url
18 from routes.util import URLGenerator
18 from routes.util import URLGenerator
19 from webtest import TestApp
19 from webtest import TestApp
20
20
21 from rhodecode.model import meta
21 from rhodecode.model import meta
22 import logging
22 import logging
23
23
24
25 log = logging.getLogger(__name__)
24 log = logging.getLogger(__name__)
26
25
27 import pylons.test
26 import pylons.test
28
27
29 __all__ = ['environ', 'url', 'TestController', 'TESTS_TMP_PATH', 'HG_REPO',
28 __all__ = ['environ', 'url', 'TestController', 'TESTS_TMP_PATH', 'HG_REPO',
30 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', 'GIT_FORK',
29 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO', 'HG_FORK', 'GIT_FORK',
31 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS' ]
30 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS' ]
32
31
33 # Invoke websetup with the current config file
32 # Invoke websetup with the current config file
34 #SetupCommand('setup-app').run([config_file])
33 # SetupCommand('setup-app').run([config_file])
35
34
36 ##RUNNING DESIRED TESTS
35 ##RUNNING DESIRED TESTS
37 # nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
36 # nosetests -x rhodecode.tests.functional.test_admin_settings:TestSettingsController.test_my_account
38 # nosetests --pdb --pdb-failures
37 # nosetests --pdb --pdb-failures
39 environ = {}
38 environ = {}
40
39
41 #SOME GLOBALS FOR TESTS
40 #SOME GLOBALS FOR TESTS
42 from tempfile import _RandomNameSequence
41 from tempfile import _RandomNameSequence
43 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
42 TESTS_TMP_PATH = jn('/', 'tmp', 'rc_test_%s' % _RandomNameSequence().next())
44 TEST_USER_ADMIN_LOGIN = 'test_admin'
43 TEST_USER_ADMIN_LOGIN = 'test_admin'
45 TEST_USER_ADMIN_PASS = 'test12'
44 TEST_USER_ADMIN_PASS = 'test12'
46 HG_REPO = 'vcs_test_hg'
45 HG_REPO = 'vcs_test_hg'
47 GIT_REPO = 'vcs_test_git'
46 GIT_REPO = 'vcs_test_git'
48
47
49 NEW_HG_REPO = 'vcs_test_hg_new'
48 NEW_HG_REPO = 'vcs_test_hg_new'
50 NEW_GIT_REPO = 'vcs_test_git_new'
49 NEW_GIT_REPO = 'vcs_test_git_new'
51
50
52 HG_FORK = 'vcs_test_hg_fork'
51 HG_FORK = 'vcs_test_hg_fork'
53 GIT_FORK = 'vcs_test_git_fork'
52 GIT_FORK = 'vcs_test_git_fork'
54
53
55 class TestController(TestCase):
54 class TestController(TestCase):
56
55
57 def __init__(self, *args, **kwargs):
56 def __init__(self, *args, **kwargs):
58 wsgiapp = pylons.test.pylonsapp
57 wsgiapp = pylons.test.pylonsapp
59 config = wsgiapp.config
58 config = wsgiapp.config
60
59
61 self.app = TestApp(wsgiapp)
60 self.app = TestApp(wsgiapp)
62 url._push_object(URLGenerator(config['routes.map'], environ))
61 url._push_object(URLGenerator(config['routes.map'], environ))
63 self.sa = meta.Session
62 self.sa = meta.Session
64 self.index_location = config['app_conf']['index_dir']
63 self.index_location = config['app_conf']['index_dir']
65 TestCase.__init__(self, *args, **kwargs)
64 TestCase.__init__(self, *args, **kwargs)
66
65
67 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
66 def log_user(self, username=TEST_USER_ADMIN_LOGIN,
68 password=TEST_USER_ADMIN_PASS):
67 password=TEST_USER_ADMIN_PASS):
69 response = self.app.post(url(controller='login', action='index'),
68 response = self.app.post(url(controller='login', action='index'),
70 {'username':username,
69 {'username':username,
71 'password':password})
70 'password':password})
72
71
73 if 'invalid user name' in response.body:
72 if 'invalid user name' in response.body:
74 self.fail('could not login using %s %s' % (username, password))
73 self.fail('could not login using %s %s' % (username, password))
75
74
76 self.assertEqual(response.status, '302 Found')
75 self.assertEqual(response.status, '302 Found')
77 self.assertEqual(response.session['rhodecode_user'].username, username)
76 self.assertEqual(response.session['rhodecode_user'].username, username)
78 return response.follow()
77 return response.follow()
79
78
80 def checkSessionFlash(self, response, msg):
79 def checkSessionFlash(self, response, msg):
81 self.assertTrue('flash' in response.session)
80 self.assertTrue('flash' in response.session)
82 self.assertTrue(msg in response.session['flash'][0][1])
81 self.assertTrue(msg in response.session['flash'][0][1])
83
82
1 NO CONTENT: file renamed from rhodecode/tests/test_concurency.py to rhodecode/tests/_test_concurency.py
NO CONTENT: file renamed from rhodecode/tests/test_concurency.py to rhodecode/tests/_test_concurency.py
@@ -1,227 +1,229 b''
1 ################################################################################
1 ################################################################################
2 ################################################################################
2 ################################################################################
3 # RhodeCode - Pylons environment configuration #
3 # RhodeCode - Pylons environment configuration #
4 # #
4 # #
5 # The %(here)s variable will be replaced with the parent directory of this file#
5 # The %(here)s variable will be replaced with the parent directory of this file#
6 ################################################################################
6 ################################################################################
7
7
8 [DEFAULT]
8 [DEFAULT]
9 debug = true
9 debug = true
10 pdebug = false
10 pdebug = false
11 ################################################################################
11 ################################################################################
12 ## Uncomment and replace with the address which should receive ##
12 ## Uncomment and replace with the address which should receive ##
13 ## any error reports after application crash ##
13 ## any error reports after application crash ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
14 ## Additionally those settings will be used by RhodeCode mailing system ##
15 ################################################################################
15 ################################################################################
16 #email_to = admin@localhost
16 #email_to = admin@localhost
17 #error_email_from = paste_error@localhost
17 #error_email_from = paste_error@localhost
18 #app_email_from = rhodecode-noreply@localhost
18 #app_email_from = rhodecode-noreply@localhost
19 #error_message =
19 #error_message =
20
20
21 #smtp_server = mail.server.com
21 #smtp_server = mail.server.com
22 #smtp_username =
22 #smtp_username =
23 #smtp_password =
23 #smtp_password =
24 #smtp_port =
24 #smtp_port =
25 #smtp_use_tls = false
25 #smtp_use_tls = false
26 #smtp_use_ssl = true
26 #smtp_use_ssl = true
27
27
28 [server:main]
28 [server:main]
29 ##nr of threads to spawn
29 ##nr of threads to spawn
30 threadpool_workers = 5
30 threadpool_workers = 5
31
31
32 ##max request before thread respawn
32 ##max request before thread respawn
33 threadpool_max_requests = 2
33 threadpool_max_requests = 2
34
34
35 ##option to use threads of process
35 ##option to use threads of process
36 use_threadpool = true
36 use_threadpool = true
37
37
38 use = egg:Paste#http
38 use = egg:Paste#http
39 host = 127.0.0.1
39 host = 127.0.0.1
40 port = 5000
40 port = 5000
41
41
42 [app:main]
42 [app:main]
43 use = egg:rhodecode
43 use = egg:rhodecode
44 full_stack = true
44 full_stack = true
45 static_files = true
45 static_files = true
46 lang=en
46 lang=en
47 cache_dir = /tmp/data
47 cache_dir = /tmp/data
48 index_dir = /tmp/index
48 index_dir = /tmp/index
49 app_instance_uuid = develop-test
49 app_instance_uuid = develop-test
50 cut_off_limit = 256000
50 cut_off_limit = 256000
51 force_https = false
51 force_https = false
52 commit_parse_limit = 25
52 commit_parse_limit = 25
53 use_gravatar = true
53 use_gravatar = true
54 container_auth_enabled = false
55 proxypass_auth_enabled = false
54
56
55 ####################################
57 ####################################
56 ### CELERY CONFIG ####
58 ### CELERY CONFIG ####
57 ####################################
59 ####################################
58 use_celery = false
60 use_celery = false
59 broker.host = localhost
61 broker.host = localhost
60 broker.vhost = rabbitmqhost
62 broker.vhost = rabbitmqhost
61 broker.port = 5672
63 broker.port = 5672
62 broker.user = rabbitmq
64 broker.user = rabbitmq
63 broker.password = qweqwe
65 broker.password = qweqwe
64
66
65 celery.imports = rhodecode.lib.celerylib.tasks
67 celery.imports = rhodecode.lib.celerylib.tasks
66
68
67 celery.result.backend = amqp
69 celery.result.backend = amqp
68 celery.result.dburi = amqp://
70 celery.result.dburi = amqp://
69 celery.result.serialier = json
71 celery.result.serialier = json
70
72
71 #celery.send.task.error.emails = true
73 #celery.send.task.error.emails = true
72 #celery.amqp.task.result.expires = 18000
74 #celery.amqp.task.result.expires = 18000
73
75
74 celeryd.concurrency = 2
76 celeryd.concurrency = 2
75 #celeryd.log.file = celeryd.log
77 #celeryd.log.file = celeryd.log
76 celeryd.log.level = debug
78 celeryd.log.level = debug
77 celeryd.max.tasks.per.child = 1
79 celeryd.max.tasks.per.child = 1
78
80
79 #tasks will never be sent to the queue, but executed locally instead.
81 #tasks will never be sent to the queue, but executed locally instead.
80 celery.always.eager = false
82 celery.always.eager = false
81
83
82 ####################################
84 ####################################
83 ### BEAKER CACHE ####
85 ### BEAKER CACHE ####
84 ####################################
86 ####################################
85 beaker.cache.data_dir=/tmp/data/cache/data
87 beaker.cache.data_dir=/tmp/data/cache/data
86 beaker.cache.lock_dir=/tmp/data/cache/lock
88 beaker.cache.lock_dir=/tmp/data/cache/lock
87 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
89 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
88
90
89 beaker.cache.super_short_term.type=memory
91 beaker.cache.super_short_term.type=memory
90 beaker.cache.super_short_term.expire=10
92 beaker.cache.super_short_term.expire=10
91 beaker.cache.super_short_term.key_length = 256
93 beaker.cache.super_short_term.key_length = 256
92
94
93 beaker.cache.short_term.type=memory
95 beaker.cache.short_term.type=memory
94 beaker.cache.short_term.expire=60
96 beaker.cache.short_term.expire=60
95 beaker.cache.short_term.key_length = 256
97 beaker.cache.short_term.key_length = 256
96
98
97 beaker.cache.long_term.type=memory
99 beaker.cache.long_term.type=memory
98 beaker.cache.long_term.expire=36000
100 beaker.cache.long_term.expire=36000
99 beaker.cache.long_term.key_length = 256
101 beaker.cache.long_term.key_length = 256
100
102
101 beaker.cache.sql_cache_short.type=memory
103 beaker.cache.sql_cache_short.type=memory
102 beaker.cache.sql_cache_short.expire=10
104 beaker.cache.sql_cache_short.expire=10
103 beaker.cache.sql_cache_short.key_length = 256
105 beaker.cache.sql_cache_short.key_length = 256
104
106
105 beaker.cache.sql_cache_med.type=memory
107 beaker.cache.sql_cache_med.type=memory
106 beaker.cache.sql_cache_med.expire=360
108 beaker.cache.sql_cache_med.expire=360
107 beaker.cache.sql_cache_med.key_length = 256
109 beaker.cache.sql_cache_med.key_length = 256
108
110
109 beaker.cache.sql_cache_long.type=file
111 beaker.cache.sql_cache_long.type=file
110 beaker.cache.sql_cache_long.expire=3600
112 beaker.cache.sql_cache_long.expire=3600
111 beaker.cache.sql_cache_long.key_length = 256
113 beaker.cache.sql_cache_long.key_length = 256
112
114
113 ####################################
115 ####################################
114 ### BEAKER SESSION ####
116 ### BEAKER SESSION ####
115 ####################################
117 ####################################
116 ## Type of storage used for the session, current types are
118 ## Type of storage used for the session, current types are
117 ## dbm, file, memcached, database, and memory.
119 ## dbm, file, memcached, database, and memory.
118 ## The storage uses the Container API
120 ## The storage uses the Container API
119 ##that is also used by the cache system.
121 ##that is also used by the cache system.
120 beaker.session.type = file
122 beaker.session.type = file
121
123
122 beaker.session.key = rhodecode
124 beaker.session.key = rhodecode
123 beaker.session.secret = g654dcno0-9873jhgfreyu
125 beaker.session.secret = g654dcno0-9873jhgfreyu
124 beaker.session.timeout = 36000
126 beaker.session.timeout = 36000
125
127
126 ##auto save the session to not to use .save()
128 ##auto save the session to not to use .save()
127 beaker.session.auto = False
129 beaker.session.auto = False
128
130
129 ##true exire at browser close
131 ##true exire at browser close
130 #beaker.session.cookie_expires = 3600
132 #beaker.session.cookie_expires = 3600
131
133
132
134
133 ################################################################################
135 ################################################################################
134 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
136 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
135 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
137 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
136 ## execute malicious code after an exception is raised. ##
138 ## execute malicious code after an exception is raised. ##
137 ################################################################################
139 ################################################################################
138 #set debug = false
140 #set debug = false
139
141
140 ##################################
142 ##################################
141 ### LOGVIEW CONFIG ###
143 ### LOGVIEW CONFIG ###
142 ##################################
144 ##################################
143 logview.sqlalchemy = #faa
145 logview.sqlalchemy = #faa
144 logview.pylons.templating = #bfb
146 logview.pylons.templating = #bfb
145 logview.pylons.util = #eee
147 logview.pylons.util = #eee
146
148
147 #########################################################
149 #########################################################
148 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
150 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
149 #########################################################
151 #########################################################
150 sqlalchemy.db1.url = sqlite:///%(here)s/test.db
152 sqlalchemy.db1.url = sqlite:///%(here)s/test.db
151 #sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode_tests
153 #sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode_tests
152 #sqlalchemy.db1.echo = false
154 #sqlalchemy.db1.echo = false
153 #sqlalchemy.db1.pool_recycle = 3600
155 #sqlalchemy.db1.pool_recycle = 3600
154 sqlalchemy.convert_unicode = true
156 sqlalchemy.convert_unicode = true
155
157
156 ################################
158 ################################
157 ### LOGGING CONFIGURATION ####
159 ### LOGGING CONFIGURATION ####
158 ################################
160 ################################
159 [loggers]
161 [loggers]
160 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
162 keys = root, routes, rhodecode, sqlalchemy, beaker, templates
161
163
162 [handlers]
164 [handlers]
163 keys = console
165 keys = console
164
166
165 [formatters]
167 [formatters]
166 keys = generic, color_formatter
168 keys = generic, color_formatter
167
169
168 #############
170 #############
169 ## LOGGERS ##
171 ## LOGGERS ##
170 #############
172 #############
171 [logger_root]
173 [logger_root]
172 level = ERROR
174 level = ERROR
173 handlers = console
175 handlers = console
174
176
175 [logger_routes]
177 [logger_routes]
176 level = ERROR
178 level = ERROR
177 handlers =
179 handlers =
178 qualname = routes.middleware
180 qualname = routes.middleware
179 # "level = DEBUG" logs the route matched and routing variables.
181 # "level = DEBUG" logs the route matched and routing variables.
180 propagate = 1
182 propagate = 1
181
183
182 [logger_beaker]
184 [logger_beaker]
183 level = DEBUG
185 level = DEBUG
184 handlers =
186 handlers =
185 qualname = beaker.container
187 qualname = beaker.container
186 propagate = 1
188 propagate = 1
187
189
188 [logger_templates]
190 [logger_templates]
189 level = INFO
191 level = INFO
190 handlers =
192 handlers =
191 qualname = pylons.templating
193 qualname = pylons.templating
192 propagate = 1
194 propagate = 1
193
195
194 [logger_rhodecode]
196 [logger_rhodecode]
195 level = ERROR
197 level = ERROR
196 handlers =
198 handlers =
197 qualname = rhodecode
199 qualname = rhodecode
198 propagate = 1
200 propagate = 1
199
201
200 [logger_sqlalchemy]
202 [logger_sqlalchemy]
201 level = ERROR
203 level = ERROR
202 handlers = console
204 handlers = console
203 qualname = sqlalchemy.engine
205 qualname = sqlalchemy.engine
204 propagate = 0
206 propagate = 0
205
207
206 ##############
208 ##############
207 ## HANDLERS ##
209 ## HANDLERS ##
208 ##############
210 ##############
209
211
210 [handler_console]
212 [handler_console]
211 class = StreamHandler
213 class = StreamHandler
212 args = (sys.stderr,)
214 args = (sys.stderr,)
213 level = NOTSET
215 level = NOTSET
214 formatter = generic
216 formatter = generic
215
217
216 ################
218 ################
217 ## FORMATTERS ##
219 ## FORMATTERS ##
218 ################
220 ################
219
221
220 [formatter_generic]
222 [formatter_generic]
221 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
223 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
222 datefmt = %Y-%m-%d %H:%M:%S
224 datefmt = %Y-%m-%d %H:%M:%S
223
225
224 [formatter_color_formatter]
226 [formatter_color_formatter]
225 class=rhodecode.lib.colored_formatter.ColorFormatter
227 class=rhodecode.lib.colored_formatter.ColorFormatter
226 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
228 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
227 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
229 datefmt = %Y-%m-%d %H:%M:%S
General Comments 0
You need to be logged in to leave comments. Login now