##// END OF EJS Templates
moved out sqlalchemy cache from meta to the config files....
marcink -
r609:c1c1cf77 default
parent child Browse files
Show More
@@ -1,160 +1,171 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 ################################################################################
10 ################################################################################
11 ## Uncomment and replace with the address which should receive ##
11 ## Uncomment and replace with the address which should receive ##
12 ## any error reports after application crash ##
12 ## any error reports after application crash ##
13 ## Additionally those settings will be used by rhodecode mailing system ##
13 ## Additionally those settings will be used by rhodecode mailing system ##
14 ################################################################################
14 ################################################################################
15 #email_to = admin@localhost
15 #email_to = admin@localhost
16 #error_email_from = paste_error@localhost
16 #error_email_from = paste_error@localhost
17 #app_email_from = rhodecode-noreply@localhost
17 #app_email_from = rhodecode-noreply@localhost
18 #error_message =
18 #error_message =
19
19
20 #smtp_server = mail.server.com
20 #smtp_server = mail.server.com
21 #smtp_username =
21 #smtp_username =
22 #smtp_password =
22 #smtp_password =
23 #smtp_port =
23 #smtp_port =
24 #smtp_use_tls =
24 #smtp_use_tls =
25
25
26 [server:main]
26 [server:main]
27 ##nr of threads to spawn
27 ##nr of threads to spawn
28 threadpool_workers = 5
28 threadpool_workers = 5
29
29
30 ##max request before
30 ##max request before
31 threadpool_max_requests = 6
31 threadpool_max_requests = 6
32
32
33 ##option to use threads of process
33 ##option to use threads of process
34 use_threadpool = false
34 use_threadpool = false
35
35
36 use = egg:Paste#http
36 use = egg:Paste#http
37 host = 127.0.0.1
37 host = 127.0.0.1
38 port = 5000
38 port = 5000
39
39
40 [app:main]
40 [app:main]
41 use = egg:rhodecode
41 use = egg:rhodecode
42 full_stack = true
42 full_stack = true
43 static_files = true
43 static_files = true
44 lang=en
44 lang=en
45 cache_dir = %(here)s/data
45 cache_dir = %(here)s/data
46
46
47 ####################################
47 ####################################
48 ### BEAKER CACHE ####
48 ### BEAKER CACHE ####
49 ####################################
49 ####################################
50 beaker.cache.data_dir=/%(here)s/data/cache/data
50 beaker.cache.data_dir=/%(here)s/data/cache/data
51 beaker.cache.lock_dir=/%(here)s/data/cache/lock
51 beaker.cache.lock_dir=/%(here)s/data/cache/lock
52 beaker.cache.regions=super_short_term,short_term,long_term
52 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
53 beaker.cache.long_term.type=memory
53 beaker.cache.long_term.type=memory
54 beaker.cache.long_term.expire=36000
54 beaker.cache.long_term.expire=36000
55
55 beaker.cache.short_term.type=memory
56 beaker.cache.short_term.type=memory
56 beaker.cache.short_term.expire=60
57 beaker.cache.short_term.expire=60
58
57 beaker.cache.super_short_term.type=memory
59 beaker.cache.super_short_term.type=memory
58 beaker.cache.super_short_term.expire=10
60 beaker.cache.super_short_term.expire=10
59
61
62 beaker.cache.sql_cache_short.type=memory
63 beaker.cache.sql_cache_short.expire=5
64
65 beaker.cache.sql_cache_med.type=memory
66 beaker.cache.sql_cache_med.expire=360
67
68 beaker.cache.sql_cache_long.type=file
69 beaker.cache.sql_cache_long.expire=3600
70
60 ####################################
71 ####################################
61 ### BEAKER SESSION ####
72 ### BEAKER SESSION ####
62 ####################################
73 ####################################
63 ## Type of storage used for the session, current types are
74 ## Type of storage used for the session, current types are
64 ## "dbm", "file", "memcached", "database", and "memory".
75 ## "dbm", "file", "memcached", "database", and "memory".
65 ## The storage uses the Container API
76 ## The storage uses the Container API
66 ##that is also used by the cache system.
77 ##that is also used by the cache system.
67 beaker.session.type = file
78 beaker.session.type = file
68
79
69 beaker.session.key = rhodecode
80 beaker.session.key = rhodecode
70 beaker.session.secret = g654dcno0-9873jhgfreyu
81 beaker.session.secret = g654dcno0-9873jhgfreyu
71 beaker.session.timeout = 36000
82 beaker.session.timeout = 36000
72
83
73 ##auto save the session to not to use .save()
84 ##auto save the session to not to use .save()
74 beaker.session.auto = False
85 beaker.session.auto = False
75
86
76 ##true exire at browser close
87 ##true exire at browser close
77 #beaker.session.cookie_expires = 3600
88 #beaker.session.cookie_expires = 3600
78
89
79
90
80 ################################################################################
91 ################################################################################
81 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
92 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
82 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
93 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
83 ## execute malicious code after an exception is raised. ##
94 ## execute malicious code after an exception is raised. ##
84 ################################################################################
95 ################################################################################
85 #set debug = false
96 #set debug = false
86
97
87 ##################################
98 ##################################
88 ### LOGVIEW CONFIG ###
99 ### LOGVIEW CONFIG ###
89 ##################################
100 ##################################
90 logview.sqlalchemy = #faa
101 logview.sqlalchemy = #faa
91 logview.pylons.templating = #bfb
102 logview.pylons.templating = #bfb
92 logview.pylons.util = #eee
103 logview.pylons.util = #eee
93
104
94 #########################################################
105 #########################################################
95 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
106 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
96 #########################################################
107 #########################################################
97 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
108 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
98 #sqlalchemy.db1.echo = False
109 #sqlalchemy.db1.echo = False
99 #sqlalchemy.db1.pool_recycle = 3600
110 #sqlalchemy.db1.pool_recycle = 3600
100 sqlalchemy.convert_unicode = true
111 sqlalchemy.convert_unicode = true
101
112
102 ################################
113 ################################
103 ### LOGGING CONFIGURATION ####
114 ### LOGGING CONFIGURATION ####
104 ################################
115 ################################
105 [loggers]
116 [loggers]
106 keys = root, routes, rhodecode, sqlalchemy
117 keys = root, routes, rhodecode, sqlalchemy
107
118
108 [handlers]
119 [handlers]
109 keys = console
120 keys = console
110
121
111 [formatters]
122 [formatters]
112 keys = generic,color_formatter
123 keys = generic,color_formatter
113
124
114 #############
125 #############
115 ## LOGGERS ##
126 ## LOGGERS ##
116 #############
127 #############
117 [logger_root]
128 [logger_root]
118 level = NOTSET
129 level = NOTSET
119 handlers = console
130 handlers = console
120
131
121 [logger_routes]
132 [logger_routes]
122 level = DEBUG
133 level = DEBUG
123 handlers = console
134 handlers = console
124 qualname = routes.middleware
135 qualname = routes.middleware
125 # "level = DEBUG" logs the route matched and routing variables.
136 # "level = DEBUG" logs the route matched and routing variables.
126
137
127 [logger_rhodecode]
138 [logger_rhodecode]
128 level = DEBUG
139 level = DEBUG
129 handlers = console
140 handlers = console
130 qualname = rhodecode
141 qualname = rhodecode
131 propagate = 0
142 propagate = 0
132
143
133 [logger_sqlalchemy]
144 [logger_sqlalchemy]
134 level = ERROR
145 level = ERROR
135 handlers = console
146 handlers = console
136 qualname = sqlalchemy.engine
147 qualname = sqlalchemy.engine
137 propagate = 0
148 propagate = 0
138
149
139 ##############
150 ##############
140 ## HANDLERS ##
151 ## HANDLERS ##
141 ##############
152 ##############
142
153
143 [handler_console]
154 [handler_console]
144 class = StreamHandler
155 class = StreamHandler
145 args = (sys.stderr,)
156 args = (sys.stderr,)
146 level = NOTSET
157 level = NOTSET
147 formatter = color_formatter
158 formatter = color_formatter
148
159
149 ################
160 ################
150 ## FORMATTERS ##
161 ## FORMATTERS ##
151 ################
162 ################
152
163
153 [formatter_generic]
164 [formatter_generic]
154 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
165 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
155 datefmt = %Y-%m-%d %H:%M:%S
166 datefmt = %Y-%m-%d %H:%M:%S
156
167
157 [formatter_color_formatter]
168 [formatter_color_formatter]
158 class=rhodecode.lib.colored_formatter.ColorFormatter
169 class=rhodecode.lib.colored_formatter.ColorFormatter
159 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
170 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
160 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
171 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,160 +1,171 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 ################################################################################
10 ################################################################################
11 ## Uncomment and replace with the address which should receive ##
11 ## Uncomment and replace with the address which should receive ##
12 ## any error reports after application crash ##
12 ## any error reports after application crash ##
13 ## Additionally those settings will be used by rhodecode mailing system ##
13 ## Additionally those settings will be used by rhodecode mailing system ##
14 ################################################################################
14 ################################################################################
15 #email_to = admin@localhost
15 #email_to = admin@localhost
16 #error_email_from = paste_error@localhost
16 #error_email_from = paste_error@localhost
17 #app_email_from = rhodecode-noreply@localhost
17 #app_email_from = rhodecode-noreply@localhost
18 #error_message =
18 #error_message =
19
19
20 #smtp_server = mail.server.com
20 #smtp_server = mail.server.com
21 #smtp_username =
21 #smtp_username =
22 #smtp_password =
22 #smtp_password =
23 #smtp_port =
23 #smtp_port =
24 #smtp_use_tls = false
24 #smtp_use_tls = false
25
25
26 [server:main]
26 [server:main]
27 ##nr of threads to spawn
27 ##nr of threads to spawn
28 threadpool_workers = 5
28 threadpool_workers = 5
29
29
30 ##max request before thread respawn
30 ##max request before thread respawn
31 threadpool_max_requests = 2
31 threadpool_max_requests = 2
32
32
33 ##option to use threads of process
33 ##option to use threads of process
34 use_threadpool = true
34 use_threadpool = true
35
35
36 use = egg:Paste#http
36 use = egg:Paste#http
37 host = 127.0.0.1
37 host = 127.0.0.1
38 port = 8001
38 port = 8001
39
39
40 [app:main]
40 [app:main]
41 use = egg:rhodecode
41 use = egg:rhodecode
42 full_stack = true
42 full_stack = true
43 static_files = false
43 static_files = false
44 lang=en
44 lang=en
45 cache_dir = %(here)s/data
45 cache_dir = %(here)s/data
46
46
47 ####################################
47 ####################################
48 ### BEAKER CACHE ####
48 ### BEAKER CACHE ####
49 ####################################
49 ####################################
50 beaker.cache.data_dir=/%(here)s/data/cache/data
50 beaker.cache.data_dir=/%(here)s/data/cache/data
51 beaker.cache.lock_dir=/%(here)s/data/cache/lock
51 beaker.cache.lock_dir=/%(here)s/data/cache/lock
52 beaker.cache.regions=super_short_term,short_term,long_term
52 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
53 beaker.cache.long_term.type=memory
53 beaker.cache.long_term.type=memory
54 beaker.cache.long_term.expire=36000
54 beaker.cache.long_term.expire=36000
55
55 beaker.cache.short_term.type=memory
56 beaker.cache.short_term.type=memory
56 beaker.cache.short_term.expire=60
57 beaker.cache.short_term.expire=60
58
57 beaker.cache.super_short_term.type=memory
59 beaker.cache.super_short_term.type=memory
58 beaker.cache.super_short_term.expire=10
60 beaker.cache.super_short_term.expire=10
59
61
62 beaker.cache.sql_cache_short.type=memory
63 beaker.cache.sql_cache_short.expire=5
64
65 beaker.cache.sql_cache_med.type=memory
66 beaker.cache.sql_cache_med.expire=360
67
68 beaker.cache.sql_cache_long.type=file
69 beaker.cache.sql_cache_long.expire=3600
70
60 ####################################
71 ####################################
61 ### BEAKER SESSION ####
72 ### BEAKER SESSION ####
62 ####################################
73 ####################################
63 ## Type of storage used for the session, current types are
74 ## Type of storage used for the session, current types are
64 ## dbm, file, memcached, database, and memory.
75 ## dbm, file, memcached, database, and memory.
65 ## The storage uses the Container API
76 ## The storage uses the Container API
66 ##that is also used by the cache system.
77 ##that is also used by the cache system.
67 beaker.session.type = file
78 beaker.session.type = file
68
79
69 beaker.session.key = rhodecode
80 beaker.session.key = rhodecode
70 beaker.session.secret = g654dcno0-9873jhgfreyu
81 beaker.session.secret = g654dcno0-9873jhgfreyu
71 beaker.session.timeout = 36000
82 beaker.session.timeout = 36000
72
83
73 ##auto save the session to not to use .save()
84 ##auto save the session to not to use .save()
74 beaker.session.auto = False
85 beaker.session.auto = False
75
86
76 ##true exire at browser close
87 ##true exire at browser close
77 #beaker.session.cookie_expires = 3600
88 #beaker.session.cookie_expires = 3600
78
89
79
90
80 ################################################################################
91 ################################################################################
81 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
92 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
82 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
93 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
83 ## execute malicious code after an exception is raised. ##
94 ## execute malicious code after an exception is raised. ##
84 ################################################################################
95 ################################################################################
85 set debug = false
96 set debug = false
86
97
87 ##################################
98 ##################################
88 ### LOGVIEW CONFIG ###
99 ### LOGVIEW CONFIG ###
89 ##################################
100 ##################################
90 logview.sqlalchemy = #faa
101 logview.sqlalchemy = #faa
91 logview.pylons.templating = #bfb
102 logview.pylons.templating = #bfb
92 logview.pylons.util = #eee
103 logview.pylons.util = #eee
93
104
94 #########################################################
105 #########################################################
95 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
106 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
96 #########################################################
107 #########################################################
97 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
108 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
98 #sqlalchemy.db1.echo = False
109 #sqlalchemy.db1.echo = False
99 #sqlalchemy.db1.pool_recycle = 3600
110 #sqlalchemy.db1.pool_recycle = 3600
100 sqlalchemy.convert_unicode = true
111 sqlalchemy.convert_unicode = true
101
112
102 ################################
113 ################################
103 ### LOGGING CONFIGURATION ####
114 ### LOGGING CONFIGURATION ####
104 ################################
115 ################################
105 [loggers]
116 [loggers]
106 keys = root, routes, rhodecode, sqlalchemy
117 keys = root, routes, rhodecode, sqlalchemy
107
118
108 [handlers]
119 [handlers]
109 keys = console
120 keys = console
110
121
111 [formatters]
122 [formatters]
112 keys = generic,color_formatter
123 keys = generic,color_formatter
113
124
114 #############
125 #############
115 ## LOGGERS ##
126 ## LOGGERS ##
116 #############
127 #############
117 [logger_root]
128 [logger_root]
118 level = INFO
129 level = INFO
119 handlers = console
130 handlers = console
120
131
121 [logger_routes]
132 [logger_routes]
122 level = INFO
133 level = INFO
123 handlers = console
134 handlers = console
124 qualname = routes.middleware
135 qualname = routes.middleware
125 # "level = DEBUG" logs the route matched and routing variables.
136 # "level = DEBUG" logs the route matched and routing variables.
126
137
127 [logger_rhodecode]
138 [logger_rhodecode]
128 level = DEBUG
139 level = DEBUG
129 handlers = console
140 handlers = console
130 qualname = rhodecode
141 qualname = rhodecode
131 propagate = 0
142 propagate = 0
132
143
133 [logger_sqlalchemy]
144 [logger_sqlalchemy]
134 level = ERROR
145 level = ERROR
135 handlers = console
146 handlers = console
136 qualname = sqlalchemy.engine
147 qualname = sqlalchemy.engine
137 propagate = 0
148 propagate = 0
138
149
139 ##############
150 ##############
140 ## HANDLERS ##
151 ## HANDLERS ##
141 ##############
152 ##############
142
153
143 [handler_console]
154 [handler_console]
144 class = StreamHandler
155 class = StreamHandler
145 args = (sys.stderr,)
156 args = (sys.stderr,)
146 level = NOTSET
157 level = NOTSET
147 formatter = color_formatter
158 formatter = color_formatter
148
159
149 ################
160 ################
150 ## FORMATTERS ##
161 ## FORMATTERS ##
151 ################
162 ################
152
163
153 [formatter_generic]
164 [formatter_generic]
154 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
165 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
155 datefmt = %Y-%m-%d %H:%M:%S
166 datefmt = %Y-%m-%d %H:%M:%S
156
167
157 [formatter_color_formatter]
168 [formatter_color_formatter]
158 class=rhodecode.lib.colored_formatter.ColorFormatter
169 class=rhodecode.lib.colored_formatter.ColorFormatter
159 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
170 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
160 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
171 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,161 +1,172 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 ################################################################################
10 ################################################################################
11 ## Uncomment and replace with the address which should receive ##
11 ## Uncomment and replace with the address which should receive ##
12 ## any error reports after application crash ##
12 ## any error reports after application crash ##
13 ## Additionally those settings will be used by rhodecode mailing system ##
13 ## Additionally those settings will be used by rhodecode mailing system ##
14 ################################################################################
14 ################################################################################
15 #email_to = admin@localhost
15 #email_to = admin@localhost
16 #error_email_from = paste_error@localhost
16 #error_email_from = paste_error@localhost
17 #app_email_from = rhodecode-noreply@localhost
17 #app_email_from = rhodecode-noreply@localhost
18 #error_message =
18 #error_message =
19
19
20 #smtp_server = mail.server.com
20 #smtp_server = mail.server.com
21 #smtp_username =
21 #smtp_username =
22 #smtp_password =
22 #smtp_password =
23 #smtp_port =
23 #smtp_port =
24 #smtp_use_tls = false
24 #smtp_use_tls = false
25
25
26 [server:main]
26 [server:main]
27 ##nr of threads to spawn
27 ##nr of threads to spawn
28 threadpool_workers = 5
28 threadpool_workers = 5
29
29
30 ##max request before thread respawn
30 ##max request before thread respawn
31 threadpool_max_requests = 2
31 threadpool_max_requests = 2
32
32
33 ##option to use threads of process
33 ##option to use threads of process
34 use_threadpool = true
34 use_threadpool = true
35
35
36 use = egg:Paste#http
36 use = egg:Paste#http
37 host = 127.0.0.1
37 host = 127.0.0.1
38 port = 5000
38 port = 5000
39
39
40 [app:main]
40 [app:main]
41 use = egg:rhodecode
41 use = egg:rhodecode
42 full_stack = true
42 full_stack = true
43 static_files = true
43 static_files = true
44 lang=en
44 lang=en
45 cache_dir = %(here)s/data
45 cache_dir = %(here)s/data
46 app_instance_uuid = ${app_instance_uuid}
46 app_instance_uuid = ${app_instance_uuid}
47
47
48 ####################################
48 ####################################
49 ### BEAKER CACHE ####
49 ### BEAKER CACHE ####
50 ####################################
50 ####################################
51 beaker.cache.data_dir=/%(here)s/data/cache/data
51 beaker.cache.data_dir=/%(here)s/data/cache/data
52 beaker.cache.lock_dir=/%(here)s/data/cache/lock
52 beaker.cache.lock_dir=/%(here)s/data/cache/lock
53 beaker.cache.regions=super_short_term,short_term,long_term
53 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
54 beaker.cache.long_term.type=memory
54 beaker.cache.long_term.type=memory
55 beaker.cache.long_term.expire=36000
55 beaker.cache.long_term.expire=36000
56
56 beaker.cache.short_term.type=memory
57 beaker.cache.short_term.type=memory
57 beaker.cache.short_term.expire=60
58 beaker.cache.short_term.expire=60
59
58 beaker.cache.super_short_term.type=memory
60 beaker.cache.super_short_term.type=memory
59 beaker.cache.super_short_term.expire=10
61 beaker.cache.super_short_term.expire=10
60
62
63 beaker.cache.sql_cache_short.type=memory
64 beaker.cache.sql_cache_short.expire=5
65
66 beaker.cache.sql_cache_med.type=memory
67 beaker.cache.sql_cache_med.expire=360
68
69 beaker.cache.sql_cache_long.type=file
70 beaker.cache.sql_cache_long.expire=3600
71
61 ####################################
72 ####################################
62 ### BEAKER SESSION ####
73 ### BEAKER SESSION ####
63 ####################################
74 ####################################
64 ## Type of storage used for the session, current types are
75 ## Type of storage used for the session, current types are
65 ## dbm, file, memcached, database, and memory.
76 ## dbm, file, memcached, database, and memory.
66 ## The storage uses the Container API
77 ## The storage uses the Container API
67 ##that is also used by the cache system.
78 ##that is also used by the cache system.
68 beaker.session.type = file
79 beaker.session.type = file
69
80
70 beaker.session.key = rhodecode
81 beaker.session.key = rhodecode
71 beaker.session.secret = ${app_instance_secret}
82 beaker.session.secret = ${app_instance_secret}
72 beaker.session.timeout = 36000
83 beaker.session.timeout = 36000
73
84
74 ##auto save the session to not to use .save()
85 ##auto save the session to not to use .save()
75 beaker.session.auto = False
86 beaker.session.auto = False
76
87
77 ##true exire at browser close
88 ##true exire at browser close
78 #beaker.session.cookie_expires = 3600
89 #beaker.session.cookie_expires = 3600
79
90
80
91
81 ################################################################################
92 ################################################################################
82 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
93 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
83 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
94 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
84 ## execute malicious code after an exception is raised. ##
95 ## execute malicious code after an exception is raised. ##
85 ################################################################################
96 ################################################################################
86 set debug = false
97 set debug = false
87
98
88 ##################################
99 ##################################
89 ### LOGVIEW CONFIG ###
100 ### LOGVIEW CONFIG ###
90 ##################################
101 ##################################
91 logview.sqlalchemy = #faa
102 logview.sqlalchemy = #faa
92 logview.pylons.templating = #bfb
103 logview.pylons.templating = #bfb
93 logview.pylons.util = #eee
104 logview.pylons.util = #eee
94
105
95 #########################################################
106 #########################################################
96 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
107 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
97 #########################################################
108 #########################################################
98 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
109 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
99 #sqlalchemy.db1.echo = False
110 #sqlalchemy.db1.echo = False
100 #sqlalchemy.db1.pool_recycle = 3600
111 #sqlalchemy.db1.pool_recycle = 3600
101 sqlalchemy.convert_unicode = true
112 sqlalchemy.convert_unicode = true
102
113
103 ################################
114 ################################
104 ### LOGGING CONFIGURATION ####
115 ### LOGGING CONFIGURATION ####
105 ################################
116 ################################
106 [loggers]
117 [loggers]
107 keys = root, routes, rhodecode, sqlalchemy
118 keys = root, routes, rhodecode, sqlalchemy
108
119
109 [handlers]
120 [handlers]
110 keys = console
121 keys = console
111
122
112 [formatters]
123 [formatters]
113 keys = generic,color_formatter
124 keys = generic,color_formatter
114
125
115 #############
126 #############
116 ## LOGGERS ##
127 ## LOGGERS ##
117 #############
128 #############
118 [logger_root]
129 [logger_root]
119 level = INFO
130 level = INFO
120 handlers = console
131 handlers = console
121
132
122 [logger_routes]
133 [logger_routes]
123 level = INFO
134 level = INFO
124 handlers = console
135 handlers = console
125 qualname = routes.middleware
136 qualname = routes.middleware
126 # "level = DEBUG" logs the route matched and routing variables.
137 # "level = DEBUG" logs the route matched and routing variables.
127
138
128 [logger_rhodecode]
139 [logger_rhodecode]
129 level = DEBUG
140 level = DEBUG
130 handlers = console
141 handlers = console
131 qualname = rhodecode
142 qualname = rhodecode
132 propagate = 0
143 propagate = 0
133
144
134 [logger_sqlalchemy]
145 [logger_sqlalchemy]
135 level = ERROR
146 level = ERROR
136 handlers = console
147 handlers = console
137 qualname = sqlalchemy.engine
148 qualname = sqlalchemy.engine
138 propagate = 0
149 propagate = 0
139
150
140 ##############
151 ##############
141 ## HANDLERS ##
152 ## HANDLERS ##
142 ##############
153 ##############
143
154
144 [handler_console]
155 [handler_console]
145 class = StreamHandler
156 class = StreamHandler
146 args = (sys.stderr,)
157 args = (sys.stderr,)
147 level = NOTSET
158 level = NOTSET
148 formatter = color_formatter
159 formatter = color_formatter
149
160
150 ################
161 ################
151 ## FORMATTERS ##
162 ## FORMATTERS ##
152 ################
163 ################
153
164
154 [formatter_generic]
165 [formatter_generic]
155 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
166 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
156 datefmt = %Y-%m-%d %H:%M:%S
167 datefmt = %Y-%m-%d %H:%M:%S
157
168
158 [formatter_color_formatter]
169 [formatter_color_formatter]
159 class=rhodecode.lib.colored_formatter.ColorFormatter
170 class=rhodecode.lib.colored_formatter.ColorFormatter
160 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
171 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
161 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
172 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,486 +1,492 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # authentication and permission libraries
3 # authentication and permission libraries
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 4, 2010
21 Created on April 4, 2010
22
22
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from beaker.cache import cache_region
25 from beaker.cache import cache_region
26 from pylons import config, session, url, request
26 from pylons import config, session, url, request
27 from pylons.controllers.util import abort, redirect
27 from pylons.controllers.util import abort, redirect
28 from rhodecode.lib.utils import get_repo_slug
28 from rhodecode.lib.utils import get_repo_slug
29 from rhodecode.model import meta
29 from rhodecode.model import meta
30 from rhodecode.model.caching_query import FromCache
30 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
31 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
31 UserToPerm
32 UserToPerm
32 from sqlalchemy.exc import OperationalError
33 from sqlalchemy.exc import OperationalError
33 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
34 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
34 import bcrypt
35 import bcrypt
35 from decorator import decorator
36 from decorator import decorator
36 import logging
37 import logging
37 import random
38 import random
38
39
39 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
40
41
41 class PasswordGenerator(object):
42 class PasswordGenerator(object):
42 """This is a simple class for generating password from
43 """This is a simple class for generating password from
43 different sets of characters
44 different sets of characters
44 usage:
45 usage:
45 passwd_gen = PasswordGenerator()
46 passwd_gen = PasswordGenerator()
46 #print 8-letter password containing only big and small letters of alphabet
47 #print 8-letter password containing only big and small letters of alphabet
47 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
48 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
48 """
49 """
49 ALPHABETS_NUM = r'''1234567890'''#[0]
50 ALPHABETS_NUM = r'''1234567890'''#[0]
50 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
51 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
51 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
52 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
52 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
53 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
53 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
54 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
54 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
55 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
55 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
56 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
56 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
57 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
57 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
58 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
58
59
59 def __init__(self, passwd=''):
60 def __init__(self, passwd=''):
60 self.passwd = passwd
61 self.passwd = passwd
61
62
62 def gen_password(self, len, type):
63 def gen_password(self, len, type):
63 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
64 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
64 return self.passwd
65 return self.passwd
65
66
66
67
67 def get_crypt_password(password):
68 def get_crypt_password(password):
68 """Cryptographic function used for password hashing based on sha1
69 """Cryptographic function used for password hashing based on sha1
69 @param password: password to hash
70 @param password: password to hash
70 """
71 """
71 return bcrypt.hashpw(password, bcrypt.gensalt(10))
72 return bcrypt.hashpw(password, bcrypt.gensalt(10))
72
73
73 def check_password(password, hashed):
74 def check_password(password, hashed):
74 return bcrypt.hashpw(password, hashed) == hashed
75 return bcrypt.hashpw(password, hashed) == hashed
75
76
76 @cache_region('super_short_term', 'cached_user')
77 @cache_region('super_short_term', 'cached_user')
77 def get_user_cached(username):
78 def get_user_cached(username):
78 sa = meta.Session
79 sa = meta.Session
79 try:
80 try:
80 user = sa.query(User).filter(User.username == username).one()
81 user = sa.query(User).filter(User.username == username).one()
81 finally:
82 finally:
82 meta.Session.remove()
83 meta.Session.remove()
83 return user
84 return user
84
85
85 def authfunc(environ, username, password):
86 def authfunc(environ, username, password):
86 try:
87 try:
87 user = get_user_cached(username)
88 user = get_user_cached(username)
88 except (NoResultFound, MultipleResultsFound, OperationalError), e:
89 except (NoResultFound, MultipleResultsFound, OperationalError), e:
89 log.error(e)
90 log.error(e)
90 user = None
91 user = None
91
92
92 if user:
93 if user:
93 if user.active:
94 if user.active:
94 if user.username == username and check_password(password, user.password):
95 if user.username == username and check_password(password, user.password):
95 log.info('user %s authenticated correctly', username)
96 log.info('user %s authenticated correctly', username)
96 return True
97 return True
97 else:
98 else:
98 log.error('user %s is disabled', username)
99 log.error('user %s is disabled', username)
99
100
100 return False
101 return False
101
102
102 class AuthUser(object):
103 class AuthUser(object):
103 """
104 """
104 A simple object that handles a mercurial username for authentication
105 A simple object that handles a mercurial username for authentication
105 """
106 """
106 def __init__(self):
107 def __init__(self):
107 self.username = 'None'
108 self.username = 'None'
108 self.name = ''
109 self.name = ''
109 self.lastname = ''
110 self.lastname = ''
110 self.email = ''
111 self.email = ''
111 self.user_id = None
112 self.user_id = None
112 self.is_authenticated = False
113 self.is_authenticated = False
113 self.is_admin = False
114 self.is_admin = False
114 self.permissions = {}
115 self.permissions = {}
115
116
116
117
117 def set_available_permissions(config):
118 def set_available_permissions(config):
118 """
119 """
119 This function will propagate pylons globals with all available defined
120 This function will propagate pylons globals with all available defined
120 permission given in db. We don't wannt to check each time from db for new
121 permission given in db. We don't wannt to check each time from db for new
121 permissions since adding a new permission also requires application restart
122 permissions since adding a new permission also requires application restart
122 ie. to decorate new views with the newly created permission
123 ie. to decorate new views with the newly created permission
123 @param config:
124 @param config:
124 """
125 """
125 log.info('getting information about all available permissions')
126 log.info('getting information about all available permissions')
126 try:
127 try:
127 sa = meta.Session
128 sa = meta.Session
128 all_perms = sa.query(Permission).all()
129 all_perms = sa.query(Permission).all()
129 finally:
130 finally:
130 meta.Session.remove()
131 meta.Session.remove()
131
132
132 config['available_permissions'] = [x.permission_name for x in all_perms]
133 config['available_permissions'] = [x.permission_name for x in all_perms]
133
134
134 def set_base_path(config):
135 def set_base_path(config):
135 config['base_path'] = config['pylons.app_globals'].base_path
136 config['base_path'] = config['pylons.app_globals'].base_path
136
137
137 def fill_data(user):
138 def fill_data(user):
138 """
139 """
139 Fills user data with those from database and log out user if not present
140 Fills user data with those from database and log out user if not present
140 in database
141 in database
141 @param user:
142 @param user:
142 """
143 """
143 sa = meta.Session
144 sa = meta.Session
144 dbuser = sa.query(User).get(user.user_id)
145 dbuser = sa.query(User).options(FromCache('sql_cache_short',
146 'getuser_%s' % user.user_id))\
147 .get(user.user_id)
145 if dbuser:
148 if dbuser:
146 user.username = dbuser.username
149 user.username = dbuser.username
147 user.is_admin = dbuser.admin
150 user.is_admin = dbuser.admin
148 user.name = dbuser.name
151 user.name = dbuser.name
149 user.lastname = dbuser.lastname
152 user.lastname = dbuser.lastname
150 user.email = dbuser.email
153 user.email = dbuser.email
151 else:
154 else:
152 user.is_authenticated = False
155 user.is_authenticated = False
153 meta.Session.remove()
156 meta.Session.remove()
154 return user
157 return user
155
158
156 def fill_perms(user):
159 def fill_perms(user):
157 """
160 """
158 Fills user permission attribute with permissions taken from database
161 Fills user permission attribute with permissions taken from database
159 @param user:
162 @param user:
160 """
163 """
161
164
162 sa = meta.Session
165 sa = meta.Session
163 user.permissions['repositories'] = {}
166 user.permissions['repositories'] = {}
164 user.permissions['global'] = set()
167 user.permissions['global'] = set()
165
168
166 #===========================================================================
169 #===========================================================================
167 # fetch default permissions
170 # fetch default permissions
168 #===========================================================================
171 #===========================================================================
172 default_user = sa.query(User)\
173 .options(FromCache('sql_cache_short','getuser_%s' % 'default'))\
174 .filter(User.username == 'default').scalar()
175
169 default_perms = sa.query(RepoToPerm, Repository, Permission)\
176 default_perms = sa.query(RepoToPerm, Repository, Permission)\
170 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
177 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
171 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
178 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
172 .filter(RepoToPerm.user == sa.query(User).filter(User.username ==
179 .filter(RepoToPerm.user == default_user).all()
173 'default').scalar()).all()
174
180
175 if user.is_admin:
181 if user.is_admin:
176 #=======================================================================
182 #=======================================================================
177 # #admin have all default rights set to admin
183 # #admin have all default rights set to admin
178 #=======================================================================
184 #=======================================================================
179 user.permissions['global'].add('hg.admin')
185 user.permissions['global'].add('hg.admin')
180
186
181 for perm in default_perms:
187 for perm in default_perms:
182 p = 'repository.admin'
188 p = 'repository.admin'
183 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
189 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
184
190
185 else:
191 else:
186 #=======================================================================
192 #=======================================================================
187 # set default permissions
193 # set default permissions
188 #=======================================================================
194 #=======================================================================
189
195
190 #default global
196 #default global
191 default_global_perms = sa.query(UserToPerm)\
197 default_global_perms = sa.query(UserToPerm)\
192 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
198 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
193 'default').one())
199 'default').one())
194
200
195 for perm in default_global_perms:
201 for perm in default_global_perms:
196 user.permissions['global'].add(perm.permission.permission_name)
202 user.permissions['global'].add(perm.permission.permission_name)
197
203
198 #default repositories
204 #default repositories
199 for perm in default_perms:
205 for perm in default_perms:
200 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
206 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
201 #disable defaults for private repos,
207 #disable defaults for private repos,
202 p = 'repository.none'
208 p = 'repository.none'
203 elif perm.Repository.user_id == user.user_id:
209 elif perm.Repository.user_id == user.user_id:
204 #set admin if owner
210 #set admin if owner
205 p = 'repository.admin'
211 p = 'repository.admin'
206 else:
212 else:
207 p = perm.Permission.permission_name
213 p = perm.Permission.permission_name
208
214
209 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
215 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
210
216
211 #=======================================================================
217 #=======================================================================
212 # #overwrite default with user permissions if any
218 # #overwrite default with user permissions if any
213 #=======================================================================
219 #=======================================================================
214 user_perms = sa.query(RepoToPerm, Permission, Repository)\
220 user_perms = sa.query(RepoToPerm, Permission, Repository)\
215 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
221 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
216 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
222 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
217 .filter(RepoToPerm.user_id == user.user_id).all()
223 .filter(RepoToPerm.user_id == user.user_id).all()
218
224
219 for perm in user_perms:
225 for perm in user_perms:
220 if perm.Repository.user_id == user.user_id:#set admin if owner
226 if perm.Repository.user_id == user.user_id:#set admin if owner
221 p = 'repository.admin'
227 p = 'repository.admin'
222 else:
228 else:
223 p = perm.Permission.permission_name
229 p = perm.Permission.permission_name
224 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
230 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
225 meta.Session.remove()
231 meta.Session.remove()
226 return user
232 return user
227
233
228 def get_user(session):
234 def get_user(session):
229 """
235 """
230 Gets user from session, and wraps permissions into user
236 Gets user from session, and wraps permissions into user
231 @param session:
237 @param session:
232 """
238 """
233 user = session.get('rhodecode_user', AuthUser())
239 user = session.get('rhodecode_user', AuthUser())
234 if user.is_authenticated:
240 if user.is_authenticated:
235 user = fill_data(user)
241 user = fill_data(user)
236 user = fill_perms(user)
242 user = fill_perms(user)
237 session['rhodecode_user'] = user
243 session['rhodecode_user'] = user
238 session.save()
244 session.save()
239 return user
245 return user
240
246
241 #===============================================================================
247 #===============================================================================
242 # CHECK DECORATORS
248 # CHECK DECORATORS
243 #===============================================================================
249 #===============================================================================
244 class LoginRequired(object):
250 class LoginRequired(object):
245 """Must be logged in to execute this function else redirect to login page"""
251 """Must be logged in to execute this function else redirect to login page"""
246
252
247 def __call__(self, func):
253 def __call__(self, func):
248 return decorator(self.__wrapper, func)
254 return decorator(self.__wrapper, func)
249
255
250 def __wrapper(self, func, *fargs, **fkwargs):
256 def __wrapper(self, func, *fargs, **fkwargs):
251 user = session.get('rhodecode_user', AuthUser())
257 user = session.get('rhodecode_user', AuthUser())
252 log.debug('Checking login required for user:%s', user.username)
258 log.debug('Checking login required for user:%s', user.username)
253 if user.is_authenticated:
259 if user.is_authenticated:
254 log.debug('user %s is authenticated', user.username)
260 log.debug('user %s is authenticated', user.username)
255 return func(*fargs, **fkwargs)
261 return func(*fargs, **fkwargs)
256 else:
262 else:
257 log.warn('user %s not authenticated', user.username)
263 log.warn('user %s not authenticated', user.username)
258
264
259 p = ''
265 p = ''
260 if request.environ.get('SCRIPT_NAME') != '/':
266 if request.environ.get('SCRIPT_NAME') != '/':
261 p += request.environ.get('SCRIPT_NAME')
267 p += request.environ.get('SCRIPT_NAME')
262
268
263 p += request.environ.get('PATH_INFO')
269 p += request.environ.get('PATH_INFO')
264 if request.environ.get('QUERY_STRING'):
270 if request.environ.get('QUERY_STRING'):
265 p += '?' + request.environ.get('QUERY_STRING')
271 p += '?' + request.environ.get('QUERY_STRING')
266
272
267 log.debug('redirecting to login page with %s', p)
273 log.debug('redirecting to login page with %s', p)
268 return redirect(url('login_home', came_from=p))
274 return redirect(url('login_home', came_from=p))
269
275
270 class PermsDecorator(object):
276 class PermsDecorator(object):
271 """Base class for decorators"""
277 """Base class for decorators"""
272
278
273 def __init__(self, *required_perms):
279 def __init__(self, *required_perms):
274 available_perms = config['available_permissions']
280 available_perms = config['available_permissions']
275 for perm in required_perms:
281 for perm in required_perms:
276 if perm not in available_perms:
282 if perm not in available_perms:
277 raise Exception("'%s' permission is not defined" % perm)
283 raise Exception("'%s' permission is not defined" % perm)
278 self.required_perms = set(required_perms)
284 self.required_perms = set(required_perms)
279 self.user_perms = None
285 self.user_perms = None
280
286
281 def __call__(self, func):
287 def __call__(self, func):
282 return decorator(self.__wrapper, func)
288 return decorator(self.__wrapper, func)
283
289
284
290
285 def __wrapper(self, func, *fargs, **fkwargs):
291 def __wrapper(self, func, *fargs, **fkwargs):
286 # _wrapper.__name__ = func.__name__
292 # _wrapper.__name__ = func.__name__
287 # _wrapper.__dict__.update(func.__dict__)
293 # _wrapper.__dict__.update(func.__dict__)
288 # _wrapper.__doc__ = func.__doc__
294 # _wrapper.__doc__ = func.__doc__
289
295
290 self.user_perms = session.get('rhodecode_user', AuthUser()).permissions
296 self.user_perms = session.get('rhodecode_user', AuthUser()).permissions
291 log.debug('checking %s permissions %s for %s',
297 log.debug('checking %s permissions %s for %s',
292 self.__class__.__name__, self.required_perms, func.__name__)
298 self.__class__.__name__, self.required_perms, func.__name__)
293
299
294 if self.check_permissions():
300 if self.check_permissions():
295 log.debug('Permission granted for %s', func.__name__)
301 log.debug('Permission granted for %s', func.__name__)
296
302
297 return func(*fargs, **fkwargs)
303 return func(*fargs, **fkwargs)
298
304
299 else:
305 else:
300 log.warning('Permission denied for %s', func.__name__)
306 log.warning('Permission denied for %s', func.__name__)
301 #redirect with forbidden ret code
307 #redirect with forbidden ret code
302 return abort(403)
308 return abort(403)
303
309
304
310
305
311
306 def check_permissions(self):
312 def check_permissions(self):
307 """Dummy function for overriding"""
313 """Dummy function for overriding"""
308 raise Exception('You have to write this function in child class')
314 raise Exception('You have to write this function in child class')
309
315
310 class HasPermissionAllDecorator(PermsDecorator):
316 class HasPermissionAllDecorator(PermsDecorator):
311 """Checks for access permission for all given predicates. All of them
317 """Checks for access permission for all given predicates. All of them
312 have to be meet in order to fulfill the request
318 have to be meet in order to fulfill the request
313 """
319 """
314
320
315 def check_permissions(self):
321 def check_permissions(self):
316 if self.required_perms.issubset(self.user_perms.get('global')):
322 if self.required_perms.issubset(self.user_perms.get('global')):
317 return True
323 return True
318 return False
324 return False
319
325
320
326
321 class HasPermissionAnyDecorator(PermsDecorator):
327 class HasPermissionAnyDecorator(PermsDecorator):
322 """Checks for access permission for any of given predicates. In order to
328 """Checks for access permission for any of given predicates. In order to
323 fulfill the request any of predicates must be meet
329 fulfill the request any of predicates must be meet
324 """
330 """
325
331
326 def check_permissions(self):
332 def check_permissions(self):
327 if self.required_perms.intersection(self.user_perms.get('global')):
333 if self.required_perms.intersection(self.user_perms.get('global')):
328 return True
334 return True
329 return False
335 return False
330
336
331 class HasRepoPermissionAllDecorator(PermsDecorator):
337 class HasRepoPermissionAllDecorator(PermsDecorator):
332 """Checks for access permission for all given predicates for specific
338 """Checks for access permission for all given predicates for specific
333 repository. All of them have to be meet in order to fulfill the request
339 repository. All of them have to be meet in order to fulfill the request
334 """
340 """
335
341
336 def check_permissions(self):
342 def check_permissions(self):
337 repo_name = get_repo_slug(request)
343 repo_name = get_repo_slug(request)
338 try:
344 try:
339 user_perms = set([self.user_perms['repositories'][repo_name]])
345 user_perms = set([self.user_perms['repositories'][repo_name]])
340 except KeyError:
346 except KeyError:
341 return False
347 return False
342 if self.required_perms.issubset(user_perms):
348 if self.required_perms.issubset(user_perms):
343 return True
349 return True
344 return False
350 return False
345
351
346
352
347 class HasRepoPermissionAnyDecorator(PermsDecorator):
353 class HasRepoPermissionAnyDecorator(PermsDecorator):
348 """Checks for access permission for any of given predicates for specific
354 """Checks for access permission for any of given predicates for specific
349 repository. In order to fulfill the request any of predicates must be meet
355 repository. In order to fulfill the request any of predicates must be meet
350 """
356 """
351
357
352 def check_permissions(self):
358 def check_permissions(self):
353 repo_name = get_repo_slug(request)
359 repo_name = get_repo_slug(request)
354
360
355 try:
361 try:
356 user_perms = set([self.user_perms['repositories'][repo_name]])
362 user_perms = set([self.user_perms['repositories'][repo_name]])
357 except KeyError:
363 except KeyError:
358 return False
364 return False
359 if self.required_perms.intersection(user_perms):
365 if self.required_perms.intersection(user_perms):
360 return True
366 return True
361 return False
367 return False
362 #===============================================================================
368 #===============================================================================
363 # CHECK FUNCTIONS
369 # CHECK FUNCTIONS
364 #===============================================================================
370 #===============================================================================
365
371
366 class PermsFunction(object):
372 class PermsFunction(object):
367 """Base function for other check functions"""
373 """Base function for other check functions"""
368
374
369 def __init__(self, *perms):
375 def __init__(self, *perms):
370 available_perms = config['available_permissions']
376 available_perms = config['available_permissions']
371
377
372 for perm in perms:
378 for perm in perms:
373 if perm not in available_perms:
379 if perm not in available_perms:
374 raise Exception("'%s' permission in not defined" % perm)
380 raise Exception("'%s' permission in not defined" % perm)
375 self.required_perms = set(perms)
381 self.required_perms = set(perms)
376 self.user_perms = None
382 self.user_perms = None
377 self.granted_for = ''
383 self.granted_for = ''
378 self.repo_name = None
384 self.repo_name = None
379
385
380 def __call__(self, check_Location=''):
386 def __call__(self, check_Location=''):
381 user = session.get('rhodecode_user', False)
387 user = session.get('rhodecode_user', False)
382 if not user:
388 if not user:
383 return False
389 return False
384 self.user_perms = user.permissions
390 self.user_perms = user.permissions
385 self.granted_for = user.username
391 self.granted_for = user.username
386 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
392 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
387
393
388 if self.check_permissions():
394 if self.check_permissions():
389 log.debug('Permission granted for %s @%s', self.granted_for,
395 log.debug('Permission granted for %s @%s', self.granted_for,
390 check_Location)
396 check_Location)
391 return True
397 return True
392
398
393 else:
399 else:
394 log.warning('Permission denied for %s @%s', self.granted_for,
400 log.warning('Permission denied for %s @%s', self.granted_for,
395 check_Location)
401 check_Location)
396 return False
402 return False
397
403
398 def check_permissions(self):
404 def check_permissions(self):
399 """Dummy function for overriding"""
405 """Dummy function for overriding"""
400 raise Exception('You have to write this function in child class')
406 raise Exception('You have to write this function in child class')
401
407
402 class HasPermissionAll(PermsFunction):
408 class HasPermissionAll(PermsFunction):
403 def check_permissions(self):
409 def check_permissions(self):
404 if self.required_perms.issubset(self.user_perms.get('global')):
410 if self.required_perms.issubset(self.user_perms.get('global')):
405 return True
411 return True
406 return False
412 return False
407
413
408 class HasPermissionAny(PermsFunction):
414 class HasPermissionAny(PermsFunction):
409 def check_permissions(self):
415 def check_permissions(self):
410 if self.required_perms.intersection(self.user_perms.get('global')):
416 if self.required_perms.intersection(self.user_perms.get('global')):
411 return True
417 return True
412 return False
418 return False
413
419
414 class HasRepoPermissionAll(PermsFunction):
420 class HasRepoPermissionAll(PermsFunction):
415
421
416 def __call__(self, repo_name=None, check_Location=''):
422 def __call__(self, repo_name=None, check_Location=''):
417 self.repo_name = repo_name
423 self.repo_name = repo_name
418 return super(HasRepoPermissionAll, self).__call__(check_Location)
424 return super(HasRepoPermissionAll, self).__call__(check_Location)
419
425
420 def check_permissions(self):
426 def check_permissions(self):
421 if not self.repo_name:
427 if not self.repo_name:
422 self.repo_name = get_repo_slug(request)
428 self.repo_name = get_repo_slug(request)
423
429
424 try:
430 try:
425 self.user_perms = set([self.user_perms['repositories']\
431 self.user_perms = set([self.user_perms['repositories']\
426 [self.repo_name]])
432 [self.repo_name]])
427 except KeyError:
433 except KeyError:
428 return False
434 return False
429 self.granted_for = self.repo_name
435 self.granted_for = self.repo_name
430 if self.required_perms.issubset(self.user_perms):
436 if self.required_perms.issubset(self.user_perms):
431 return True
437 return True
432 return False
438 return False
433
439
434 class HasRepoPermissionAny(PermsFunction):
440 class HasRepoPermissionAny(PermsFunction):
435
441
436 def __call__(self, repo_name=None, check_Location=''):
442 def __call__(self, repo_name=None, check_Location=''):
437 self.repo_name = repo_name
443 self.repo_name = repo_name
438 return super(HasRepoPermissionAny, self).__call__(check_Location)
444 return super(HasRepoPermissionAny, self).__call__(check_Location)
439
445
440 def check_permissions(self):
446 def check_permissions(self):
441 if not self.repo_name:
447 if not self.repo_name:
442 self.repo_name = get_repo_slug(request)
448 self.repo_name = get_repo_slug(request)
443
449
444 try:
450 try:
445 self.user_perms = set([self.user_perms['repositories']\
451 self.user_perms = set([self.user_perms['repositories']\
446 [self.repo_name]])
452 [self.repo_name]])
447 except KeyError:
453 except KeyError:
448 return False
454 return False
449 self.granted_for = self.repo_name
455 self.granted_for = self.repo_name
450 if self.required_perms.intersection(self.user_perms):
456 if self.required_perms.intersection(self.user_perms):
451 return True
457 return True
452 return False
458 return False
453
459
454 #===============================================================================
460 #===============================================================================
455 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
461 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
456 #===============================================================================
462 #===============================================================================
457
463
458 class HasPermissionAnyMiddleware(object):
464 class HasPermissionAnyMiddleware(object):
459 def __init__(self, *perms):
465 def __init__(self, *perms):
460 self.required_perms = set(perms)
466 self.required_perms = set(perms)
461
467
462 def __call__(self, user, repo_name):
468 def __call__(self, user, repo_name):
463 usr = AuthUser()
469 usr = AuthUser()
464 usr.user_id = user.user_id
470 usr.user_id = user.user_id
465 usr.username = user.username
471 usr.username = user.username
466 usr.is_admin = user.admin
472 usr.is_admin = user.admin
467
473
468 try:
474 try:
469 self.user_perms = set([fill_perms(usr)\
475 self.user_perms = set([fill_perms(usr)\
470 .permissions['repositories'][repo_name]])
476 .permissions['repositories'][repo_name]])
471 except:
477 except:
472 self.user_perms = set()
478 self.user_perms = set()
473 self.granted_for = ''
479 self.granted_for = ''
474 self.username = user.username
480 self.username = user.username
475 self.repo_name = repo_name
481 self.repo_name = repo_name
476 return self.check_permissions()
482 return self.check_permissions()
477
483
478 def check_permissions(self):
484 def check_permissions(self):
479 log.debug('checking mercurial protocol '
485 log.debug('checking mercurial protocol '
480 'permissions for user:%s repository:%s',
486 'permissions for user:%s repository:%s',
481 self.username, self.repo_name)
487 self.username, self.repo_name)
482 if self.required_perms.intersection(self.user_perms):
488 if self.required_perms.intersection(self.user_perms):
483 log.debug('permission granted')
489 log.debug('permission granted')
484 return True
490 return True
485 log.debug('permission denied')
491 log.debug('permission denied')
486 return False
492 return False
@@ -1,267 +1,275 b''
1 """caching_query.py
1 """caching_query.py
2
2
3 Represent persistence structures which allow the usage of
3 Represent persistence structures which allow the usage of
4 Beaker caching with SQLAlchemy.
4 Beaker caching with SQLAlchemy.
5
5
6 The three new concepts introduced here are:
6 The three new concepts introduced here are:
7
7
8 * CachingQuery - a Query subclass that caches and
8 * CachingQuery - a Query subclass that caches and
9 retrieves results in/from Beaker.
9 retrieves results in/from Beaker.
10 * FromCache - a query option that establishes caching
10 * FromCache - a query option that establishes caching
11 parameters on a Query
11 parameters on a Query
12 * RelationshipCache - a variant of FromCache which is specific
12 * RelationshipCache - a variant of FromCache which is specific
13 to a query invoked during a lazy load.
13 to a query invoked during a lazy load.
14 * _params_from_query - extracts value parameters from
14 * _params_from_query - extracts value parameters from
15 a Query.
15 a Query.
16
16
17 The rest of what's here are standard SQLAlchemy and
17 The rest of what's here are standard SQLAlchemy and
18 Beaker constructs.
18 Beaker constructs.
19
19
20 """
20 """
21 from beaker.exceptions import BeakerException
21 from sqlalchemy.orm.interfaces import MapperOption
22 from sqlalchemy.orm.interfaces import MapperOption
22 from sqlalchemy.orm.query import Query
23 from sqlalchemy.orm.query import Query
23 from sqlalchemy.sql import visitors
24 from sqlalchemy.sql import visitors
25 import beaker
24
26
25 class CachingQuery(Query):
27 class CachingQuery(Query):
26 """A Query subclass which optionally loads full results from a Beaker
28 """A Query subclass which optionally loads full results from a Beaker
27 cache region.
29 cache region.
28
30
29 The CachingQuery stores additional state that allows it to consult
31 The CachingQuery stores additional state that allows it to consult
30 a Beaker cache before accessing the database:
32 a Beaker cache before accessing the database:
31
33
32 * A "region", which is a cache region argument passed to a
34 * A "region", which is a cache region argument passed to a
33 Beaker CacheManager, specifies a particular cache configuration
35 Beaker CacheManager, specifies a particular cache configuration
34 (including backend implementation, expiration times, etc.)
36 (including backend implementation, expiration times, etc.)
35 * A "namespace", which is a qualifying name that identifies a
37 * A "namespace", which is a qualifying name that identifies a
36 group of keys within the cache. A query that filters on a name
38 group of keys within the cache. A query that filters on a name
37 might use the name "by_name", a query that filters on a date range
39 might use the name "by_name", a query that filters on a date range
38 to a joined table might use the name "related_date_range".
40 to a joined table might use the name "related_date_range".
39
41
40 When the above state is present, a Beaker cache is retrieved.
42 When the above state is present, a Beaker cache is retrieved.
41
43
42 The "namespace" name is first concatenated with
44 The "namespace" name is first concatenated with
43 a string composed of the individual entities and columns the Query
45 a string composed of the individual entities and columns the Query
44 requests, i.e. such as ``Query(User.id, User.name)``.
46 requests, i.e. such as ``Query(User.id, User.name)``.
45
47
46 The Beaker cache is then loaded from the cache manager based
48 The Beaker cache is then loaded from the cache manager based
47 on the region and composed namespace. The key within the cache
49 on the region and composed namespace. The key within the cache
48 itself is then constructed against the bind parameters specified
50 itself is then constructed against the bind parameters specified
49 by this query, which are usually literals defined in the
51 by this query, which are usually literals defined in the
50 WHERE clause.
52 WHERE clause.
51
53
52 The FromCache and RelationshipCache mapper options below represent
54 The FromCache and RelationshipCache mapper options below represent
53 the "public" method of configuring this state upon the CachingQuery.
55 the "public" method of configuring this state upon the CachingQuery.
54
56
55 """
57 """
56
58
57 def __init__(self, manager, *args, **kw):
59 def __init__(self, manager, *args, **kw):
58 self.cache_manager = manager
60 self.cache_manager = manager
59 Query.__init__(self, *args, **kw)
61 Query.__init__(self, *args, **kw)
60
62
61 def __iter__(self):
63 def __iter__(self):
62 """override __iter__ to pull results from Beaker
64 """override __iter__ to pull results from Beaker
63 if particular attributes have been configured.
65 if particular attributes have been configured.
64
66
65 Note that this approach does *not* detach the loaded objects from
67 Note that this approach does *not* detach the loaded objects from
66 the current session. If the cache backend is an in-process cache
68 the current session. If the cache backend is an in-process cache
67 (like "memory") and lives beyond the scope of the current session's
69 (like "memory") and lives beyond the scope of the current session's
68 transaction, those objects may be expired. The method here can be
70 transaction, those objects may be expired. The method here can be
69 modified to first expunge() each loaded item from the current
71 modified to first expunge() each loaded item from the current
70 session before returning the list of items, so that the items
72 session before returning the list of items, so that the items
71 in the cache are not the same ones in the current Session.
73 in the cache are not the same ones in the current Session.
72
74
73 """
75 """
74 if hasattr(self, '_cache_parameters'):
76 if hasattr(self, '_cache_parameters'):
75 return self.get_value(createfunc=lambda: list(Query.__iter__(self)))
77 return self.get_value(createfunc=lambda: list(Query.__iter__(self)))
76 else:
78 else:
77 return Query.__iter__(self)
79 return Query.__iter__(self)
78
80
79 def invalidate(self):
81 def invalidate(self):
80 """Invalidate the value represented by this Query."""
82 """Invalidate the value represented by this Query."""
81
83
82 cache, cache_key = _get_cache_parameters(self)
84 cache, cache_key = _get_cache_parameters(self)
83 cache.remove(cache_key)
85 cache.remove(cache_key)
84
86
85 def get_value(self, merge=True, createfunc=None):
87 def get_value(self, merge=True, createfunc=None):
86 """Return the value from the cache for this query.
88 """Return the value from the cache for this query.
87
89
88 Raise KeyError if no value present and no
90 Raise KeyError if no value present and no
89 createfunc specified.
91 createfunc specified.
90
92
91 """
93 """
92 cache, cache_key = _get_cache_parameters(self)
94 cache, cache_key = _get_cache_parameters(self)
93 ret = cache.get_value(cache_key, createfunc=createfunc)
95 ret = cache.get_value(cache_key, createfunc=createfunc)
94 if merge:
96 if merge:
95 ret = self.merge_result(ret, load=False)
97 ret = self.merge_result(ret, load=False)
96 return ret
98 return ret
97
99
98 def set_value(self, value):
100 def set_value(self, value):
99 """Set the value in the cache for this query."""
101 """Set the value in the cache for this query."""
100
102
101 cache, cache_key = _get_cache_parameters(self)
103 cache, cache_key = _get_cache_parameters(self)
102 cache.put(cache_key, value)
104 cache.put(cache_key, value)
103
105
104 def query_callable(manager):
106 def query_callable(manager):
105 def query(*arg, **kw):
107 def query(*arg, **kw):
106 return CachingQuery(manager, *arg, **kw)
108 return CachingQuery(manager, *arg, **kw)
107 return query
109 return query
108
110
111 def get_cache_region(name, region):
112 if region not in beaker.cache.cache_regions:
113 raise BeakerException('Cache region not configured: %s' % region)
114 kw = beaker.cache.cache_regions[region]
115 return beaker.cache.Cache._get_cache(name, kw)
116
109 def _get_cache_parameters(query):
117 def _get_cache_parameters(query):
110 """For a query with cache_region and cache_namespace configured,
118 """For a query with cache_region and cache_namespace configured,
111 return the correspoinding Cache instance and cache key, based
119 return the correspoinding Cache instance and cache key, based
112 on this query's current criterion and parameter values.
120 on this query's current criterion and parameter values.
113
121
114 """
122 """
115 if not hasattr(query, '_cache_parameters'):
123 if not hasattr(query, '_cache_parameters'):
116 raise ValueError("This Query does not have caching parameters configured.")
124 raise ValueError("This Query does not have caching parameters configured.")
117
125
118 region, namespace, cache_key = query._cache_parameters
126 region, namespace, cache_key = query._cache_parameters
119
127
120 namespace = _namespace_from_query(namespace, query)
128 namespace = _namespace_from_query(namespace, query)
121
129
122 if cache_key is None:
130 if cache_key is None:
123 # cache key - the value arguments from this query's parameters.
131 # cache key - the value arguments from this query's parameters.
124 args = _params_from_query(query)
132 args = _params_from_query(query)
125 cache_key = " ".join([str(x) for x in args])
133 cache_key = " ".join([str(x) for x in args])
126
134
127 # get cache
135 # get cache
128 cache = query.cache_manager.get_cache_region(namespace, region)
136 #cache = query.cache_manager.get_cache_region(namespace, region)
129
137 cache = get_cache_region(namespace, region)
130 # optional - hash the cache_key too for consistent length
138 # optional - hash the cache_key too for consistent length
131 # import uuid
139 # import uuid
132 # cache_key= str(uuid.uuid5(uuid.NAMESPACE_DNS, cache_key))
140 # cache_key= str(uuid.uuid5(uuid.NAMESPACE_DNS, cache_key))
133
141
134 return cache, cache_key
142 return cache, cache_key
135
143
136 def _namespace_from_query(namespace, query):
144 def _namespace_from_query(namespace, query):
137 # cache namespace - the token handed in by the
145 # cache namespace - the token handed in by the
138 # option + class we're querying against
146 # option + class we're querying against
139 namespace = " ".join([namespace] + [str(x) for x in query._entities])
147 namespace = " ".join([namespace] + [str(x) for x in query._entities])
140
148
141 # memcached wants this
149 # memcached wants this
142 namespace = namespace.replace(' ', '_')
150 namespace = namespace.replace(' ', '_')
143
151
144 return namespace
152 return namespace
145
153
146 def _set_cache_parameters(query, region, namespace, cache_key):
154 def _set_cache_parameters(query, region, namespace, cache_key):
147
155
148 if hasattr(query, '_cache_parameters'):
156 if hasattr(query, '_cache_parameters'):
149 region, namespace, cache_key = query._cache_parameters
157 region, namespace, cache_key = query._cache_parameters
150 raise ValueError("This query is already configured "
158 raise ValueError("This query is already configured "
151 "for region %r namespace %r" %
159 "for region %r namespace %r" %
152 (region, namespace)
160 (region, namespace)
153 )
161 )
154 query._cache_parameters = region, namespace, cache_key
162 query._cache_parameters = region, namespace, cache_key
155
163
156 class FromCache(MapperOption):
164 class FromCache(MapperOption):
157 """Specifies that a Query should load results from a cache."""
165 """Specifies that a Query should load results from a cache."""
158
166
159 propagate_to_loaders = False
167 propagate_to_loaders = False
160
168
161 def __init__(self, region, namespace, cache_key=None):
169 def __init__(self, region, namespace, cache_key=None):
162 """Construct a new FromCache.
170 """Construct a new FromCache.
163
171
164 :param region: the cache region. Should be a
172 :param region: the cache region. Should be a
165 region configured in the Beaker CacheManager.
173 region configured in the Beaker CacheManager.
166
174
167 :param namespace: the cache namespace. Should
175 :param namespace: the cache namespace. Should
168 be a name uniquely describing the target Query's
176 be a name uniquely describing the target Query's
169 lexical structure.
177 lexical structure.
170
178
171 :param cache_key: optional. A string cache key
179 :param cache_key: optional. A string cache key
172 that will serve as the key to the query. Use this
180 that will serve as the key to the query. Use this
173 if your query has a huge amount of parameters (such
181 if your query has a huge amount of parameters (such
174 as when using in_()) which correspond more simply to
182 as when using in_()) which correspond more simply to
175 some other identifier.
183 some other identifier.
176
184
177 """
185 """
178 self.region = region
186 self.region = region
179 self.namespace = namespace
187 self.namespace = namespace
180 self.cache_key = cache_key
188 self.cache_key = cache_key
181
189
182 def process_query(self, query):
190 def process_query(self, query):
183 """Process a Query during normal loading operation."""
191 """Process a Query during normal loading operation."""
184
192
185 _set_cache_parameters(query, self.region, self.namespace, self.cache_key)
193 _set_cache_parameters(query, self.region, self.namespace, self.cache_key)
186
194
187 class RelationshipCache(MapperOption):
195 class RelationshipCache(MapperOption):
188 """Specifies that a Query as called within a "lazy load"
196 """Specifies that a Query as called within a "lazy load"
189 should load results from a cache."""
197 should load results from a cache."""
190
198
191 propagate_to_loaders = True
199 propagate_to_loaders = True
192
200
193 def __init__(self, region, namespace, attribute):
201 def __init__(self, region, namespace, attribute):
194 """Construct a new RelationshipCache.
202 """Construct a new RelationshipCache.
195
203
196 :param region: the cache region. Should be a
204 :param region: the cache region. Should be a
197 region configured in the Beaker CacheManager.
205 region configured in the Beaker CacheManager.
198
206
199 :param namespace: the cache namespace. Should
207 :param namespace: the cache namespace. Should
200 be a name uniquely describing the target Query's
208 be a name uniquely describing the target Query's
201 lexical structure.
209 lexical structure.
202
210
203 :param attribute: A Class.attribute which
211 :param attribute: A Class.attribute which
204 indicates a particular class relationship() whose
212 indicates a particular class relationship() whose
205 lazy loader should be pulled from the cache.
213 lazy loader should be pulled from the cache.
206
214
207 """
215 """
208 self.region = region
216 self.region = region
209 self.namespace = namespace
217 self.namespace = namespace
210 self._relationship_options = {
218 self._relationship_options = {
211 (attribute.property.parent.class_, attribute.property.key) : self
219 (attribute.property.parent.class_, attribute.property.key) : self
212 }
220 }
213
221
214 def process_query_conditionally(self, query):
222 def process_query_conditionally(self, query):
215 """Process a Query that is used within a lazy loader.
223 """Process a Query that is used within a lazy loader.
216
224
217 (the process_query_conditionally() method is a SQLAlchemy
225 (the process_query_conditionally() method is a SQLAlchemy
218 hook invoked only within lazyload.)
226 hook invoked only within lazyload.)
219
227
220 """
228 """
221 if query._current_path:
229 if query._current_path:
222 mapper, key = query._current_path[-2:]
230 mapper, key = query._current_path[-2:]
223
231
224 for cls in mapper.class_.__mro__:
232 for cls in mapper.class_.__mro__:
225 if (cls, key) in self._relationship_options:
233 if (cls, key) in self._relationship_options:
226 relationship_option = self._relationship_options[(cls, key)]
234 relationship_option = self._relationship_options[(cls, key)]
227 _set_cache_parameters(
235 _set_cache_parameters(
228 query,
236 query,
229 relationship_option.region,
237 relationship_option.region,
230 relationship_option.namespace,
238 relationship_option.namespace,
231 None)
239 None)
232
240
233 def and_(self, option):
241 def and_(self, option):
234 """Chain another RelationshipCache option to this one.
242 """Chain another RelationshipCache option to this one.
235
243
236 While many RelationshipCache objects can be specified on a single
244 While many RelationshipCache objects can be specified on a single
237 Query separately, chaining them together allows for a more efficient
245 Query separately, chaining them together allows for a more efficient
238 lookup during load.
246 lookup during load.
239
247
240 """
248 """
241 self._relationship_options.update(option._relationship_options)
249 self._relationship_options.update(option._relationship_options)
242 return self
250 return self
243
251
244
252
245 def _params_from_query(query):
253 def _params_from_query(query):
246 """Pull the bind parameter values from a query.
254 """Pull the bind parameter values from a query.
247
255
248 This takes into account any scalar attribute bindparam set up.
256 This takes into account any scalar attribute bindparam set up.
249
257
250 E.g. params_from_query(query.filter(Cls.foo==5).filter(Cls.bar==7)))
258 E.g. params_from_query(query.filter(Cls.foo==5).filter(Cls.bar==7)))
251 would return [5, 7].
259 would return [5, 7].
252
260
253 """
261 """
254 v = []
262 v = []
255 def visit_bindparam(bind):
263 def visit_bindparam(bind):
256 value = query._params.get(bind.key, bind.value)
264 value = query._params.get(bind.key, bind.value)
257
265
258 # lazyloader may dig a callable in here, intended
266 # lazyloader may dig a callable in here, intended
259 # to late-evaluate params after autoflush is called.
267 # to late-evaluate params after autoflush is called.
260 # convert to a scalar value.
268 # convert to a scalar value.
261 if callable(value):
269 if callable(value):
262 value = value()
270 value = value()
263
271
264 v.append(value)
272 v.append(value)
265 if query._criterion is not None:
273 if query._criterion is not None:
266 visitors.traverse(query._criterion, {}, {'bindparam':visit_bindparam})
274 visitors.traverse(query._criterion, {}, {'bindparam':visit_bindparam})
267 return v
275 return v
@@ -1,63 +1,33 b''
1 """SQLAlchemy Metadata and Session object"""
1 """SQLAlchemy Metadata and Session object"""
2 from sqlalchemy.ext.declarative import declarative_base
2 from sqlalchemy.ext.declarative import declarative_base
3 from sqlalchemy.orm import scoped_session, sessionmaker
3 from sqlalchemy.orm import scoped_session, sessionmaker
4 from rhodecode.model import caching_query
4 from rhodecode.model import caching_query
5 from beaker import cache
5 from beaker import cache
6 import os
6 import os
7 from os.path import join as jn, dirname as dn, abspath
7 from os.path import join as jn, dirname as dn, abspath
8 import time
8 import time
9
9
10 # Beaker CacheManager. A home base for cache configurations.
10 # Beaker CacheManager. A home base for cache configurations.
11 cache_manager = cache.CacheManager()
11 cache_manager = cache.CacheManager()
12
12
13 __all__ = ['Base', 'Session']
13 __all__ = ['Base', 'Session']
14 #
14 #
15 # SQLAlchemy session manager. Updated by model.init_model()
15 # SQLAlchemy session manager. Updated by model.init_model()
16 #
16 #
17 Session = scoped_session(
17 Session = scoped_session(
18 sessionmaker(
18 sessionmaker(
19 query_cls=caching_query.query_callable(cache_manager)
19 query_cls=caching_query.query_callable(cache_manager)
20 )
20 )
21 )
21 )
22
22
23 # The declarative Base
23 # The declarative Base
24 Base = declarative_base()
24 Base = declarative_base()
25 #For another db...
25 #For another db...
26 #Base2 = declarative_base()
26 #Base2 = declarative_base()
27
27
28 #===============================================================================
28 #===============================================================================
29 # CACHE OPTIONS
29 # CACHE OPTIONS
30 #===============================================================================
30 #===============================================================================
31 cache_base = jn(dn(dn(dn(abspath(__file__)))), 'data')
31 #Configured globally in .ini files
32 cache_dir = jn(cache_base, 'cache')
33
34 if not os.path.isdir(cache_base):
35 os.mkdir(cache_base)
36
37 if not os.path.isdir(cache_dir):
38 os.mkdir(cache_dir)
39 # set start_time to current time
40 # to re-cache everything
41 # upon application startup
42 start_time = time.time()
43 # configure the "sqlalchemy" cache region.
44 cache_manager.regions['sql_cache_short'] = {
45 'type':'memory',
46 'data_dir':cache_dir,
47 'expire':10,
48 'start_time':start_time
49 }
50 cache_manager.regions['sql_cache_med'] = {
51 'type':'memory',
52 'data_dir':cache_dir,
53 'expire':360,
54 'start_time':start_time
55 }
56 cache_manager.regions['sql_cache_long'] = {
57 'type':'file',
58 'data_dir':cache_dir,
59 'expire':3600,
60 'start_time':start_time
61 }
62 #to use cache use this in query
32 #to use cache use this in query
63 #.options(FromCache("sqlalchemy_cache_type", "cachekey"))
33 #.options(FromCache("sqlalchemy_cache_type", "cachekey"))
General Comments 0
You need to be logged in to leave comments. Login now