##// END OF EJS Templates
Added api_key into user, api key get's generated again after password change...
marcink -
r1116:716911af beta
parent child Browse files
Show More
@@ -1,221 +1,221 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 #smtp_use_ssl = true
25 #smtp_use_ssl = true
26
26
27 [server:main]
27 [server:main]
28 ##nr of threads to spawn
28 ##nr of threads to spawn
29 threadpool_workers = 5
29 threadpool_workers = 5
30
30
31 ##max request before thread respawn
31 ##max request before thread respawn
32 threadpool_max_requests = 6
32 threadpool_max_requests = 6
33
33
34 ##option to use threads of process
34 ##option to use threads of process
35 use_threadpool = false
35 use_threadpool = true
36
36
37 use = egg:Paste#http
37 use = egg:Paste#http
38 host = 0.0.0.0
38 host = 0.0.0.0
39 port = 5000
39 port = 5000
40
40
41 [app:main]
41 [app:main]
42 use = egg:rhodecode
42 use = egg:rhodecode
43 full_stack = true
43 full_stack = true
44 static_files = true
44 static_files = true
45 lang=en
45 lang=en
46 cache_dir = %(here)s/data
46 cache_dir = %(here)s/data
47 index_dir = %(here)s/data/index
47 index_dir = %(here)s/data/index
48 app_instance_uuid = develop
48 app_instance_uuid = develop
49 cut_off_limit = 256000
49 cut_off_limit = 256000
50 force_https = false
50 force_https = false
51 commit_parse_limit = 25
51 commit_parse_limit = 25
52 use_gravatar = true
52 use_gravatar = true
53
53
54 ####################################
54 ####################################
55 ### CELERY CONFIG ####
55 ### CELERY CONFIG ####
56 ####################################
56 ####################################
57 use_celery = false
57 use_celery = false
58 broker.host = localhost
58 broker.host = localhost
59 broker.vhost = rabbitmqhost
59 broker.vhost = rabbitmqhost
60 broker.port = 5672
60 broker.port = 5672
61 broker.user = rabbitmq
61 broker.user = rabbitmq
62 broker.password = qweqwe
62 broker.password = qweqwe
63
63
64 celery.imports = rhodecode.lib.celerylib.tasks
64 celery.imports = rhodecode.lib.celerylib.tasks
65
65
66 celery.result.backend = amqp
66 celery.result.backend = amqp
67 celery.result.dburi = amqp://
67 celery.result.dburi = amqp://
68 celery.result.serialier = json
68 celery.result.serialier = json
69
69
70 #celery.send.task.error.emails = true
70 #celery.send.task.error.emails = true
71 #celery.amqp.task.result.expires = 18000
71 #celery.amqp.task.result.expires = 18000
72
72
73 celeryd.concurrency = 2
73 celeryd.concurrency = 2
74 #celeryd.log.file = celeryd.log
74 #celeryd.log.file = celeryd.log
75 celeryd.log.level = debug
75 celeryd.log.level = debug
76 celeryd.max.tasks.per.child = 1
76 celeryd.max.tasks.per.child = 1
77
77
78 #tasks will never be sent to the queue, but executed locally instead.
78 #tasks will never be sent to the queue, but executed locally instead.
79 celery.always.eager = false
79 celery.always.eager = false
80
80
81 ####################################
81 ####################################
82 ### BEAKER CACHE ####
82 ### BEAKER CACHE ####
83 ####################################
83 ####################################
84 beaker.cache.data_dir=%(here)s/data/cache/data
84 beaker.cache.data_dir=%(here)s/data/cache/data
85 beaker.cache.lock_dir=%(here)s/data/cache/lock
85 beaker.cache.lock_dir=%(here)s/data/cache/lock
86
86
87 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
87 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
88
88
89 beaker.cache.super_short_term.type=memory
89 beaker.cache.super_short_term.type=memory
90 beaker.cache.super_short_term.expire=10
90 beaker.cache.super_short_term.expire=10
91
91
92 beaker.cache.short_term.type=memory
92 beaker.cache.short_term.type=memory
93 beaker.cache.short_term.expire=60
93 beaker.cache.short_term.expire=60
94
94
95 beaker.cache.long_term.type=memory
95 beaker.cache.long_term.type=memory
96 beaker.cache.long_term.expire=36000
96 beaker.cache.long_term.expire=36000
97
97
98 beaker.cache.sql_cache_short.type=memory
98 beaker.cache.sql_cache_short.type=memory
99 beaker.cache.sql_cache_short.expire=10
99 beaker.cache.sql_cache_short.expire=10
100
100
101 beaker.cache.sql_cache_med.type=memory
101 beaker.cache.sql_cache_med.type=memory
102 beaker.cache.sql_cache_med.expire=360
102 beaker.cache.sql_cache_med.expire=360
103
103
104 beaker.cache.sql_cache_long.type=file
104 beaker.cache.sql_cache_long.type=file
105 beaker.cache.sql_cache_long.expire=3600
105 beaker.cache.sql_cache_long.expire=3600
106
106
107 ####################################
107 ####################################
108 ### BEAKER SESSION ####
108 ### BEAKER SESSION ####
109 ####################################
109 ####################################
110 ## Type of storage used for the session, current types are
110 ## Type of storage used for the session, current types are
111 ## dbm, file, memcached, database, and memory.
111 ## dbm, file, memcached, database, and memory.
112 ## The storage uses the Container API
112 ## The storage uses the Container API
113 ##that is also used by the cache system.
113 ##that is also used by the cache system.
114 beaker.session.type = file
114 beaker.session.type = file
115
115
116 beaker.session.key = rhodecode
116 beaker.session.key = rhodecode
117 beaker.session.secret = g654dcno0-9873jhgfreyu
117 beaker.session.secret = g654dcno0-9873jhgfreyu
118 beaker.session.timeout = 36000
118 beaker.session.timeout = 36000
119
119
120 ##auto save the session to not to use .save()
120 ##auto save the session to not to use .save()
121 beaker.session.auto = False
121 beaker.session.auto = False
122
122
123 ##true exire at browser close
123 ##true exire at browser close
124 #beaker.session.cookie_expires = 3600
124 #beaker.session.cookie_expires = 3600
125
125
126
126
127 ################################################################################
127 ################################################################################
128 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
128 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
129 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
129 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
130 ## execute malicious code after an exception is raised. ##
130 ## execute malicious code after an exception is raised. ##
131 ################################################################################
131 ################################################################################
132 #set debug = false
132 #set debug = false
133
133
134 ##################################
134 ##################################
135 ### LOGVIEW CONFIG ###
135 ### LOGVIEW CONFIG ###
136 ##################################
136 ##################################
137 logview.sqlalchemy = #faa
137 logview.sqlalchemy = #faa
138 logview.pylons.templating = #bfb
138 logview.pylons.templating = #bfb
139 logview.pylons.util = #eee
139 logview.pylons.util = #eee
140
140
141 #########################################################
141 #########################################################
142 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
142 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
143 #########################################################
143 #########################################################
144 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
144 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
145 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
145 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
146 #sqlalchemy.db1.echo = False
146 #sqlalchemy.db1.echo = False
147 #sqlalchemy.db1.pool_recycle = 3600
147 #sqlalchemy.db1.pool_recycle = 3600
148 sqlalchemy.convert_unicode = true
148 sqlalchemy.convert_unicode = true
149
149
150 ################################
150 ################################
151 ### LOGGING CONFIGURATION ####
151 ### LOGGING CONFIGURATION ####
152 ################################
152 ################################
153 [loggers]
153 [loggers]
154 keys = root, routes, rhodecode, sqlalchemy,beaker,templates
154 keys = root, routes, rhodecode, sqlalchemy,beaker,templates
155
155
156 [handlers]
156 [handlers]
157 keys = console
157 keys = console
158
158
159 [formatters]
159 [formatters]
160 keys = generic,color_formatter
160 keys = generic,color_formatter
161
161
162 #############
162 #############
163 ## LOGGERS ##
163 ## LOGGERS ##
164 #############
164 #############
165 [logger_root]
165 [logger_root]
166 level = NOTSET
166 level = NOTSET
167 handlers = console
167 handlers = console
168
168
169 [logger_routes]
169 [logger_routes]
170 level = DEBUG
170 level = DEBUG
171 handlers = console
171 handlers = console
172 qualname = routes.middleware
172 qualname = routes.middleware
173 # "level = DEBUG" logs the route matched and routing variables.
173 # "level = DEBUG" logs the route matched and routing variables.
174 propagate = 0
174 propagate = 0
175
175
176 [logger_beaker]
176 [logger_beaker]
177 level = ERROR
177 level = ERROR
178 handlers = console
178 handlers = console
179 qualname = beaker.container
179 qualname = beaker.container
180 propagate = 0
180 propagate = 0
181
181
182 [logger_templates]
182 [logger_templates]
183 level = INFO
183 level = INFO
184 handlers = console
184 handlers = console
185 qualname = pylons.templating
185 qualname = pylons.templating
186 propagate = 0
186 propagate = 0
187
187
188 [logger_rhodecode]
188 [logger_rhodecode]
189 level = DEBUG
189 level = DEBUG
190 handlers = console
190 handlers = console
191 qualname = rhodecode
191 qualname = rhodecode
192 propagate = 0
192 propagate = 0
193
193
194 [logger_sqlalchemy]
194 [logger_sqlalchemy]
195 level = ERROR
195 level = ERROR
196 handlers = console
196 handlers = console
197 qualname = sqlalchemy.engine
197 qualname = sqlalchemy.engine
198 propagate = 0
198 propagate = 0
199
199
200 ##############
200 ##############
201 ## HANDLERS ##
201 ## HANDLERS ##
202 ##############
202 ##############
203
203
204 [handler_console]
204 [handler_console]
205 class = StreamHandler
205 class = StreamHandler
206 args = (sys.stderr,)
206 args = (sys.stderr,)
207 level = NOTSET
207 level = NOTSET
208 formatter = color_formatter
208 formatter = color_formatter
209
209
210 ################
210 ################
211 ## FORMATTERS ##
211 ## FORMATTERS ##
212 ################
212 ################
213
213
214 [formatter_generic]
214 [formatter_generic]
215 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
215 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
216 datefmt = %Y-%m-%d %H:%M:%S
216 datefmt = %Y-%m-%d %H:%M:%S
217
217
218 [formatter_color_formatter]
218 [formatter_color_formatter]
219 class=rhodecode.lib.colored_formatter.ColorFormatter
219 class=rhodecode.lib.colored_formatter.ColorFormatter
220 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
220 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
221 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
221 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,220 +1,220 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 #smtp_use_ssl = true
25 #smtp_use_ssl = true
26
26
27 [server:main]
27 [server:main]
28 ##nr of threads to spawn
28 ##nr of threads to spawn
29 threadpool_workers = 5
29 threadpool_workers = 5
30
30
31 ##max request before thread respawn
31 ##max request before thread respawn
32 threadpool_max_requests = 2
32 threadpool_max_requests = 6
33
33
34 ##option to use threads of process
34 ##option to use threads of process
35 use_threadpool = true
35 use_threadpool = true
36
36
37 use = egg:Paste#http
37 use = egg:Paste#http
38 host = 127.0.0.1
38 host = 127.0.0.1
39 port = 8001
39 port = 8001
40
40
41 [app:main]
41 [app:main]
42 use = egg:rhodecode
42 use = egg:rhodecode
43 full_stack = true
43 full_stack = true
44 static_files = false
44 static_files = false
45 lang=en
45 lang=en
46 cache_dir = %(here)s/data
46 cache_dir = %(here)s/data
47 index_dir = %(here)s/data/index
47 index_dir = %(here)s/data/index
48 cut_off_limit = 256000
48 cut_off_limit = 256000
49 force_https = false
49 force_https = false
50 commit_parse_limit = 250
50 commit_parse_limit = 25
51 use_gravatar = true
51 use_gravatar = true
52
52
53 ####################################
53 ####################################
54 ### CELERY CONFIG ####
54 ### CELERY CONFIG ####
55 ####################################
55 ####################################
56 use_celery = false
56 use_celery = false
57 broker.host = localhost
57 broker.host = localhost
58 broker.vhost = rabbitmqhost
58 broker.vhost = rabbitmqhost
59 broker.port = 5672
59 broker.port = 5672
60 broker.user = rabbitmq
60 broker.user = rabbitmq
61 broker.password = qweqwe
61 broker.password = qweqwe
62
62
63 celery.imports = rhodecode.lib.celerylib.tasks
63 celery.imports = rhodecode.lib.celerylib.tasks
64
64
65 celery.result.backend = amqp
65 celery.result.backend = amqp
66 celery.result.dburi = amqp://
66 celery.result.dburi = amqp://
67 celery.result.serialier = json
67 celery.result.serialier = json
68
68
69 #celery.send.task.error.emails = true
69 #celery.send.task.error.emails = true
70 #celery.amqp.task.result.expires = 18000
70 #celery.amqp.task.result.expires = 18000
71
71
72 celeryd.concurrency = 2
72 celeryd.concurrency = 2
73 #celeryd.log.file = celeryd.log
73 #celeryd.log.file = celeryd.log
74 celeryd.log.level = debug
74 celeryd.log.level = debug
75 celeryd.max.tasks.per.child = 1
75 celeryd.max.tasks.per.child = 1
76
76
77 #tasks will never be sent to the queue, but executed locally instead.
77 #tasks will never be sent to the queue, but executed locally instead.
78 celery.always.eager = false
78 celery.always.eager = false
79
79
80 ####################################
80 ####################################
81 ### BEAKER CACHE ####
81 ### BEAKER CACHE ####
82 ####################################
82 ####################################
83 beaker.cache.data_dir=%(here)s/data/cache/data
83 beaker.cache.data_dir=%(here)s/data/cache/data
84 beaker.cache.lock_dir=%(here)s/data/cache/lock
84 beaker.cache.lock_dir=%(here)s/data/cache/lock
85
85
86 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
86 beaker.cache.regions=super_short_term,short_term,long_term,sql_cache_short,sql_cache_med,sql_cache_long
87
87
88 beaker.cache.super_short_term.type=memory
88 beaker.cache.super_short_term.type=memory
89 beaker.cache.super_short_term.expire=10
89 beaker.cache.super_short_term.expire=10
90
90
91 beaker.cache.short_term.type=memory
91 beaker.cache.short_term.type=memory
92 beaker.cache.short_term.expire=60
92 beaker.cache.short_term.expire=60
93
93
94 beaker.cache.long_term.type=memory
94 beaker.cache.long_term.type=memory
95 beaker.cache.long_term.expire=36000
95 beaker.cache.long_term.expire=36000
96
96
97
98 beaker.cache.sql_cache_short.type=memory
97 beaker.cache.sql_cache_short.type=memory
99 beaker.cache.sql_cache_short.expire=10
98 beaker.cache.sql_cache_short.expire=10
100
99
101 beaker.cache.sql_cache_med.type=memory
100 beaker.cache.sql_cache_med.type=memory
102 beaker.cache.sql_cache_med.expire=360
101 beaker.cache.sql_cache_med.expire=360
103
102
104 beaker.cache.sql_cache_long.type=file
103 beaker.cache.sql_cache_long.type=file
105 beaker.cache.sql_cache_long.expire=3600
104 beaker.cache.sql_cache_long.expire=3600
106
105
107 ####################################
106 ####################################
108 ### BEAKER SESSION ####
107 ### BEAKER SESSION ####
109 ####################################
108 ####################################
110 ## Type of storage used for the session, current types are
109 ## Type of storage used for the session, current types are
111 ## dbm, file, memcached, database, and memory.
110 ## dbm, file, memcached, database, and memory.
112 ## The storage uses the Container API
111 ## The storage uses the Container API
113 ##that is also used by the cache system.
112 ##that is also used by the cache system.
114 beaker.session.type = file
113 beaker.session.type = file
115
114
116 beaker.session.key = rhodecode
115 beaker.session.key = rhodecode
117 beaker.session.secret = g654dcno0-9873jhgfreyu
116 beaker.session.secret = g654dcno0-9873jhgfreyu
118 beaker.session.timeout = 36000
117 beaker.session.timeout = 36000
119
118
120 ##auto save the session to not to use .save()
119 ##auto save the session to not to use .save()
121 beaker.session.auto = False
120 beaker.session.auto = False
122
121
123 ##true exire at browser close
122 ##true exire at browser close
124 #beaker.session.cookie_expires = 3600
123 #beaker.session.cookie_expires = 3600
125
124
126
125
127 ################################################################################
126 ################################################################################
128 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
127 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
129 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
128 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
130 ## execute malicious code after an exception is raised. ##
129 ## execute malicious code after an exception is raised. ##
131 ################################################################################
130 ################################################################################
132 set debug = false
131 set debug = false
133
132
134 ##################################
133 ##################################
135 ### LOGVIEW CONFIG ###
134 ### LOGVIEW CONFIG ###
136 ##################################
135 ##################################
137 logview.sqlalchemy = #faa
136 logview.sqlalchemy = #faa
138 logview.pylons.templating = #bfb
137 logview.pylons.templating = #bfb
139 logview.pylons.util = #eee
138 logview.pylons.util = #eee
140
139
141 #########################################################
140 #########################################################
142 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
141 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
143 #########################################################
142 #########################################################
144 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
143 #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db
144 sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode
145 #sqlalchemy.db1.echo = False
145 #sqlalchemy.db1.echo = False
146 #sqlalchemy.db1.pool_recycle = 3600
146 #sqlalchemy.db1.pool_recycle = 3600
147 sqlalchemy.convert_unicode = true
147 sqlalchemy.convert_unicode = true
148
148
149 ################################
149 ################################
150 ### LOGGING CONFIGURATION ####
150 ### LOGGING CONFIGURATION ####
151 ################################
151 ################################
152 [loggers]
152 [loggers]
153 keys = root, routes, rhodecode, sqlalchemy,beaker,templates
153 keys = root, routes, rhodecode, sqlalchemy,beaker,templates
154
154
155 [handlers]
155 [handlers]
156 keys = console
156 keys = console
157
157
158 [formatters]
158 [formatters]
159 keys = generic,color_formatter
159 keys = generic,color_formatter
160
160
161 #############
161 #############
162 ## LOGGERS ##
162 ## LOGGERS ##
163 #############
163 #############
164 [logger_root]
164 [logger_root]
165 level = INFO
165 level = INFO
166 handlers = console
166 handlers = console
167
167
168 [logger_routes]
168 [logger_routes]
169 level = INFO
169 level = INFO
170 handlers = console
170 handlers = console
171 qualname = routes.middleware
171 qualname = routes.middleware
172 # "level = DEBUG" logs the route matched and routing variables.
172 # "level = DEBUG" logs the route matched and routing variables.
173 propagate = 0
173 propagate = 0
174
174
175 [logger_beaker]
175 [logger_beaker]
176 level = ERROR
176 level = ERROR
177 handlers = console
177 handlers = console
178 qualname = beaker.container
178 qualname = beaker.container
179 propagate = 0
179 propagate = 0
180
180
181 [logger_templates]
181 [logger_templates]
182 level = INFO
182 level = INFO
183 handlers = console
183 handlers = console
184 qualname = pylons.templating
184 qualname = pylons.templating
185 propagate = 0
185 propagate = 0
186
186
187 [logger_rhodecode]
187 [logger_rhodecode]
188 level = DEBUG
188 level = DEBUG
189 handlers = console
189 handlers = console
190 qualname = rhodecode
190 qualname = rhodecode
191 propagate = 0
191 propagate = 0
192
192
193 [logger_sqlalchemy]
193 [logger_sqlalchemy]
194 level = ERROR
194 level = ERROR
195 handlers = console
195 handlers = console
196 qualname = sqlalchemy.engine
196 qualname = sqlalchemy.engine
197 propagate = 0
197 propagate = 0
198
198
199 ##############
199 ##############
200 ## HANDLERS ##
200 ## HANDLERS ##
201 ##############
201 ##############
202
202
203 [handler_console]
203 [handler_console]
204 class = StreamHandler
204 class = StreamHandler
205 args = (sys.stderr,)
205 args = (sys.stderr,)
206 level = NOTSET
206 level = NOTSET
207 formatter = color_formatter
207 formatter = color_formatter
208
208
209 ################
209 ################
210 ## FORMATTERS ##
210 ## FORMATTERS ##
211 ################
211 ################
212
212
213 [formatter_generic]
213 [formatter_generic]
214 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
214 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
215 datefmt = %Y-%m-%d %H:%M:%S
215 datefmt = %Y-%m-%d %H:%M:%S
216
216
217 [formatter_color_formatter]
217 [formatter_color_formatter]
218 class=rhodecode.lib.colored_formatter.ColorFormatter
218 class=rhodecode.lib.colored_formatter.ColorFormatter
219 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
219 format= %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
220 datefmt = %Y-%m-%d %H:%M:%S No newline at end of file
220 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,29 +1,38 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.__init__
3 rhodecode.lib.__init__
4 ~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Some simple helper functions
6 Some simple helper functions
7
7
8 :created_on: Jan 5, 2011
8 :created_on: Jan 5, 2011
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2009-2010 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
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 def str2bool(v):
28 def str2bool(v):
29 return v.lower() in ["yes", "true", "t", "1"] if v else None
29 return v.lower() in ["yes", "true", "t", "1"] if v else None
30
31 def generate_api_key(username, salt=None):
32 from tempfile import _RandomNameSequence
33 import hashlib
34
35 if salt is None:
36 salt = _RandomNameSequence().next()
37
38 return hashlib.sha1(username + salt).hexdigest()
@@ -1,614 +1,621 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) 2010 by marcink.
9 :copyright: (c) 2010 by marcink.
10 :license: LICENSE_NAME, see LICENSE_FILE for more details.
10 :license: LICENSE_NAME, see LICENSE_FILE for more details.
11 """
11 """
12 # This program is free software; you can redistribute it and/or
12 # This program is free software; you can redistribute it and/or
13 # modify it under the terms of the GNU General Public License
13 # modify it under the terms of the GNU General Public License
14 # as published by the Free Software Foundation; version 2
14 # as published by the Free Software Foundation; version 2
15 # of the License or (at your opinion) any later version of the license.
15 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # MA 02110-1301, USA.
25 # MA 02110-1301, USA.
26
26
27 import bcrypt
27 import bcrypt
28 import random
28 import random
29 import logging
29 import logging
30 import traceback
30 import traceback
31
31 import hashlib
32 from tempfile import _RandomNameSequence
32 from decorator import decorator
33 from decorator import decorator
33
34
34 from pylons import config, session, url, request
35 from pylons import config, session, url, request
35 from pylons.controllers.util import abort, redirect
36 from pylons.controllers.util import abort, redirect
36 from pylons.i18n.translation import _
37 from pylons.i18n.translation import _
37
38
38 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
39 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
39 from rhodecode.lib.utils import get_repo_slug
40 from rhodecode.lib.utils import get_repo_slug
40 from rhodecode.lib.auth_ldap import AuthLdap
41 from rhodecode.lib.auth_ldap import AuthLdap
41
42
42 from rhodecode.model import meta
43 from rhodecode.model import meta
43 from rhodecode.model.user import UserModel
44 from rhodecode.model.user import UserModel
44 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
45 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
45 UserToPerm, UsersGroupToPerm, UsersGroupMember
46 UserToPerm, UsersGroupToPerm, UsersGroupMember
46
47
47
48
48 log = logging.getLogger(__name__)
49 log = logging.getLogger(__name__)
49
50
50
51
51 PERM_WEIGHTS = {'repository.none':0,
52 PERM_WEIGHTS = {'repository.none':0,
52 'repository.read':1,
53 'repository.read':1,
53 'repository.write':3,
54 'repository.write':3,
54 'repository.admin':3}
55 'repository.admin':3}
55
56
56
57
57 class PasswordGenerator(object):
58 class PasswordGenerator(object):
58 """This is a simple class for generating password from
59 """This is a simple class for generating password from
59 different sets of characters
60 different sets of characters
60 usage:
61 usage:
61 passwd_gen = PasswordGenerator()
62 passwd_gen = PasswordGenerator()
62 #print 8-letter password containing only big and small letters of alphabet
63 #print 8-letter password containing only big and small letters of alphabet
63 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
64 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
64 """
65 """
65 ALPHABETS_NUM = r'''1234567890'''#[0]
66 ALPHABETS_NUM = r'''1234567890'''#[0]
66 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
67 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
67 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
68 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
68 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
69 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
69 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
70 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
70 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
71 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
71 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
72 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
72 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
73 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
73 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
74 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
74
75
75 def __init__(self, passwd=''):
76 def __init__(self, passwd=''):
76 self.passwd = passwd
77 self.passwd = passwd
77
78
78 def gen_password(self, len, type):
79 def gen_password(self, len, type):
79 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
80 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
80 return self.passwd
81 return self.passwd
81
82
82
83
83 def get_crypt_password(password):
84 def get_crypt_password(password):
84 """Cryptographic function used for password hashing based on pybcrypt
85 """Cryptographic function used for password hashing based on pybcrypt
85
86
86 :param password: password to hash
87 :param password: password to hash
87 """
88 """
88 return bcrypt.hashpw(password, bcrypt.gensalt(10))
89 return bcrypt.hashpw(password, bcrypt.gensalt(10))
89
90
91 def generate_api_key(username, salt=None):
92 if salt is None:
93 salt = _RandomNameSequence().next()
94
95 return hashlib.sha1(username + salt).hexdigest()
96
90 def check_password(password, hashed):
97 def check_password(password, hashed):
91 return bcrypt.hashpw(password, hashed) == hashed
98 return bcrypt.hashpw(password, hashed) == hashed
92
99
93 def authfunc(environ, username, password):
100 def authfunc(environ, username, password):
94 """Dummy authentication function used in Mercurial/Git/ and access control,
101 """Dummy authentication function used in Mercurial/Git/ and access control,
95
102
96 :param environ: needed only for using in Basic auth
103 :param environ: needed only for using in Basic auth
97 """
104 """
98 return authenticate(username, password)
105 return authenticate(username, password)
99
106
100
107
101 def authenticate(username, password):
108 def authenticate(username, password):
102 """Authentication function used for access control,
109 """Authentication function used for access control,
103 firstly checks for db authentication then if ldap is enabled for ldap
110 firstly checks for db authentication then if ldap is enabled for ldap
104 authentication, also creates ldap user if not in database
111 authentication, also creates ldap user if not in database
105
112
106 :param username: username
113 :param username: username
107 :param password: password
114 :param password: password
108 """
115 """
109 user_model = UserModel()
116 user_model = UserModel()
110 user = user_model.get_by_username(username, cache=False)
117 user = user_model.get_by_username(username, cache=False)
111
118
112 log.debug('Authenticating user using RhodeCode account')
119 log.debug('Authenticating user using RhodeCode account')
113 if user is not None and not user.ldap_dn:
120 if user is not None and not user.ldap_dn:
114 if user.active:
121 if user.active:
115
122
116 if user.username == 'default' and user.active:
123 if user.username == 'default' and user.active:
117 log.info('user %s authenticated correctly as anonymous user',
124 log.info('user %s authenticated correctly as anonymous user',
118 username)
125 username)
119 return True
126 return True
120
127
121 elif user.username == username and check_password(password, user.password):
128 elif user.username == username and check_password(password, user.password):
122 log.info('user %s authenticated correctly', username)
129 log.info('user %s authenticated correctly', username)
123 return True
130 return True
124 else:
131 else:
125 log.warning('user %s is disabled', username)
132 log.warning('user %s is disabled', username)
126
133
127 else:
134 else:
128 log.debug('Regular authentication failed')
135 log.debug('Regular authentication failed')
129 user_obj = user_model.get_by_username(username, cache=False,
136 user_obj = user_model.get_by_username(username, cache=False,
130 case_insensitive=True)
137 case_insensitive=True)
131
138
132 if user_obj is not None and not user_obj.ldap_dn:
139 if user_obj is not None and not user_obj.ldap_dn:
133 log.debug('this user already exists as non ldap')
140 log.debug('this user already exists as non ldap')
134 return False
141 return False
135
142
136 from rhodecode.model.settings import SettingsModel
143 from rhodecode.model.settings import SettingsModel
137 ldap_settings = SettingsModel().get_ldap_settings()
144 ldap_settings = SettingsModel().get_ldap_settings()
138
145
139 #======================================================================
146 #======================================================================
140 # FALLBACK TO LDAP AUTH IF ENABLE
147 # FALLBACK TO LDAP AUTH IF ENABLE
141 #======================================================================
148 #======================================================================
142 if ldap_settings.get('ldap_active', False):
149 if ldap_settings.get('ldap_active', False):
143 log.debug("Authenticating user using ldap")
150 log.debug("Authenticating user using ldap")
144 kwargs = {
151 kwargs = {
145 'server':ldap_settings.get('ldap_host', ''),
152 'server':ldap_settings.get('ldap_host', ''),
146 'base_dn':ldap_settings.get('ldap_base_dn', ''),
153 'base_dn':ldap_settings.get('ldap_base_dn', ''),
147 'port':ldap_settings.get('ldap_port'),
154 'port':ldap_settings.get('ldap_port'),
148 'bind_dn':ldap_settings.get('ldap_dn_user'),
155 'bind_dn':ldap_settings.get('ldap_dn_user'),
149 'bind_pass':ldap_settings.get('ldap_dn_pass'),
156 'bind_pass':ldap_settings.get('ldap_dn_pass'),
150 'use_ldaps':ldap_settings.get('ldap_ldaps'),
157 'use_ldaps':ldap_settings.get('ldap_ldaps'),
151 'tls_reqcert':ldap_settings.get('ldap_tls_reqcert'),
158 'tls_reqcert':ldap_settings.get('ldap_tls_reqcert'),
152 'ldap_filter':ldap_settings.get('ldap_filter'),
159 'ldap_filter':ldap_settings.get('ldap_filter'),
153 'search_scope':ldap_settings.get('ldap_search_scope'),
160 'search_scope':ldap_settings.get('ldap_search_scope'),
154 'attr_login':ldap_settings.get('ldap_attr_login'),
161 'attr_login':ldap_settings.get('ldap_attr_login'),
155 'ldap_version':3,
162 'ldap_version':3,
156 }
163 }
157 log.debug('Checking for ldap authentication')
164 log.debug('Checking for ldap authentication')
158 try:
165 try:
159 aldap = AuthLdap(**kwargs)
166 aldap = AuthLdap(**kwargs)
160 (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password)
167 (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password)
161 log.debug('Got ldap DN response %s', user_dn)
168 log.debug('Got ldap DN response %s', user_dn)
162
169
163 user_attrs = {
170 user_attrs = {
164 'name' : ldap_attrs[ldap_settings.get('ldap_attr_firstname')][0],
171 'name' : ldap_attrs[ldap_settings.get('ldap_attr_firstname')][0],
165 'lastname' : ldap_attrs[ldap_settings.get('ldap_attr_lastname')][0],
172 'lastname' : ldap_attrs[ldap_settings.get('ldap_attr_lastname')][0],
166 'email' : ldap_attrs[ldap_settings.get('ldap_attr_email')][0],
173 'email' : ldap_attrs[ldap_settings.get('ldap_attr_email')][0],
167 }
174 }
168
175
169 if user_model.create_ldap(username, password, user_dn, user_attrs):
176 if user_model.create_ldap(username, password, user_dn, user_attrs):
170 log.info('created new ldap user %s', username)
177 log.info('created new ldap user %s', username)
171
178
172 return True
179 return True
173 except (LdapUsernameError, LdapPasswordError,):
180 except (LdapUsernameError, LdapPasswordError,):
174 pass
181 pass
175 except (Exception,):
182 except (Exception,):
176 log.error(traceback.format_exc())
183 log.error(traceback.format_exc())
177 pass
184 pass
178 return False
185 return False
179
186
180 class AuthUser(object):
187 class AuthUser(object):
181 """A simple object that handles a mercurial username for authentication
188 """A simple object that handles a mercurial username for authentication
182 """
189 """
183
190
184 def __init__(self):
191 def __init__(self):
185 self.username = 'None'
192 self.username = 'None'
186 self.name = ''
193 self.name = ''
187 self.lastname = ''
194 self.lastname = ''
188 self.email = ''
195 self.email = ''
189 self.user_id = None
196 self.user_id = None
190 self.is_authenticated = False
197 self.is_authenticated = False
191 self.is_admin = False
198 self.is_admin = False
192 self.permissions = {}
199 self.permissions = {}
193
200
194 def __repr__(self):
201 def __repr__(self):
195 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
202 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
196
203
197 def set_available_permissions(config):
204 def set_available_permissions(config):
198 """This function will propagate pylons globals with all available defined
205 """This function will propagate pylons globals with all available defined
199 permission given in db. We don't want to check each time from db for new
206 permission given in db. We don't want to check each time from db for new
200 permissions since adding a new permission also requires application restart
207 permissions since adding a new permission also requires application restart
201 ie. to decorate new views with the newly created permission
208 ie. to decorate new views with the newly created permission
202
209
203 :param config: current pylons config instance
210 :param config: current pylons config instance
204
211
205 """
212 """
206 log.info('getting information about all available permissions')
213 log.info('getting information about all available permissions')
207 try:
214 try:
208 sa = meta.Session()
215 sa = meta.Session()
209 all_perms = sa.query(Permission).all()
216 all_perms = sa.query(Permission).all()
210 except:
217 except:
211 pass
218 pass
212 finally:
219 finally:
213 meta.Session.remove()
220 meta.Session.remove()
214
221
215 config['available_permissions'] = [x.permission_name for x in all_perms]
222 config['available_permissions'] = [x.permission_name for x in all_perms]
216
223
217 def fill_perms(user):
224 def fill_perms(user):
218 """Fills user permission attribute with permissions taken from database
225 """Fills user permission attribute with permissions taken from database
219 works for permissions given for repositories, and for permissions that
226 works for permissions given for repositories, and for permissions that
220 as part of beeing group member
227 as part of beeing group member
221
228
222 :param user: user instance to fill his perms
229 :param user: user instance to fill his perms
223 """
230 """
224
231
225 sa = meta.Session()
232 sa = meta.Session()
226 user.permissions['repositories'] = {}
233 user.permissions['repositories'] = {}
227 user.permissions['global'] = set()
234 user.permissions['global'] = set()
228
235
229 #===========================================================================
236 #===========================================================================
230 # fetch default permissions
237 # fetch default permissions
231 #===========================================================================
238 #===========================================================================
232 default_user = UserModel().get_by_username('default', cache=True)
239 default_user = UserModel().get_by_username('default', cache=True)
233
240
234 default_perms = sa.query(RepoToPerm, Repository, Permission)\
241 default_perms = sa.query(RepoToPerm, Repository, Permission)\
235 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
242 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
236 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
243 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
237 .filter(RepoToPerm.user == default_user).all()
244 .filter(RepoToPerm.user == default_user).all()
238
245
239 if user.is_admin:
246 if user.is_admin:
240 #=======================================================================
247 #=======================================================================
241 # #admin have all default rights set to admin
248 # #admin have all default rights set to admin
242 #=======================================================================
249 #=======================================================================
243 user.permissions['global'].add('hg.admin')
250 user.permissions['global'].add('hg.admin')
244
251
245 for perm in default_perms:
252 for perm in default_perms:
246 p = 'repository.admin'
253 p = 'repository.admin'
247 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
254 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
248
255
249 else:
256 else:
250 #=======================================================================
257 #=======================================================================
251 # set default permissions
258 # set default permissions
252 #=======================================================================
259 #=======================================================================
253
260
254 #default global
261 #default global
255 default_global_perms = sa.query(UserToPerm)\
262 default_global_perms = sa.query(UserToPerm)\
256 .filter(UserToPerm.user == sa.query(User)\
263 .filter(UserToPerm.user == sa.query(User)\
257 .filter(User.username == 'default').one())
264 .filter(User.username == 'default').one())
258
265
259 for perm in default_global_perms:
266 for perm in default_global_perms:
260 user.permissions['global'].add(perm.permission.permission_name)
267 user.permissions['global'].add(perm.permission.permission_name)
261
268
262 #default for repositories
269 #default for repositories
263 for perm in default_perms:
270 for perm in default_perms:
264 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
271 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
265 #disable defaults for private repos,
272 #disable defaults for private repos,
266 p = 'repository.none'
273 p = 'repository.none'
267 elif perm.Repository.user_id == user.user_id:
274 elif perm.Repository.user_id == user.user_id:
268 #set admin if owner
275 #set admin if owner
269 p = 'repository.admin'
276 p = 'repository.admin'
270 else:
277 else:
271 p = perm.Permission.permission_name
278 p = perm.Permission.permission_name
272
279
273 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
280 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
274
281
275 #=======================================================================
282 #=======================================================================
276 # overwrite default with user permissions if any
283 # overwrite default with user permissions if any
277 #=======================================================================
284 #=======================================================================
278 user_perms = sa.query(RepoToPerm, Permission, Repository)\
285 user_perms = sa.query(RepoToPerm, Permission, Repository)\
279 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
286 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
280 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
287 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
281 .filter(RepoToPerm.user_id == user.user_id).all()
288 .filter(RepoToPerm.user_id == user.user_id).all()
282
289
283 for perm in user_perms:
290 for perm in user_perms:
284 if perm.Repository.user_id == user.user_id:#set admin if owner
291 if perm.Repository.user_id == user.user_id:#set admin if owner
285 p = 'repository.admin'
292 p = 'repository.admin'
286 else:
293 else:
287 p = perm.Permission.permission_name
294 p = perm.Permission.permission_name
288 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
295 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
289
296
290
297
291 #=======================================================================
298 #=======================================================================
292 # check if user is part of groups for this repository and fill in
299 # check if user is part of groups for this repository and fill in
293 # (or replace with higher) permissions
300 # (or replace with higher) permissions
294 #=======================================================================
301 #=======================================================================
295 user_perms_from_users_groups = sa.query(UsersGroupToPerm, Permission, Repository,)\
302 user_perms_from_users_groups = sa.query(UsersGroupToPerm, Permission, Repository,)\
296 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
303 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
297 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
304 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
298 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
305 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
299 .filter(UsersGroupMember.user_id == user.user_id).all()
306 .filter(UsersGroupMember.user_id == user.user_id).all()
300
307
301 for perm in user_perms_from_users_groups:
308 for perm in user_perms_from_users_groups:
302 p = perm.Permission.permission_name
309 p = perm.Permission.permission_name
303 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
310 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
304 #overwrite permission only if it's greater than permission given from other sources
311 #overwrite permission only if it's greater than permission given from other sources
305 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
312 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
306 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
313 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
307
314
308 meta.Session.remove()
315 meta.Session.remove()
309 return user
316 return user
310
317
311 def get_user(session):
318 def get_user(session):
312 """Gets user from session, and wraps permissions into user
319 """Gets user from session, and wraps permissions into user
313
320
314 :param session:
321 :param session:
315 """
322 """
316 user = session.get('rhodecode_user', AuthUser())
323 user = session.get('rhodecode_user', AuthUser())
317 #if the user is not logged in we check for anonymous access
324 #if the user is not logged in we check for anonymous access
318 #if user is logged and it's a default user check if we still have anonymous
325 #if user is logged and it's a default user check if we still have anonymous
319 #access enabled
326 #access enabled
320 if user.user_id is None or user.username == 'default':
327 if user.user_id is None or user.username == 'default':
321 anonymous_user = UserModel().get_by_username('default', cache=True)
328 anonymous_user = UserModel().get_by_username('default', cache=True)
322 if anonymous_user.active is True:
329 if anonymous_user.active is True:
323 #then we set this user is logged in
330 #then we set this user is logged in
324 user.is_authenticated = True
331 user.is_authenticated = True
325 user.user_id = anonymous_user.user_id
332 user.user_id = anonymous_user.user_id
326 else:
333 else:
327 user.is_authenticated = False
334 user.is_authenticated = False
328
335
329 if user.is_authenticated:
336 if user.is_authenticated:
330 user = UserModel().fill_data(user)
337 user = UserModel().fill_data(user)
331
338
332 user = fill_perms(user)
339 user = fill_perms(user)
333 session['rhodecode_user'] = user
340 session['rhodecode_user'] = user
334 session.save()
341 session.save()
335 return user
342 return user
336
343
337 #===============================================================================
344 #===============================================================================
338 # CHECK DECORATORS
345 # CHECK DECORATORS
339 #===============================================================================
346 #===============================================================================
340 class LoginRequired(object):
347 class LoginRequired(object):
341 """Must be logged in to execute this function else
348 """Must be logged in to execute this function else
342 redirect to login page"""
349 redirect to login page"""
343
350
344 def __call__(self, func):
351 def __call__(self, func):
345 return decorator(self.__wrapper, func)
352 return decorator(self.__wrapper, func)
346
353
347 def __wrapper(self, func, *fargs, **fkwargs):
354 def __wrapper(self, func, *fargs, **fkwargs):
348 user = session.get('rhodecode_user', AuthUser())
355 user = session.get('rhodecode_user', AuthUser())
349 log.debug('Checking login required for user:%s', user.username)
356 log.debug('Checking login required for user:%s', user.username)
350 if user.is_authenticated:
357 if user.is_authenticated:
351 log.debug('user %s is authenticated', user.username)
358 log.debug('user %s is authenticated', user.username)
352 return func(*fargs, **fkwargs)
359 return func(*fargs, **fkwargs)
353 else:
360 else:
354 log.warn('user %s not authenticated', user.username)
361 log.warn('user %s not authenticated', user.username)
355
362
356 p = ''
363 p = ''
357 if request.environ.get('SCRIPT_NAME') != '/':
364 if request.environ.get('SCRIPT_NAME') != '/':
358 p += request.environ.get('SCRIPT_NAME')
365 p += request.environ.get('SCRIPT_NAME')
359
366
360 p += request.environ.get('PATH_INFO')
367 p += request.environ.get('PATH_INFO')
361 if request.environ.get('QUERY_STRING'):
368 if request.environ.get('QUERY_STRING'):
362 p += '?' + request.environ.get('QUERY_STRING')
369 p += '?' + request.environ.get('QUERY_STRING')
363
370
364 log.debug('redirecting to login page with %s', p)
371 log.debug('redirecting to login page with %s', p)
365 return redirect(url('login_home', came_from=p))
372 return redirect(url('login_home', came_from=p))
366
373
367 class NotAnonymous(object):
374 class NotAnonymous(object):
368 """Must be logged in to execute this function else
375 """Must be logged in to execute this function else
369 redirect to login page"""
376 redirect to login page"""
370
377
371 def __call__(self, func):
378 def __call__(self, func):
372 return decorator(self.__wrapper, func)
379 return decorator(self.__wrapper, func)
373
380
374 def __wrapper(self, func, *fargs, **fkwargs):
381 def __wrapper(self, func, *fargs, **fkwargs):
375 user = session.get('rhodecode_user', AuthUser())
382 user = session.get('rhodecode_user', AuthUser())
376 log.debug('Checking if user is not anonymous')
383 log.debug('Checking if user is not anonymous')
377
384
378 anonymous = user.username == 'default'
385 anonymous = user.username == 'default'
379
386
380 if anonymous:
387 if anonymous:
381 p = ''
388 p = ''
382 if request.environ.get('SCRIPT_NAME') != '/':
389 if request.environ.get('SCRIPT_NAME') != '/':
383 p += request.environ.get('SCRIPT_NAME')
390 p += request.environ.get('SCRIPT_NAME')
384
391
385 p += request.environ.get('PATH_INFO')
392 p += request.environ.get('PATH_INFO')
386 if request.environ.get('QUERY_STRING'):
393 if request.environ.get('QUERY_STRING'):
387 p += '?' + request.environ.get('QUERY_STRING')
394 p += '?' + request.environ.get('QUERY_STRING')
388
395
389 import rhodecode.lib.helpers as h
396 import rhodecode.lib.helpers as h
390 h.flash(_('You need to be a registered user to perform this action'),
397 h.flash(_('You need to be a registered user to perform this action'),
391 category='warning')
398 category='warning')
392 return redirect(url('login_home', came_from=p))
399 return redirect(url('login_home', came_from=p))
393 else:
400 else:
394 return func(*fargs, **fkwargs)
401 return func(*fargs, **fkwargs)
395
402
396 class PermsDecorator(object):
403 class PermsDecorator(object):
397 """Base class for decorators"""
404 """Base class for decorators"""
398
405
399 def __init__(self, *required_perms):
406 def __init__(self, *required_perms):
400 available_perms = config['available_permissions']
407 available_perms = config['available_permissions']
401 for perm in required_perms:
408 for perm in required_perms:
402 if perm not in available_perms:
409 if perm not in available_perms:
403 raise Exception("'%s' permission is not defined" % perm)
410 raise Exception("'%s' permission is not defined" % perm)
404 self.required_perms = set(required_perms)
411 self.required_perms = set(required_perms)
405 self.user_perms = None
412 self.user_perms = None
406
413
407 def __call__(self, func):
414 def __call__(self, func):
408 return decorator(self.__wrapper, func)
415 return decorator(self.__wrapper, func)
409
416
410
417
411 def __wrapper(self, func, *fargs, **fkwargs):
418 def __wrapper(self, func, *fargs, **fkwargs):
412 # _wrapper.__name__ = func.__name__
419 # _wrapper.__name__ = func.__name__
413 # _wrapper.__dict__.update(func.__dict__)
420 # _wrapper.__dict__.update(func.__dict__)
414 # _wrapper.__doc__ = func.__doc__
421 # _wrapper.__doc__ = func.__doc__
415 self.user = session.get('rhodecode_user', AuthUser())
422 self.user = session.get('rhodecode_user', AuthUser())
416 self.user_perms = self.user.permissions
423 self.user_perms = self.user.permissions
417 log.debug('checking %s permissions %s for %s %s',
424 log.debug('checking %s permissions %s for %s %s',
418 self.__class__.__name__, self.required_perms, func.__name__,
425 self.__class__.__name__, self.required_perms, func.__name__,
419 self.user)
426 self.user)
420
427
421 if self.check_permissions():
428 if self.check_permissions():
422 log.debug('Permission granted for %s %s', func.__name__, self.user)
429 log.debug('Permission granted for %s %s', func.__name__, self.user)
423
430
424 return func(*fargs, **fkwargs)
431 return func(*fargs, **fkwargs)
425
432
426 else:
433 else:
427 log.warning('Permission denied for %s %s', func.__name__, self.user)
434 log.warning('Permission denied for %s %s', func.__name__, self.user)
428 #redirect with forbidden ret code
435 #redirect with forbidden ret code
429 return abort(403)
436 return abort(403)
430
437
431
438
432
439
433 def check_permissions(self):
440 def check_permissions(self):
434 """Dummy function for overriding"""
441 """Dummy function for overriding"""
435 raise Exception('You have to write this function in child class')
442 raise Exception('You have to write this function in child class')
436
443
437 class HasPermissionAllDecorator(PermsDecorator):
444 class HasPermissionAllDecorator(PermsDecorator):
438 """Checks for access permission for all given predicates. All of them
445 """Checks for access permission for all given predicates. All of them
439 have to be meet in order to fulfill the request
446 have to be meet in order to fulfill the request
440 """
447 """
441
448
442 def check_permissions(self):
449 def check_permissions(self):
443 if self.required_perms.issubset(self.user_perms.get('global')):
450 if self.required_perms.issubset(self.user_perms.get('global')):
444 return True
451 return True
445 return False
452 return False
446
453
447
454
448 class HasPermissionAnyDecorator(PermsDecorator):
455 class HasPermissionAnyDecorator(PermsDecorator):
449 """Checks for access permission for any of given predicates. In order to
456 """Checks for access permission for any of given predicates. In order to
450 fulfill the request any of predicates must be meet
457 fulfill the request any of predicates must be meet
451 """
458 """
452
459
453 def check_permissions(self):
460 def check_permissions(self):
454 if self.required_perms.intersection(self.user_perms.get('global')):
461 if self.required_perms.intersection(self.user_perms.get('global')):
455 return True
462 return True
456 return False
463 return False
457
464
458 class HasRepoPermissionAllDecorator(PermsDecorator):
465 class HasRepoPermissionAllDecorator(PermsDecorator):
459 """Checks for access permission for all given predicates for specific
466 """Checks for access permission for all given predicates for specific
460 repository. All of them have to be meet in order to fulfill the request
467 repository. All of them have to be meet in order to fulfill the request
461 """
468 """
462
469
463 def check_permissions(self):
470 def check_permissions(self):
464 repo_name = get_repo_slug(request)
471 repo_name = get_repo_slug(request)
465 try:
472 try:
466 user_perms = set([self.user_perms['repositories'][repo_name]])
473 user_perms = set([self.user_perms['repositories'][repo_name]])
467 except KeyError:
474 except KeyError:
468 return False
475 return False
469 if self.required_perms.issubset(user_perms):
476 if self.required_perms.issubset(user_perms):
470 return True
477 return True
471 return False
478 return False
472
479
473
480
474 class HasRepoPermissionAnyDecorator(PermsDecorator):
481 class HasRepoPermissionAnyDecorator(PermsDecorator):
475 """Checks for access permission for any of given predicates for specific
482 """Checks for access permission for any of given predicates for specific
476 repository. In order to fulfill the request any of predicates must be meet
483 repository. In order to fulfill the request any of predicates must be meet
477 """
484 """
478
485
479 def check_permissions(self):
486 def check_permissions(self):
480 repo_name = get_repo_slug(request)
487 repo_name = get_repo_slug(request)
481
488
482 try:
489 try:
483 user_perms = set([self.user_perms['repositories'][repo_name]])
490 user_perms = set([self.user_perms['repositories'][repo_name]])
484 except KeyError:
491 except KeyError:
485 return False
492 return False
486 if self.required_perms.intersection(user_perms):
493 if self.required_perms.intersection(user_perms):
487 return True
494 return True
488 return False
495 return False
489 #===============================================================================
496 #===============================================================================
490 # CHECK FUNCTIONS
497 # CHECK FUNCTIONS
491 #===============================================================================
498 #===============================================================================
492
499
493 class PermsFunction(object):
500 class PermsFunction(object):
494 """Base function for other check functions"""
501 """Base function for other check functions"""
495
502
496 def __init__(self, *perms):
503 def __init__(self, *perms):
497 available_perms = config['available_permissions']
504 available_perms = config['available_permissions']
498
505
499 for perm in perms:
506 for perm in perms:
500 if perm not in available_perms:
507 if perm not in available_perms:
501 raise Exception("'%s' permission in not defined" % perm)
508 raise Exception("'%s' permission in not defined" % perm)
502 self.required_perms = set(perms)
509 self.required_perms = set(perms)
503 self.user_perms = None
510 self.user_perms = None
504 self.granted_for = ''
511 self.granted_for = ''
505 self.repo_name = None
512 self.repo_name = None
506
513
507 def __call__(self, check_Location=''):
514 def __call__(self, check_Location=''):
508 user = session.get('rhodecode_user', False)
515 user = session.get('rhodecode_user', False)
509 if not user:
516 if not user:
510 return False
517 return False
511 self.user_perms = user.permissions
518 self.user_perms = user.permissions
512 self.granted_for = user.username
519 self.granted_for = user.username
513 log.debug('checking %s %s %s', self.__class__.__name__,
520 log.debug('checking %s %s %s', self.__class__.__name__,
514 self.required_perms, user)
521 self.required_perms, user)
515
522
516 if self.check_permissions():
523 if self.check_permissions():
517 log.debug('Permission granted for %s @ %s %s', self.granted_for,
524 log.debug('Permission granted for %s @ %s %s', self.granted_for,
518 check_Location, user)
525 check_Location, user)
519 return True
526 return True
520
527
521 else:
528 else:
522 log.warning('Permission denied for %s @ %s %s', self.granted_for,
529 log.warning('Permission denied for %s @ %s %s', self.granted_for,
523 check_Location, user)
530 check_Location, user)
524 return False
531 return False
525
532
526 def check_permissions(self):
533 def check_permissions(self):
527 """Dummy function for overriding"""
534 """Dummy function for overriding"""
528 raise Exception('You have to write this function in child class')
535 raise Exception('You have to write this function in child class')
529
536
530 class HasPermissionAll(PermsFunction):
537 class HasPermissionAll(PermsFunction):
531 def check_permissions(self):
538 def check_permissions(self):
532 if self.required_perms.issubset(self.user_perms.get('global')):
539 if self.required_perms.issubset(self.user_perms.get('global')):
533 return True
540 return True
534 return False
541 return False
535
542
536 class HasPermissionAny(PermsFunction):
543 class HasPermissionAny(PermsFunction):
537 def check_permissions(self):
544 def check_permissions(self):
538 if self.required_perms.intersection(self.user_perms.get('global')):
545 if self.required_perms.intersection(self.user_perms.get('global')):
539 return True
546 return True
540 return False
547 return False
541
548
542 class HasRepoPermissionAll(PermsFunction):
549 class HasRepoPermissionAll(PermsFunction):
543
550
544 def __call__(self, repo_name=None, check_Location=''):
551 def __call__(self, repo_name=None, check_Location=''):
545 self.repo_name = repo_name
552 self.repo_name = repo_name
546 return super(HasRepoPermissionAll, self).__call__(check_Location)
553 return super(HasRepoPermissionAll, self).__call__(check_Location)
547
554
548 def check_permissions(self):
555 def check_permissions(self):
549 if not self.repo_name:
556 if not self.repo_name:
550 self.repo_name = get_repo_slug(request)
557 self.repo_name = get_repo_slug(request)
551
558
552 try:
559 try:
553 self.user_perms = set([self.user_perms['repositories']\
560 self.user_perms = set([self.user_perms['repositories']\
554 [self.repo_name]])
561 [self.repo_name]])
555 except KeyError:
562 except KeyError:
556 return False
563 return False
557 self.granted_for = self.repo_name
564 self.granted_for = self.repo_name
558 if self.required_perms.issubset(self.user_perms):
565 if self.required_perms.issubset(self.user_perms):
559 return True
566 return True
560 return False
567 return False
561
568
562 class HasRepoPermissionAny(PermsFunction):
569 class HasRepoPermissionAny(PermsFunction):
563
570
564 def __call__(self, repo_name=None, check_Location=''):
571 def __call__(self, repo_name=None, check_Location=''):
565 self.repo_name = repo_name
572 self.repo_name = repo_name
566 return super(HasRepoPermissionAny, self).__call__(check_Location)
573 return super(HasRepoPermissionAny, self).__call__(check_Location)
567
574
568 def check_permissions(self):
575 def check_permissions(self):
569 if not self.repo_name:
576 if not self.repo_name:
570 self.repo_name = get_repo_slug(request)
577 self.repo_name = get_repo_slug(request)
571
578
572 try:
579 try:
573 self.user_perms = set([self.user_perms['repositories']\
580 self.user_perms = set([self.user_perms['repositories']\
574 [self.repo_name]])
581 [self.repo_name]])
575 except KeyError:
582 except KeyError:
576 return False
583 return False
577 self.granted_for = self.repo_name
584 self.granted_for = self.repo_name
578 if self.required_perms.intersection(self.user_perms):
585 if self.required_perms.intersection(self.user_perms):
579 return True
586 return True
580 return False
587 return False
581
588
582 #===============================================================================
589 #===============================================================================
583 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
590 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
584 #===============================================================================
591 #===============================================================================
585
592
586 class HasPermissionAnyMiddleware(object):
593 class HasPermissionAnyMiddleware(object):
587 def __init__(self, *perms):
594 def __init__(self, *perms):
588 self.required_perms = set(perms)
595 self.required_perms = set(perms)
589
596
590 def __call__(self, user, repo_name):
597 def __call__(self, user, repo_name):
591 usr = AuthUser()
598 usr = AuthUser()
592 usr.user_id = user.user_id
599 usr.user_id = user.user_id
593 usr.username = user.username
600 usr.username = user.username
594 usr.is_admin = user.admin
601 usr.is_admin = user.admin
595
602
596 try:
603 try:
597 self.user_perms = set([fill_perms(usr)\
604 self.user_perms = set([fill_perms(usr)\
598 .permissions['repositories'][repo_name]])
605 .permissions['repositories'][repo_name]])
599 except:
606 except:
600 self.user_perms = set()
607 self.user_perms = set()
601 self.granted_for = ''
608 self.granted_for = ''
602 self.username = user.username
609 self.username = user.username
603 self.repo_name = repo_name
610 self.repo_name = repo_name
604 return self.check_permissions()
611 return self.check_permissions()
605
612
606 def check_permissions(self):
613 def check_permissions(self):
607 log.debug('checking mercurial protocol '
614 log.debug('checking mercurial protocol '
608 'permissions %s for user:%s repository:%s', self.user_perms,
615 'permissions %s for user:%s repository:%s', self.user_perms,
609 self.username, self.repo_name)
616 self.username, self.repo_name)
610 if self.required_perms.intersection(self.user_perms):
617 if self.required_perms.intersection(self.user_perms):
611 log.debug('permission granted')
618 log.debug('permission granted')
612 return True
619 return True
613 log.debug('permission denied')
620 log.debug('permission denied')
614 return False
621 return False
@@ -1,408 +1,409 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.celerylib.tasks
3 rhodecode.lib.celerylib.tasks
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 RhodeCode task modules, containing all task that suppose to be run
6 RhodeCode task modules, containing all task that suppose to be run
7 by celery daemon
7 by celery daemon
8
8
9 :created_on: Oct 6, 2010
9 :created_on: Oct 6, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software; you can redistribute it and/or
14 # This program is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; version 2
16 # as published by the Free Software Foundation; version 2
17 # of the License or (at your opinion) any later version of the license.
17 # of the License or (at your opinion) any later version of the license.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 # MA 02110-1301, USA.
27 # MA 02110-1301, USA.
28 from celery.decorators import task
28 from celery.decorators import task
29
29
30 import os
30 import os
31 import traceback
31 import traceback
32 import logging
32 import logging
33
33
34 from time import mktime
34 from time import mktime
35 from operator import itemgetter
35 from operator import itemgetter
36
36
37 from pylons import config
37 from pylons import config
38 from pylons.i18n.translation import _
38 from pylons.i18n.translation import _
39
39
40 from rhodecode.lib.celerylib import run_task, locked_task, str2bool
40 from rhodecode.lib.celerylib import run_task, locked_task, str2bool
41 from rhodecode.lib.helpers import person
41 from rhodecode.lib.helpers import person
42 from rhodecode.lib.smtp_mailer import SmtpMailer
42 from rhodecode.lib.smtp_mailer import SmtpMailer
43 from rhodecode.lib.utils import OrderedDict, add_cache
43 from rhodecode.lib.utils import OrderedDict, add_cache
44 from rhodecode.model import init_model
44 from rhodecode.model import init_model
45 from rhodecode.model import meta
45 from rhodecode.model import meta
46 from rhodecode.model.db import RhodeCodeUi
46 from rhodecode.model.db import RhodeCodeUi
47
47
48 from vcs.backends import get_repo
48 from vcs.backends import get_repo
49
49
50 from sqlalchemy import engine_from_config
50 from sqlalchemy import engine_from_config
51
51
52 add_cache(config)
52 add_cache(config)
53
53
54 try:
54 try:
55 import json
55 import json
56 except ImportError:
56 except ImportError:
57 #python 2.5 compatibility
57 #python 2.5 compatibility
58 import simplejson as json
58 import simplejson as json
59
59
60 __all__ = ['whoosh_index', 'get_commits_stats',
60 __all__ = ['whoosh_index', 'get_commits_stats',
61 'reset_user_password', 'send_email']
61 'reset_user_password', 'send_email']
62
62
63 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
63 CELERY_ON = str2bool(config['app_conf'].get('use_celery'))
64
64
65 def get_session():
65 def get_session():
66 if CELERY_ON:
66 if CELERY_ON:
67 engine = engine_from_config(config, 'sqlalchemy.db1.')
67 engine = engine_from_config(config, 'sqlalchemy.db1.')
68 init_model(engine)
68 init_model(engine)
69 sa = meta.Session()
69 sa = meta.Session()
70 return sa
70 return sa
71
71
72 def get_repos_path():
72 def get_repos_path():
73 sa = get_session()
73 sa = get_session()
74 q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
74 q = sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
75 return q.ui_value
75 return q.ui_value
76
76
77 @task(ignore_result=True)
77 @task(ignore_result=True)
78 @locked_task
78 @locked_task
79 def whoosh_index(repo_location, full_index):
79 def whoosh_index(repo_location, full_index):
80 #log = whoosh_index.get_logger()
80 #log = whoosh_index.get_logger()
81 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
81 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
82 index_location = config['index_dir']
82 index_location = config['index_dir']
83 WhooshIndexingDaemon(index_location=index_location,
83 WhooshIndexingDaemon(index_location=index_location,
84 repo_location=repo_location, sa=get_session())\
84 repo_location=repo_location, sa=get_session())\
85 .run(full_index=full_index)
85 .run(full_index=full_index)
86
86
87 @task(ignore_result=True)
87 @task(ignore_result=True)
88 @locked_task
88 @locked_task
89 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
89 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
90 try:
90 try:
91 log = get_commits_stats.get_logger()
91 log = get_commits_stats.get_logger()
92 except:
92 except:
93 log = logging.getLogger(__name__)
93 log = logging.getLogger(__name__)
94
94
95 from rhodecode.model.db import Statistics, Repository
95 from rhodecode.model.db import Statistics, Repository
96
96
97 #for js data compatibilty
97 #for js data compatibilty
98 author_key_cleaner = lambda k: person(k).replace('"', "")
98 author_key_cleaner = lambda k: person(k).replace('"', "")
99
99
100 commits_by_day_author_aggregate = {}
100 commits_by_day_author_aggregate = {}
101 commits_by_day_aggregate = {}
101 commits_by_day_aggregate = {}
102 repos_path = get_repos_path()
102 repos_path = get_repos_path()
103 p = os.path.join(repos_path, repo_name)
103 p = os.path.join(repos_path, repo_name)
104 repo = get_repo(p)
104 repo = get_repo(p)
105
105
106 skip_date_limit = True
106 skip_date_limit = True
107 parse_limit = int(config['app_conf'].get('commit_parse_limit'))
107 parse_limit = int(config['app_conf'].get('commit_parse_limit'))
108 last_rev = 0
108 last_rev = 0
109 last_cs = None
109 last_cs = None
110 timegetter = itemgetter('time')
110 timegetter = itemgetter('time')
111
111
112 sa = get_session()
112 sa = get_session()
113
113
114 dbrepo = sa.query(Repository)\
114 dbrepo = sa.query(Repository)\
115 .filter(Repository.repo_name == repo_name).scalar()
115 .filter(Repository.repo_name == repo_name).scalar()
116 cur_stats = sa.query(Statistics)\
116 cur_stats = sa.query(Statistics)\
117 .filter(Statistics.repository == dbrepo).scalar()
117 .filter(Statistics.repository == dbrepo).scalar()
118
118
119 if cur_stats is not None:
119 if cur_stats is not None:
120 last_rev = cur_stats.stat_on_revision
120 last_rev = cur_stats.stat_on_revision
121
121
122 #return if repo is empty
122 #return if repo is empty
123 if not repo.revisions:
123 if not repo.revisions:
124 return True
124 return True
125
125
126 if last_rev == repo.get_changeset().revision and len(repo.revisions) > 1:
126 if last_rev == repo.get_changeset().revision and len(repo.revisions) > 1:
127 #pass silently without any work if we're not on first revision or
127 #pass silently without any work if we're not on first revision or
128 #current state of parsing revision(from db marker) is the last revision
128 #current state of parsing revision(from db marker) is the last revision
129 return True
129 return True
130
130
131 if cur_stats:
131 if cur_stats:
132 commits_by_day_aggregate = OrderedDict(
132 commits_by_day_aggregate = OrderedDict(
133 json.loads(
133 json.loads(
134 cur_stats.commit_activity_combined))
134 cur_stats.commit_activity_combined))
135 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
135 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
136
136
137 log.debug('starting parsing %s', parse_limit)
137 log.debug('starting parsing %s', parse_limit)
138 lmktime = mktime
138 lmktime = mktime
139
139
140 last_rev = last_rev + 1 if last_rev > 0 else last_rev
140 last_rev = last_rev + 1 if last_rev > 0 else last_rev
141
141
142 for cs in repo[last_rev:last_rev + parse_limit]:
142 for cs in repo[last_rev:last_rev + parse_limit]:
143 last_cs = cs #remember last parsed changeset
143 last_cs = cs #remember last parsed changeset
144 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
144 k = lmktime([cs.date.timetuple()[0], cs.date.timetuple()[1],
145 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
145 cs.date.timetuple()[2], 0, 0, 0, 0, 0, 0])
146
146
147 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
147 if commits_by_day_author_aggregate.has_key(author_key_cleaner(cs.author)):
148 try:
148 try:
149 l = [timegetter(x) for x in commits_by_day_author_aggregate\
149 l = [timegetter(x) for x in commits_by_day_author_aggregate\
150 [author_key_cleaner(cs.author)]['data']]
150 [author_key_cleaner(cs.author)]['data']]
151 time_pos = l.index(k)
151 time_pos = l.index(k)
152 except ValueError:
152 except ValueError:
153 time_pos = False
153 time_pos = False
154
154
155 if time_pos >= 0 and time_pos is not False:
155 if time_pos >= 0 and time_pos is not False:
156
156
157 datadict = commits_by_day_author_aggregate\
157 datadict = commits_by_day_author_aggregate\
158 [author_key_cleaner(cs.author)]['data'][time_pos]
158 [author_key_cleaner(cs.author)]['data'][time_pos]
159
159
160 datadict["commits"] += 1
160 datadict["commits"] += 1
161 datadict["added"] += len(cs.added)
161 datadict["added"] += len(cs.added)
162 datadict["changed"] += len(cs.changed)
162 datadict["changed"] += len(cs.changed)
163 datadict["removed"] += len(cs.removed)
163 datadict["removed"] += len(cs.removed)
164
164
165 else:
165 else:
166 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
166 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
167
167
168 datadict = {"time":k,
168 datadict = {"time":k,
169 "commits":1,
169 "commits":1,
170 "added":len(cs.added),
170 "added":len(cs.added),
171 "changed":len(cs.changed),
171 "changed":len(cs.changed),
172 "removed":len(cs.removed),
172 "removed":len(cs.removed),
173 }
173 }
174 commits_by_day_author_aggregate\
174 commits_by_day_author_aggregate\
175 [author_key_cleaner(cs.author)]['data'].append(datadict)
175 [author_key_cleaner(cs.author)]['data'].append(datadict)
176
176
177 else:
177 else:
178 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
178 if k >= ts_min_y and k <= ts_max_y or skip_date_limit:
179 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
179 commits_by_day_author_aggregate[author_key_cleaner(cs.author)] = {
180 "label":author_key_cleaner(cs.author),
180 "label":author_key_cleaner(cs.author),
181 "data":[{"time":k,
181 "data":[{"time":k,
182 "commits":1,
182 "commits":1,
183 "added":len(cs.added),
183 "added":len(cs.added),
184 "changed":len(cs.changed),
184 "changed":len(cs.changed),
185 "removed":len(cs.removed),
185 "removed":len(cs.removed),
186 }],
186 }],
187 "schema":["commits"],
187 "schema":["commits"],
188 }
188 }
189
189
190 #gather all data by day
190 #gather all data by day
191 if commits_by_day_aggregate.has_key(k):
191 if commits_by_day_aggregate.has_key(k):
192 commits_by_day_aggregate[k] += 1
192 commits_by_day_aggregate[k] += 1
193 else:
193 else:
194 commits_by_day_aggregate[k] = 1
194 commits_by_day_aggregate[k] = 1
195
195
196 overview_data = sorted(commits_by_day_aggregate.items(), key=itemgetter(0))
196 overview_data = sorted(commits_by_day_aggregate.items(), key=itemgetter(0))
197 if not commits_by_day_author_aggregate:
197 if not commits_by_day_author_aggregate:
198 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
198 commits_by_day_author_aggregate[author_key_cleaner(repo.contact)] = {
199 "label":author_key_cleaner(repo.contact),
199 "label":author_key_cleaner(repo.contact),
200 "data":[0, 1],
200 "data":[0, 1],
201 "schema":["commits"],
201 "schema":["commits"],
202 }
202 }
203
203
204 stats = cur_stats if cur_stats else Statistics()
204 stats = cur_stats if cur_stats else Statistics()
205 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
205 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
206 stats.commit_activity_combined = json.dumps(overview_data)
206 stats.commit_activity_combined = json.dumps(overview_data)
207
207
208 log.debug('last revison %s', last_rev)
208 log.debug('last revison %s', last_rev)
209 leftovers = len(repo.revisions[last_rev:])
209 leftovers = len(repo.revisions[last_rev:])
210 log.debug('revisions to parse %s', leftovers)
210 log.debug('revisions to parse %s', leftovers)
211
211
212 if last_rev == 0 or leftovers < parse_limit:
212 if last_rev == 0 or leftovers < parse_limit:
213 log.debug('getting code trending stats')
213 log.debug('getting code trending stats')
214 stats.languages = json.dumps(__get_codes_stats(repo_name))
214 stats.languages = json.dumps(__get_codes_stats(repo_name))
215
215
216 try:
216 try:
217 stats.repository = dbrepo
217 stats.repository = dbrepo
218 stats.stat_on_revision = last_cs.revision if last_cs else 0
218 stats.stat_on_revision = last_cs.revision if last_cs else 0
219 sa.add(stats)
219 sa.add(stats)
220 sa.commit()
220 sa.commit()
221 except:
221 except:
222 log.error(traceback.format_exc())
222 log.error(traceback.format_exc())
223 sa.rollback()
223 sa.rollback()
224 return False
224 return False
225 if len(repo.revisions) > 1:
225 if len(repo.revisions) > 1:
226 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
226 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
227
227
228 return True
228 return True
229
229
230 @task(ignore_result=True)
230 @task(ignore_result=True)
231 def reset_user_password(user_email):
231 def reset_user_password(user_email):
232 try:
232 try:
233 log = reset_user_password.get_logger()
233 log = reset_user_password.get_logger()
234 except:
234 except:
235 log = logging.getLogger(__name__)
235 log = logging.getLogger(__name__)
236
236
237 from rhodecode.lib import auth
237 from rhodecode.lib import auth
238 from rhodecode.model.db import User
238 from rhodecode.model.db import User
239
239
240 try:
240 try:
241 try:
241 try:
242 sa = get_session()
242 sa = get_session()
243 user = sa.query(User).filter(User.email == user_email).scalar()
243 user = sa.query(User).filter(User.email == user_email).scalar()
244 new_passwd = auth.PasswordGenerator().gen_password(8,
244 new_passwd = auth.PasswordGenerator().gen_password(8,
245 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
245 auth.PasswordGenerator.ALPHABETS_BIG_SMALL)
246 if user:
246 if user:
247 user.password = auth.get_crypt_password(new_passwd)
247 user.password = auth.get_crypt_password(new_passwd)
248 user.api_key = auth.generate_api_key(user.username)
248 sa.add(user)
249 sa.add(user)
249 sa.commit()
250 sa.commit()
250 log.info('change password for %s', user_email)
251 log.info('change password for %s', user_email)
251 if new_passwd is None:
252 if new_passwd is None:
252 raise Exception('unable to generate new password')
253 raise Exception('unable to generate new password')
253
254
254 except:
255 except:
255 log.error(traceback.format_exc())
256 log.error(traceback.format_exc())
256 sa.rollback()
257 sa.rollback()
257
258
258 run_task(send_email, user_email,
259 run_task(send_email, user_email,
259 "Your new rhodecode password",
260 "Your new rhodecode password",
260 'Your new rhodecode password:%s' % (new_passwd))
261 'Your new rhodecode password:%s' % (new_passwd))
261 log.info('send new password mail to %s', user_email)
262 log.info('send new password mail to %s', user_email)
262
263
263
264
264 except:
265 except:
265 log.error('Failed to update user password')
266 log.error('Failed to update user password')
266 log.error(traceback.format_exc())
267 log.error(traceback.format_exc())
267
268
268 return True
269 return True
269
270
270 @task(ignore_result=True)
271 @task(ignore_result=True)
271 def send_email(recipients, subject, body):
272 def send_email(recipients, subject, body):
272 """
273 """
273 Sends an email with defined parameters from the .ini files.
274 Sends an email with defined parameters from the .ini files.
274
275
275
276
276 :param recipients: list of recipients, it this is empty the defined email
277 :param recipients: list of recipients, it this is empty the defined email
277 address from field 'email_to' is used instead
278 address from field 'email_to' is used instead
278 :param subject: subject of the mail
279 :param subject: subject of the mail
279 :param body: body of the mail
280 :param body: body of the mail
280 """
281 """
281 try:
282 try:
282 log = send_email.get_logger()
283 log = send_email.get_logger()
283 except:
284 except:
284 log = logging.getLogger(__name__)
285 log = logging.getLogger(__name__)
285
286
286 email_config = config
287 email_config = config
287
288
288 if not recipients:
289 if not recipients:
289 recipients = [email_config.get('email_to')]
290 recipients = [email_config.get('email_to')]
290
291
291 mail_from = email_config.get('app_email_from')
292 mail_from = email_config.get('app_email_from')
292 user = email_config.get('smtp_username')
293 user = email_config.get('smtp_username')
293 passwd = email_config.get('smtp_password')
294 passwd = email_config.get('smtp_password')
294 mail_server = email_config.get('smtp_server')
295 mail_server = email_config.get('smtp_server')
295 mail_port = email_config.get('smtp_port')
296 mail_port = email_config.get('smtp_port')
296 tls = str2bool(email_config.get('smtp_use_tls'))
297 tls = str2bool(email_config.get('smtp_use_tls'))
297 ssl = str2bool(email_config.get('smtp_use_ssl'))
298 ssl = str2bool(email_config.get('smtp_use_ssl'))
298
299
299 try:
300 try:
300 m = SmtpMailer(mail_from, user, passwd, mail_server,
301 m = SmtpMailer(mail_from, user, passwd, mail_server,
301 mail_port, ssl, tls)
302 mail_port, ssl, tls)
302 m.send(recipients, subject, body)
303 m.send(recipients, subject, body)
303 except:
304 except:
304 log.error('Mail sending failed')
305 log.error('Mail sending failed')
305 log.error(traceback.format_exc())
306 log.error(traceback.format_exc())
306 return False
307 return False
307 return True
308 return True
308
309
309 @task(ignore_result=True)
310 @task(ignore_result=True)
310 def create_repo_fork(form_data, cur_user):
311 def create_repo_fork(form_data, cur_user):
311 try:
312 try:
312 log = create_repo_fork.get_logger()
313 log = create_repo_fork.get_logger()
313 except:
314 except:
314 log = logging.getLogger(__name__)
315 log = logging.getLogger(__name__)
315
316
316 from rhodecode.model.repo import RepoModel
317 from rhodecode.model.repo import RepoModel
317 from vcs import get_backend
318 from vcs import get_backend
318
319
319 repo_model = RepoModel(get_session())
320 repo_model = RepoModel(get_session())
320 repo_model.create(form_data, cur_user, just_db=True, fork=True)
321 repo_model.create(form_data, cur_user, just_db=True, fork=True)
321 repo_name = form_data['repo_name']
322 repo_name = form_data['repo_name']
322 repos_path = get_repos_path()
323 repos_path = get_repos_path()
323 repo_path = os.path.join(repos_path, repo_name)
324 repo_path = os.path.join(repos_path, repo_name)
324 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
325 repo_fork_path = os.path.join(repos_path, form_data['fork_name'])
325 alias = form_data['repo_type']
326 alias = form_data['repo_type']
326
327
327 log.info('creating repo fork %s as %s', repo_name, repo_path)
328 log.info('creating repo fork %s as %s', repo_name, repo_path)
328 backend = get_backend(alias)
329 backend = get_backend(alias)
329 backend(str(repo_fork_path), create=True, src_url=str(repo_path))
330 backend(str(repo_fork_path), create=True, src_url=str(repo_path))
330
331
331 def __get_codes_stats(repo_name):
332 def __get_codes_stats(repo_name):
332 LANGUAGES_EXTENSIONS_MAP = {'scm': 'Scheme', 'asmx': 'VbNetAspx', 'Rout':
333 LANGUAGES_EXTENSIONS_MAP = {'scm': 'Scheme', 'asmx': 'VbNetAspx', 'Rout':
333 'RConsole', 'rest': 'Rst', 'abap': 'ABAP', 'go': 'Go', 'phtml': 'HtmlPhp',
334 'RConsole', 'rest': 'Rst', 'abap': 'ABAP', 'go': 'Go', 'phtml': 'HtmlPhp',
334 'ns2': 'Newspeak', 'xml': 'EvoqueXml', 'sh-session': 'BashSession', 'ads':
335 'ns2': 'Newspeak', 'xml': 'EvoqueXml', 'sh-session': 'BashSession', 'ads':
335 'Ada', 'clj': 'Clojure', 'll': 'Llvm', 'ebuild': 'Bash', 'adb': 'Ada',
336 'Ada', 'clj': 'Clojure', 'll': 'Llvm', 'ebuild': 'Bash', 'adb': 'Ada',
336 'ada': 'Ada', 'c++-objdump': 'CppObjdump', 'aspx':
337 'ada': 'Ada', 'c++-objdump': 'CppObjdump', 'aspx':
337 'VbNetAspx', 'ksh': 'Bash', 'coffee': 'CoffeeScript', 'vert': 'GLShader',
338 'VbNetAspx', 'ksh': 'Bash', 'coffee': 'CoffeeScript', 'vert': 'GLShader',
338 'Makefile.*': 'Makefile', 'di': 'D', 'dpatch': 'DarcsPatch', 'rake':
339 'Makefile.*': 'Makefile', 'di': 'D', 'dpatch': 'DarcsPatch', 'rake':
339 'Ruby', 'moo': 'MOOCode', 'erl-sh': 'ErlangShell', 'geo': 'GLShader',
340 'Ruby', 'moo': 'MOOCode', 'erl-sh': 'ErlangShell', 'geo': 'GLShader',
340 'pov': 'Povray', 'bas': 'VbNet', 'bat': 'Batch', 'd': 'D', 'lisp':
341 'pov': 'Povray', 'bas': 'VbNet', 'bat': 'Batch', 'd': 'D', 'lisp':
341 'CommonLisp', 'h': 'C', 'rbx': 'Ruby', 'tcl': 'Tcl', 'c++': 'Cpp', 'md':
342 'CommonLisp', 'h': 'C', 'rbx': 'Ruby', 'tcl': 'Tcl', 'c++': 'Cpp', 'md':
342 'MiniD', '.vimrc': 'Vim', 'xsd': 'Xml', 'ml': 'Ocaml', 'el': 'CommonLisp',
343 'MiniD', '.vimrc': 'Vim', 'xsd': 'Xml', 'ml': 'Ocaml', 'el': 'CommonLisp',
343 'befunge': 'Befunge', 'xsl': 'Xslt', 'pyx': 'Cython', 'cfm':
344 'befunge': 'Befunge', 'xsl': 'Xslt', 'pyx': 'Cython', 'cfm':
344 'ColdfusionHtml', 'evoque': 'Evoque', 'cfg': 'Ini', 'htm': 'Html',
345 'ColdfusionHtml', 'evoque': 'Evoque', 'cfg': 'Ini', 'htm': 'Html',
345 'Makefile': 'Makefile', 'cfc': 'ColdfusionHtml', 'tex': 'Tex', 'cs':
346 'Makefile': 'Makefile', 'cfc': 'ColdfusionHtml', 'tex': 'Tex', 'cs':
346 'CSharp', 'mxml': 'Mxml', 'patch': 'Diff', 'apache.conf': 'ApacheConf',
347 'CSharp', 'mxml': 'Mxml', 'patch': 'Diff', 'apache.conf': 'ApacheConf',
347 'scala': 'Scala', 'applescript': 'AppleScript', 'GNUmakefile': 'Makefile',
348 'scala': 'Scala', 'applescript': 'AppleScript', 'GNUmakefile': 'Makefile',
348 'c-objdump': 'CObjdump', 'lua': 'Lua', 'apache2.conf': 'ApacheConf', 'rb':
349 'c-objdump': 'CObjdump', 'lua': 'Lua', 'apache2.conf': 'ApacheConf', 'rb':
349 'Ruby', 'gemspec': 'Ruby', 'rl': 'RagelObjectiveC', 'vala': 'Vala', 'tmpl':
350 'Ruby', 'gemspec': 'Ruby', 'rl': 'RagelObjectiveC', 'vala': 'Vala', 'tmpl':
350 'Cheetah', 'bf': 'Brainfuck', 'plt': 'Gnuplot', 'G': 'AntlrRuby', 'xslt':
351 'Cheetah', 'bf': 'Brainfuck', 'plt': 'Gnuplot', 'G': 'AntlrRuby', 'xslt':
351 'Xslt', 'flxh': 'Felix', 'asax': 'VbNetAspx', 'Rakefile': 'Ruby', 'S': 'S',
352 'Xslt', 'flxh': 'Felix', 'asax': 'VbNetAspx', 'Rakefile': 'Ruby', 'S': 'S',
352 'wsdl': 'Xml', 'js': 'Javascript', 'autodelegate': 'Myghty', 'properties':
353 'wsdl': 'Xml', 'js': 'Javascript', 'autodelegate': 'Myghty', 'properties':
353 'Ini', 'bash': 'Bash', 'c': 'C', 'g': 'AntlrRuby', 'r3': 'Rebol', 's':
354 'Ini', 'bash': 'Bash', 'c': 'C', 'g': 'AntlrRuby', 'r3': 'Rebol', 's':
354 'Gas', 'ashx': 'VbNetAspx', 'cxx': 'Cpp', 'boo': 'Boo', 'prolog': 'Prolog',
355 'Gas', 'ashx': 'VbNetAspx', 'cxx': 'Cpp', 'boo': 'Boo', 'prolog': 'Prolog',
355 'sqlite3-console': 'SqliteConsole', 'cl': 'CommonLisp', 'cc': 'Cpp', 'pot':
356 'sqlite3-console': 'SqliteConsole', 'cl': 'CommonLisp', 'cc': 'Cpp', 'pot':
356 'Gettext', 'vim': 'Vim', 'pxi': 'Cython', 'yaml': 'Yaml', 'SConstruct':
357 'Gettext', 'vim': 'Vim', 'pxi': 'Cython', 'yaml': 'Yaml', 'SConstruct':
357 'Python', 'diff': 'Diff', 'txt': 'Text', 'cw': 'Redcode', 'pxd': 'Cython',
358 'Python', 'diff': 'Diff', 'txt': 'Text', 'cw': 'Redcode', 'pxd': 'Cython',
358 'plot': 'Gnuplot', 'java': 'Java', 'hrl': 'Erlang', 'py': 'Python',
359 'plot': 'Gnuplot', 'java': 'Java', 'hrl': 'Erlang', 'py': 'Python',
359 'makefile': 'Makefile', 'squid.conf': 'SquidConf', 'asm': 'Nasm', 'toc':
360 'makefile': 'Makefile', 'squid.conf': 'SquidConf', 'asm': 'Nasm', 'toc':
360 'Tex', 'kid': 'Genshi', 'rhtml': 'Rhtml', 'po': 'Gettext', 'pl': 'Prolog',
361 'Tex', 'kid': 'Genshi', 'rhtml': 'Rhtml', 'po': 'Gettext', 'pl': 'Prolog',
361 'pm': 'Perl', 'hx': 'Haxe', 'ascx': 'VbNetAspx', 'ooc': 'Ooc', 'asy':
362 'pm': 'Perl', 'hx': 'Haxe', 'ascx': 'VbNetAspx', 'ooc': 'Ooc', 'asy':
362 'Asymptote', 'hs': 'Haskell', 'SConscript': 'Python', 'pytb':
363 'Asymptote', 'hs': 'Haskell', 'SConscript': 'Python', 'pytb':
363 'PythonTraceback', 'myt': 'Myghty', 'hh': 'Cpp', 'R': 'S', 'aux': 'Tex',
364 'PythonTraceback', 'myt': 'Myghty', 'hh': 'Cpp', 'R': 'S', 'aux': 'Tex',
364 'rst': 'Rst', 'cpp-objdump': 'CppObjdump', 'lgt': 'Logtalk', 'rss': 'Xml',
365 'rst': 'Rst', 'cpp-objdump': 'CppObjdump', 'lgt': 'Logtalk', 'rss': 'Xml',
365 'flx': 'Felix', 'b': 'Brainfuck', 'f': 'Fortran', 'rbw': 'Ruby',
366 'flx': 'Felix', 'b': 'Brainfuck', 'f': 'Fortran', 'rbw': 'Ruby',
366 '.htaccess': 'ApacheConf', 'cxx-objdump': 'CppObjdump', 'j': 'ObjectiveJ',
367 '.htaccess': 'ApacheConf', 'cxx-objdump': 'CppObjdump', 'j': 'ObjectiveJ',
367 'mll': 'Ocaml', 'yml': 'Yaml', 'mu': 'MuPAD', 'r': 'Rebol', 'ASM': 'Nasm',
368 'mll': 'Ocaml', 'yml': 'Yaml', 'mu': 'MuPAD', 'r': 'Rebol', 'ASM': 'Nasm',
368 'erl': 'Erlang', 'mly': 'Ocaml', 'mo': 'Modelica', 'def': 'Modula2', 'ini':
369 'erl': 'Erlang', 'mly': 'Ocaml', 'mo': 'Modelica', 'def': 'Modula2', 'ini':
369 'Ini', 'control': 'DebianControl', 'vb': 'VbNet', 'vapi': 'Vala', 'pro':
370 'Ini', 'control': 'DebianControl', 'vb': 'VbNet', 'vapi': 'Vala', 'pro':
370 'Prolog', 'spt': 'Cheetah', 'mli': 'Ocaml', 'as': 'ActionScript3', 'cmd':
371 'Prolog', 'spt': 'Cheetah', 'mli': 'Ocaml', 'as': 'ActionScript3', 'cmd':
371 'Batch', 'cpp': 'Cpp', 'io': 'Io', 'tac': 'Python', 'haml': 'Haml', 'rkt':
372 'Batch', 'cpp': 'Cpp', 'io': 'Io', 'tac': 'Python', 'haml': 'Haml', 'rkt':
372 'Racket', 'st':'Smalltalk', 'inc': 'Povray', 'pas': 'Delphi', 'cmake':
373 'Racket', 'st':'Smalltalk', 'inc': 'Povray', 'pas': 'Delphi', 'cmake':
373 'CMake', 'csh':'Tcsh', 'hpp': 'Cpp', 'feature': 'Gherkin', 'html': 'Html',
374 'CMake', 'csh':'Tcsh', 'hpp': 'Cpp', 'feature': 'Gherkin', 'html': 'Html',
374 'php':'Php', 'php3':'Php', 'php4':'Php', 'php5':'Php', 'xhtml': 'Html',
375 'php':'Php', 'php3':'Php', 'php4':'Php', 'php5':'Php', 'xhtml': 'Html',
375 'hxx': 'Cpp', 'eclass': 'Bash', 'css': 'Css',
376 'hxx': 'Cpp', 'eclass': 'Bash', 'css': 'Css',
376 'frag': 'GLShader', 'd-objdump': 'DObjdump', 'weechatlog': 'IrcLogs',
377 'frag': 'GLShader', 'd-objdump': 'DObjdump', 'weechatlog': 'IrcLogs',
377 'tcsh': 'Tcsh', 'objdump': 'Objdump', 'pyw': 'Python', 'h++': 'Cpp',
378 'tcsh': 'Tcsh', 'objdump': 'Objdump', 'pyw': 'Python', 'h++': 'Cpp',
378 'py3tb': 'Python3Traceback', 'jsp': 'Jsp', 'sql': 'Sql', 'mak': 'Makefile',
379 'py3tb': 'Python3Traceback', 'jsp': 'Jsp', 'sql': 'Sql', 'mak': 'Makefile',
379 'php': 'Php', 'mao': 'Mako', 'man': 'Groff', 'dylan': 'Dylan', 'sass':
380 'php': 'Php', 'mao': 'Mako', 'man': 'Groff', 'dylan': 'Dylan', 'sass':
380 'Sass', 'cfml': 'ColdfusionHtml', 'darcspatch': 'DarcsPatch', 'tpl':
381 'Sass', 'cfml': 'ColdfusionHtml', 'darcspatch': 'DarcsPatch', 'tpl':
381 'Smarty', 'm': 'ObjectiveC', 'f90': 'Fortran', 'mod': 'Modula2', 'sh':
382 'Smarty', 'm': 'ObjectiveC', 'f90': 'Fortran', 'mod': 'Modula2', 'sh':
382 'Bash', 'lhs': 'LiterateHaskell', 'sources.list': 'SourcesList', 'axd':
383 'Bash', 'lhs': 'LiterateHaskell', 'sources.list': 'SourcesList', 'axd':
383 'VbNetAspx', 'sc': 'Python'}
384 'VbNetAspx', 'sc': 'Python'}
384
385
385 repos_path = get_repos_path()
386 repos_path = get_repos_path()
386 p = os.path.join(repos_path, repo_name)
387 p = os.path.join(repos_path, repo_name)
387 repo = get_repo(p)
388 repo = get_repo(p)
388 tip = repo.get_changeset()
389 tip = repo.get_changeset()
389 code_stats = {}
390 code_stats = {}
390
391
391 def aggregate(cs):
392 def aggregate(cs):
392 for f in cs[2]:
393 for f in cs[2]:
393 ext = f.extension
394 ext = f.extension
394 key = LANGUAGES_EXTENSIONS_MAP.get(ext, ext)
395 key = LANGUAGES_EXTENSIONS_MAP.get(ext, ext)
395 key = key or ext
396 key = key or ext
396 if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
397 if ext in LANGUAGES_EXTENSIONS_MAP.keys() and not f.is_binary:
397 if code_stats.has_key(key):
398 if code_stats.has_key(key):
398 code_stats[key] += 1
399 code_stats[key] += 1
399 else:
400 else:
400 code_stats[key] = 1
401 code_stats[key] = 1
401
402
402 map(aggregate, tip.walk('/'))
403 map(aggregate, tip.walk('/'))
403
404
404 return code_stats or {}
405 return code_stats or {}
405
406
406
407
407
408
408
409
@@ -1,534 +1,536 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.db_manage
3 rhodecode.lib.db_manage
4 ~~~~~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~
5
5
6 Database creation, and setup module for RhodeCode. Used for creation
6 Database creation, and setup module for RhodeCode. Used for creation
7 of database as well as for migration operations
7 of database as well as for migration operations
8
8
9 :created_on: Apr 10, 2010
9 :created_on: Apr 10, 2010
10 :author: marcink
10 :author: marcink
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
12 :license: GPLv3, see COPYING for more details.
12 :license: GPLv3, see COPYING for more details.
13 """
13 """
14 # This program is free software; you can redistribute it and/or
14 # This program is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License
15 # modify it under the terms of the GNU General Public License
16 # as published by the Free Software Foundation; version 2
16 # as published by the Free Software Foundation; version 2
17 # of the License or (at your opinion) any later version of the license.
17 # of the License or (at your opinion) any later version of the license.
18 #
18 #
19 # This program is distributed in the hope that it will be useful,
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 # GNU General Public License for more details.
22 # GNU General Public License for more details.
23 #
23 #
24 # You should have received a copy of the GNU General Public License
24 # You should have received a copy of the GNU General Public License
25 # along with this program; if not, write to the Free Software
25 # along with this program; if not, write to the Free Software
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 # MA 02110-1301, USA.
27 # MA 02110-1301, USA.
28
28
29 import os
29 import os
30 import sys
30 import sys
31 import uuid
31 import uuid
32 import logging
32 import logging
33 from os.path import dirname as dn, join as jn
33 from os.path import dirname as dn, join as jn
34
34
35 from rhodecode import __dbversion__
35 from rhodecode import __dbversion__
36 from rhodecode.model import meta
36 from rhodecode.model import meta
37
37
38 from rhodecode.lib.auth import get_crypt_password
38 from rhodecode.lib.auth import get_crypt_password, generate_api_key
39 from rhodecode.lib.utils import ask_ok
39 from rhodecode.lib.utils import ask_ok
40 from rhodecode.model import init_model
40 from rhodecode.model import init_model
41 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
41 from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \
42 UserToPerm, DbMigrateVersion
42 UserToPerm, DbMigrateVersion
43
43
44 from sqlalchemy.engine import create_engine
44 from sqlalchemy.engine import create_engine
45
45
46 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
47
47
48 class DbManage(object):
48 class DbManage(object):
49 def __init__(self, log_sql, dbconf, root, tests=False):
49 def __init__(self, log_sql, dbconf, root, tests=False):
50 self.dbname = dbconf.split('/')[-1]
50 self.dbname = dbconf.split('/')[-1]
51 self.tests = tests
51 self.tests = tests
52 self.root = root
52 self.root = root
53 self.dburi = dbconf
53 self.dburi = dbconf
54 self.log_sql = log_sql
54 self.log_sql = log_sql
55 self.db_exists = False
55 self.db_exists = False
56 self.init_db()
56 self.init_db()
57
57
58 def init_db(self):
58 def init_db(self):
59 engine = create_engine(self.dburi, echo=self.log_sql)
59 engine = create_engine(self.dburi, echo=self.log_sql)
60 init_model(engine)
60 init_model(engine)
61 self.sa = meta.Session()
61 self.sa = meta.Session()
62
62
63 def check_for_db(self, override):
63 def check_for_db(self, override):
64 db_path = jn(self.root, self.dbname)
64 db_path = jn(self.root, self.dbname)
65 if self.dburi.startswith('sqlite'):
65 if self.dburi.startswith('sqlite'):
66 log.info('checking for existing db in %s', db_path)
66 log.info('checking for existing db in %s', db_path)
67 if os.path.isfile(db_path):
67 if os.path.isfile(db_path):
68
68
69 self.db_exists = True
69 self.db_exists = True
70 if not override:
70 if not override:
71 raise Exception('database already exists')
71 raise Exception('database already exists')
72 return 'sqlite'
72 return 'sqlite'
73 if self.dburi.startswith('postgresql'):
73 if self.dburi.startswith('postgresql'):
74 self.db_exists = True
74 self.db_exists = True
75 return 'postgresql'
75 return 'postgresql'
76
76
77
77
78 def create_tables(self, override=False):
78 def create_tables(self, override=False):
79 """Create a auth database
79 """Create a auth database
80 """
80 """
81
81
82 db_type = self.check_for_db(override)
82 db_type = self.check_for_db(override)
83 if self.db_exists:
83 if self.db_exists:
84 log.info("database exist and it's going to be destroyed")
84 log.info("database exist and it's going to be destroyed")
85 if self.tests:
85 if self.tests:
86 destroy = True
86 destroy = True
87 else:
87 else:
88 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
88 destroy = ask_ok('Are you sure to destroy old database ? [y/n]')
89 if not destroy:
89 if not destroy:
90 sys.exit()
90 sys.exit()
91 if self.db_exists and destroy:
91 if self.db_exists and destroy:
92 if db_type == 'sqlite':
92 if db_type == 'sqlite':
93 os.remove(jn(self.root, self.dbname))
93 os.remove(jn(self.root, self.dbname))
94 if db_type == 'postgresql':
94 if db_type == 'postgresql':
95 meta.Base.metadata.drop_all()
95 meta.Base.metadata.drop_all()
96
96
97 checkfirst = not override
97 checkfirst = not override
98 meta.Base.metadata.create_all(checkfirst=checkfirst)
98 meta.Base.metadata.create_all(checkfirst=checkfirst)
99 log.info('Created tables for %s', self.dbname)
99 log.info('Created tables for %s', self.dbname)
100
100
101
101
102
102
103 def set_db_version(self):
103 def set_db_version(self):
104 try:
104 try:
105 ver = DbMigrateVersion()
105 ver = DbMigrateVersion()
106 ver.version = __dbversion__
106 ver.version = __dbversion__
107 ver.repository_id = 'rhodecode_db_migrations'
107 ver.repository_id = 'rhodecode_db_migrations'
108 ver.repository_path = 'versions'
108 ver.repository_path = 'versions'
109 self.sa.add(ver)
109 self.sa.add(ver)
110 self.sa.commit()
110 self.sa.commit()
111 except:
111 except:
112 self.sa.rollback()
112 self.sa.rollback()
113 raise
113 raise
114 log.info('db version set to: %s', __dbversion__)
114 log.info('db version set to: %s', __dbversion__)
115
115
116
116
117 def upgrade(self):
117 def upgrade(self):
118 """Upgrades given database schema to given revision following
118 """Upgrades given database schema to given revision following
119 all needed steps, to perform the upgrade
119 all needed steps, to perform the upgrade
120
120
121 """
121 """
122
122
123 from rhodecode.lib.dbmigrate.migrate.versioning import api
123 from rhodecode.lib.dbmigrate.migrate.versioning import api
124 from rhodecode.lib.dbmigrate.migrate.exceptions import \
124 from rhodecode.lib.dbmigrate.migrate.exceptions import \
125 DatabaseNotControlledError
125 DatabaseNotControlledError
126
126
127 upgrade = ask_ok('You are about to perform database upgrade, make '
127 upgrade = ask_ok('You are about to perform database upgrade, make '
128 'sure You backed up your database before. '
128 'sure You backed up your database before. '
129 'Continue ? [y/n]')
129 'Continue ? [y/n]')
130 if not upgrade:
130 if not upgrade:
131 sys.exit('Nothing done')
131 sys.exit('Nothing done')
132
132
133 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
133 repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))),
134 'rhodecode/lib/dbmigrate')
134 'rhodecode/lib/dbmigrate')
135 db_uri = self.dburi
135 db_uri = self.dburi
136
136
137 try:
137 try:
138 curr_version = api.db_version(db_uri, repository_path)
138 curr_version = api.db_version(db_uri, repository_path)
139 msg = ('Found current database under version'
139 msg = ('Found current database under version'
140 ' control with version %s' % curr_version)
140 ' control with version %s' % curr_version)
141
141
142 except (RuntimeError, DatabaseNotControlledError), e:
142 except (RuntimeError, DatabaseNotControlledError), e:
143 curr_version = 1
143 curr_version = 1
144 msg = ('Current database is not under version control. Setting'
144 msg = ('Current database is not under version control. Setting'
145 ' as version %s' % curr_version)
145 ' as version %s' % curr_version)
146 api.version_control(db_uri, repository_path, curr_version)
146 api.version_control(db_uri, repository_path, curr_version)
147
147
148 print (msg)
148 print (msg)
149
149
150 if curr_version == __dbversion__:
150 if curr_version == __dbversion__:
151 sys.exit('This database is already at the newest version')
151 sys.exit('This database is already at the newest version')
152
152
153 #======================================================================
153 #======================================================================
154 # UPGRADE STEPS
154 # UPGRADE STEPS
155 #======================================================================
155 #======================================================================
156 class UpgradeSteps(object):
156 class UpgradeSteps(object):
157 """Those steps follow schema versions so for example schema
157 """Those steps follow schema versions so for example schema
158 for example schema with seq 002 == step_2 and so on.
158 for example schema with seq 002 == step_2 and so on.
159 """
159 """
160
160
161 def __init__(self, klass):
161 def __init__(self, klass):
162 self.klass = klass
162 self.klass = klass
163
163
164 def step_0(self):
164 def step_0(self):
165 #step 0 is the schema upgrade, and than follow proper upgrades
165 #step 0 is the schema upgrade, and than follow proper upgrades
166 print ('attempting to do database upgrade to version %s' \
166 print ('attempting to do database upgrade to version %s' \
167 % __dbversion__)
167 % __dbversion__)
168 api.upgrade(db_uri, repository_path, __dbversion__)
168 api.upgrade(db_uri, repository_path, __dbversion__)
169 print ('Schema upgrade completed')
169 print ('Schema upgrade completed')
170
170
171 def step_1(self):
171 def step_1(self):
172 pass
172 pass
173
173
174 def step_2(self):
174 def step_2(self):
175 print ('Patching repo paths for newer version of RhodeCode')
175 print ('Patching repo paths for newer version of RhodeCode')
176 self.klass.fix_repo_paths()
176 self.klass.fix_repo_paths()
177
177
178 print ('Patching default user of RhodeCode')
178 print ('Patching default user of RhodeCode')
179 self.klass.fix_default_user()
179 self.klass.fix_default_user()
180
180
181 log.info('Changing ui settings')
181 log.info('Changing ui settings')
182 self.klass.create_ui_settings()
182 self.klass.create_ui_settings()
183
183
184 def step_3(self):
184 def step_3(self):
185 print ('Adding additional settings into RhodeCode db')
185 print ('Adding additional settings into RhodeCode db')
186 self.klass.fix_settings()
186 self.klass.fix_settings()
187
187
188 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
188 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
189
189
190 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
190 #CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
191 for step in upgrade_steps:
191 for step in upgrade_steps:
192 print ('performing upgrade step %s' % step)
192 print ('performing upgrade step %s' % step)
193 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
193 callable = getattr(UpgradeSteps(self), 'step_%s' % step)()
194
194
195
195
196
196
197 def fix_repo_paths(self):
197 def fix_repo_paths(self):
198 """Fixes a old rhodecode version path into new one without a '*'
198 """Fixes a old rhodecode version path into new one without a '*'
199 """
199 """
200
200
201 paths = self.sa.query(RhodeCodeUi)\
201 paths = self.sa.query(RhodeCodeUi)\
202 .filter(RhodeCodeUi.ui_key == '/')\
202 .filter(RhodeCodeUi.ui_key == '/')\
203 .scalar()
203 .scalar()
204
204
205 paths.ui_value = paths.ui_value.replace('*', '')
205 paths.ui_value = paths.ui_value.replace('*', '')
206
206
207 try:
207 try:
208 self.sa.add(paths)
208 self.sa.add(paths)
209 self.sa.commit()
209 self.sa.commit()
210 except:
210 except:
211 self.sa.rollback()
211 self.sa.rollback()
212 raise
212 raise
213
213
214 def fix_default_user(self):
214 def fix_default_user(self):
215 """Fixes a old default user with some 'nicer' default values,
215 """Fixes a old default user with some 'nicer' default values,
216 used mostly for anonymous access
216 used mostly for anonymous access
217 """
217 """
218 def_user = self.sa.query(User)\
218 def_user = self.sa.query(User)\
219 .filter(User.username == 'default')\
219 .filter(User.username == 'default')\
220 .one()
220 .one()
221
221
222 def_user.name = 'Anonymous'
222 def_user.name = 'Anonymous'
223 def_user.lastname = 'User'
223 def_user.lastname = 'User'
224 def_user.email = 'anonymous@rhodecode.org'
224 def_user.email = 'anonymous@rhodecode.org'
225
225
226 try:
226 try:
227 self.sa.add(def_user)
227 self.sa.add(def_user)
228 self.sa.commit()
228 self.sa.commit()
229 except:
229 except:
230 self.sa.rollback()
230 self.sa.rollback()
231 raise
231 raise
232
232
233 def fix_settings(self):
233 def fix_settings(self):
234 """Fixes rhodecode settings adds ga_code key for google analytics
234 """Fixes rhodecode settings adds ga_code key for google analytics
235 """
235 """
236
236
237 hgsettings3 = RhodeCodeSettings('ga_code', '')
237 hgsettings3 = RhodeCodeSettings('ga_code', '')
238
238
239 try:
239 try:
240 self.sa.add(hgsettings3)
240 self.sa.add(hgsettings3)
241 self.sa.commit()
241 self.sa.commit()
242 except:
242 except:
243 self.sa.rollback()
243 self.sa.rollback()
244 raise
244 raise
245
245
246 def admin_prompt(self, second=False):
246 def admin_prompt(self, second=False):
247 if not self.tests:
247 if not self.tests:
248 import getpass
248 import getpass
249
249
250
250
251 def get_password():
251 def get_password():
252 password = getpass.getpass('Specify admin password (min 6 chars):')
252 password = getpass.getpass('Specify admin password (min 6 chars):')
253 confirm = getpass.getpass('Confirm password:')
253 confirm = getpass.getpass('Confirm password:')
254
254
255 if password != confirm:
255 if password != confirm:
256 log.error('passwords mismatch')
256 log.error('passwords mismatch')
257 return False
257 return False
258 if len(password) < 6:
258 if len(password) < 6:
259 log.error('password is to short use at least 6 characters')
259 log.error('password is to short use at least 6 characters')
260 return False
260 return False
261
261
262 return password
262 return password
263
263
264 username = raw_input('Specify admin username:')
264 username = raw_input('Specify admin username:')
265
265
266 password = get_password()
266 password = get_password()
267 if not password:
267 if not password:
268 #second try
268 #second try
269 password = get_password()
269 password = get_password()
270 if not password:
270 if not password:
271 sys.exit()
271 sys.exit()
272
272
273 email = raw_input('Specify admin email:')
273 email = raw_input('Specify admin email:')
274 self.create_user(username, password, email, True)
274 self.create_user(username, password, email, True)
275 else:
275 else:
276 log.info('creating admin and regular test users')
276 log.info('creating admin and regular test users')
277 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
277 self.create_user('test_admin', 'test12', 'test_admin@mail.com', True)
278 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
278 self.create_user('test_regular', 'test12', 'test_regular@mail.com', False)
279 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
279 self.create_user('test_regular2', 'test12', 'test_regular2@mail.com', False)
280
280
281 def create_ui_settings(self):
281 def create_ui_settings(self):
282 """Creates ui settings, fills out hooks
282 """Creates ui settings, fills out hooks
283 and disables dotencode
283 and disables dotencode
284
284
285 """
285 """
286 #HOOKS
286 #HOOKS
287 hooks1_key = 'changegroup.update'
287 hooks1_key = 'changegroup.update'
288 hooks1_ = self.sa.query(RhodeCodeUi)\
288 hooks1_ = self.sa.query(RhodeCodeUi)\
289 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
289 .filter(RhodeCodeUi.ui_key == hooks1_key).scalar()
290
290
291 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
291 hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_
292 hooks1.ui_section = 'hooks'
292 hooks1.ui_section = 'hooks'
293 hooks1.ui_key = hooks1_key
293 hooks1.ui_key = hooks1_key
294 hooks1.ui_value = 'hg update >&2'
294 hooks1.ui_value = 'hg update >&2'
295 hooks1.ui_active = False
295 hooks1.ui_active = False
296
296
297 hooks2_key = 'changegroup.repo_size'
297 hooks2_key = 'changegroup.repo_size'
298 hooks2_ = self.sa.query(RhodeCodeUi)\
298 hooks2_ = self.sa.query(RhodeCodeUi)\
299 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
299 .filter(RhodeCodeUi.ui_key == hooks2_key).scalar()
300
300
301 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
301 hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_
302 hooks2.ui_section = 'hooks'
302 hooks2.ui_section = 'hooks'
303 hooks2.ui_key = hooks2_key
303 hooks2.ui_key = hooks2_key
304 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
304 hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size'
305
305
306 hooks3 = RhodeCodeUi()
306 hooks3 = RhodeCodeUi()
307 hooks3.ui_section = 'hooks'
307 hooks3.ui_section = 'hooks'
308 hooks3.ui_key = 'pretxnchangegroup.push_logger'
308 hooks3.ui_key = 'pretxnchangegroup.push_logger'
309 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
309 hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action'
310
310
311 hooks4 = RhodeCodeUi()
311 hooks4 = RhodeCodeUi()
312 hooks4.ui_section = 'hooks'
312 hooks4.ui_section = 'hooks'
313 hooks4.ui_key = 'preoutgoing.pull_logger'
313 hooks4.ui_key = 'preoutgoing.pull_logger'
314 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
314 hooks4.ui_value = 'python:rhodecode.lib.hooks.log_pull_action'
315
315
316 #For mercurial 1.7 set backward comapatibility with format
316 #For mercurial 1.7 set backward comapatibility with format
317 dotencode_disable = RhodeCodeUi()
317 dotencode_disable = RhodeCodeUi()
318 dotencode_disable.ui_section = 'format'
318 dotencode_disable.ui_section = 'format'
319 dotencode_disable.ui_key = 'dotencode'
319 dotencode_disable.ui_key = 'dotencode'
320 dotencode_disable.ui_value = 'false'
320 dotencode_disable.ui_value = 'false'
321
321
322 try:
322 try:
323 self.sa.add(hooks1)
323 self.sa.add(hooks1)
324 self.sa.add(hooks2)
324 self.sa.add(hooks2)
325 self.sa.add(hooks3)
325 self.sa.add(hooks3)
326 self.sa.add(hooks4)
326 self.sa.add(hooks4)
327 self.sa.add(dotencode_disable)
327 self.sa.add(dotencode_disable)
328 self.sa.commit()
328 self.sa.commit()
329 except:
329 except:
330 self.sa.rollback()
330 self.sa.rollback()
331 raise
331 raise
332
332
333
333
334 def create_ldap_options(self):
334 def create_ldap_options(self):
335 """Creates ldap settings"""
335 """Creates ldap settings"""
336
336
337 try:
337 try:
338 for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
338 for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
339 'ldap_tls_reqcert', 'ldap_dn_user', 'ldap_dn_pass',
339 'ldap_tls_reqcert', 'ldap_dn_user', 'ldap_dn_pass',
340 'ldap_base_dn', 'ldap_filter', 'ldap_search_scope',
340 'ldap_base_dn', 'ldap_filter', 'ldap_search_scope',
341 'ldap_attr_login', 'ldap_attr_firstname', 'ldap_attr_lastname',
341 'ldap_attr_login', 'ldap_attr_firstname', 'ldap_attr_lastname',
342 'ldap_attr_email']:
342 'ldap_attr_email']:
343
343
344 setting = RhodeCodeSettings(k, '')
344 setting = RhodeCodeSettings(k, '')
345 self.sa.add(setting)
345 self.sa.add(setting)
346 self.sa.commit()
346 self.sa.commit()
347 except:
347 except:
348 self.sa.rollback()
348 self.sa.rollback()
349 raise
349 raise
350
350
351 def config_prompt(self, test_repo_path='', retries=3):
351 def config_prompt(self, test_repo_path='', retries=3):
352 if retries == 3:
352 if retries == 3:
353 log.info('Setting up repositories config')
353 log.info('Setting up repositories config')
354
354
355 if not self.tests and not test_repo_path:
355 if not self.tests and not test_repo_path:
356 path = raw_input('Specify valid full path to your repositories'
356 path = raw_input('Specify valid full path to your repositories'
357 ' you can change this later in application settings:')
357 ' you can change this later in application settings:')
358 else:
358 else:
359 path = test_repo_path
359 path = test_repo_path
360 path_ok = True
360 path_ok = True
361
361
362 #check proper dir
362 #check proper dir
363 if not os.path.isdir(path):
363 if not os.path.isdir(path):
364 path_ok = False
364 path_ok = False
365 log.error('Entered path is not a valid directory: %s [%s/3]',
365 log.error('Entered path is not a valid directory: %s [%s/3]',
366 path, retries)
366 path, retries)
367
367
368 #check write access
368 #check write access
369 if not os.access(path, os.W_OK):
369 if not os.access(path, os.W_OK):
370 path_ok = False
370 path_ok = False
371
371
372 log.error('No write permission to given path: %s [%s/3]',
372 log.error('No write permission to given path: %s [%s/3]',
373 path, retries)
373 path, retries)
374
374
375
375
376 if retries == 0:
376 if retries == 0:
377 sys.exit()
377 sys.exit()
378 if path_ok is False:
378 if path_ok is False:
379 retries -= 1
379 retries -= 1
380 return self.config_prompt(test_repo_path, retries)
380 return self.config_prompt(test_repo_path, retries)
381
381
382
382
383 return path
383 return path
384
384
385 def create_settings(self, path):
385 def create_settings(self, path):
386
386
387 self.create_ui_settings()
387 self.create_ui_settings()
388
388
389 #HG UI OPTIONS
389 #HG UI OPTIONS
390 web1 = RhodeCodeUi()
390 web1 = RhodeCodeUi()
391 web1.ui_section = 'web'
391 web1.ui_section = 'web'
392 web1.ui_key = 'push_ssl'
392 web1.ui_key = 'push_ssl'
393 web1.ui_value = 'false'
393 web1.ui_value = 'false'
394
394
395 web2 = RhodeCodeUi()
395 web2 = RhodeCodeUi()
396 web2.ui_section = 'web'
396 web2.ui_section = 'web'
397 web2.ui_key = 'allow_archive'
397 web2.ui_key = 'allow_archive'
398 web2.ui_value = 'gz zip bz2'
398 web2.ui_value = 'gz zip bz2'
399
399
400 web3 = RhodeCodeUi()
400 web3 = RhodeCodeUi()
401 web3.ui_section = 'web'
401 web3.ui_section = 'web'
402 web3.ui_key = 'allow_push'
402 web3.ui_key = 'allow_push'
403 web3.ui_value = '*'
403 web3.ui_value = '*'
404
404
405 web4 = RhodeCodeUi()
405 web4 = RhodeCodeUi()
406 web4.ui_section = 'web'
406 web4.ui_section = 'web'
407 web4.ui_key = 'baseurl'
407 web4.ui_key = 'baseurl'
408 web4.ui_value = '/'
408 web4.ui_value = '/'
409
409
410 paths = RhodeCodeUi()
410 paths = RhodeCodeUi()
411 paths.ui_section = 'paths'
411 paths.ui_section = 'paths'
412 paths.ui_key = '/'
412 paths.ui_key = '/'
413 paths.ui_value = path
413 paths.ui_value = path
414
414
415
415
416 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
416 hgsettings1 = RhodeCodeSettings('realm', 'RhodeCode authentication')
417 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
417 hgsettings2 = RhodeCodeSettings('title', 'RhodeCode')
418 hgsettings3 = RhodeCodeSettings('ga_code', '')
418 hgsettings3 = RhodeCodeSettings('ga_code', '')
419
419
420
420
421 try:
421 try:
422 self.sa.add(web1)
422 self.sa.add(web1)
423 self.sa.add(web2)
423 self.sa.add(web2)
424 self.sa.add(web3)
424 self.sa.add(web3)
425 self.sa.add(web4)
425 self.sa.add(web4)
426 self.sa.add(paths)
426 self.sa.add(paths)
427 self.sa.add(hgsettings1)
427 self.sa.add(hgsettings1)
428 self.sa.add(hgsettings2)
428 self.sa.add(hgsettings2)
429 self.sa.add(hgsettings3)
429 self.sa.add(hgsettings3)
430
430
431 self.sa.commit()
431 self.sa.commit()
432 except:
432 except:
433 self.sa.rollback()
433 self.sa.rollback()
434 raise
434 raise
435
435
436 self.create_ldap_options()
436 self.create_ldap_options()
437
437
438 log.info('created ui config')
438 log.info('created ui config')
439
439
440 def create_user(self, username, password, email='', admin=False):
440 def create_user(self, username, password, email='', admin=False):
441 log.info('creating administrator user %s', username)
441 log.info('creating administrator user %s', username)
442 new_user = User()
442 new_user = User()
443 new_user.username = username
443 new_user.username = username
444 new_user.password = get_crypt_password(password)
444 new_user.password = get_crypt_password(password)
445 new_user.api_key = generate_api_key(username)
445 new_user.name = 'RhodeCode'
446 new_user.name = 'RhodeCode'
446 new_user.lastname = 'Admin'
447 new_user.lastname = 'Admin'
447 new_user.email = email
448 new_user.email = email
448 new_user.admin = admin
449 new_user.admin = admin
449 new_user.active = True
450 new_user.active = True
450
451
451 try:
452 try:
452 self.sa.add(new_user)
453 self.sa.add(new_user)
453 self.sa.commit()
454 self.sa.commit()
454 except:
455 except:
455 self.sa.rollback()
456 self.sa.rollback()
456 raise
457 raise
457
458
458 def create_default_user(self):
459 def create_default_user(self):
459 log.info('creating default user')
460 log.info('creating default user')
460 #create default user for handling default permissions.
461 #create default user for handling default permissions.
461 def_user = User()
462 def_user = User()
462 def_user.username = 'default'
463 def_user.username = 'default'
463 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
464 def_user.password = get_crypt_password(str(uuid.uuid1())[:8])
465 def_user.api_key = generate_api_key('default')
464 def_user.name = 'Anonymous'
466 def_user.name = 'Anonymous'
465 def_user.lastname = 'User'
467 def_user.lastname = 'User'
466 def_user.email = 'anonymous@rhodecode.org'
468 def_user.email = 'anonymous@rhodecode.org'
467 def_user.admin = False
469 def_user.admin = False
468 def_user.active = False
470 def_user.active = False
469 try:
471 try:
470 self.sa.add(def_user)
472 self.sa.add(def_user)
471 self.sa.commit()
473 self.sa.commit()
472 except:
474 except:
473 self.sa.rollback()
475 self.sa.rollback()
474 raise
476 raise
475
477
476 def create_permissions(self):
478 def create_permissions(self):
477 #module.(access|create|change|delete)_[name]
479 #module.(access|create|change|delete)_[name]
478 #module.(read|write|owner)
480 #module.(read|write|owner)
479 perms = [('repository.none', 'Repository no access'),
481 perms = [('repository.none', 'Repository no access'),
480 ('repository.read', 'Repository read access'),
482 ('repository.read', 'Repository read access'),
481 ('repository.write', 'Repository write access'),
483 ('repository.write', 'Repository write access'),
482 ('repository.admin', 'Repository admin access'),
484 ('repository.admin', 'Repository admin access'),
483 ('hg.admin', 'Hg Administrator'),
485 ('hg.admin', 'Hg Administrator'),
484 ('hg.create.repository', 'Repository create'),
486 ('hg.create.repository', 'Repository create'),
485 ('hg.create.none', 'Repository creation disabled'),
487 ('hg.create.none', 'Repository creation disabled'),
486 ('hg.register.none', 'Register disabled'),
488 ('hg.register.none', 'Register disabled'),
487 ('hg.register.manual_activate', 'Register new user with rhodecode without manual activation'),
489 ('hg.register.manual_activate', 'Register new user with RhodeCode without manual activation'),
488 ('hg.register.auto_activate', 'Register new user with rhodecode without auto activation'),
490 ('hg.register.auto_activate', 'Register new user with RhodeCode without auto activation'),
489 ]
491 ]
490
492
491 for p in perms:
493 for p in perms:
492 new_perm = Permission()
494 new_perm = Permission()
493 new_perm.permission_name = p[0]
495 new_perm.permission_name = p[0]
494 new_perm.permission_longname = p[1]
496 new_perm.permission_longname = p[1]
495 try:
497 try:
496 self.sa.add(new_perm)
498 self.sa.add(new_perm)
497 self.sa.commit()
499 self.sa.commit()
498 except:
500 except:
499 self.sa.rollback()
501 self.sa.rollback()
500 raise
502 raise
501
503
502 def populate_default_permissions(self):
504 def populate_default_permissions(self):
503 log.info('creating default user permissions')
505 log.info('creating default user permissions')
504
506
505 default_user = self.sa.query(User)\
507 default_user = self.sa.query(User)\
506 .filter(User.username == 'default').scalar()
508 .filter(User.username == 'default').scalar()
507
509
508 reg_perm = UserToPerm()
510 reg_perm = UserToPerm()
509 reg_perm.user = default_user
511 reg_perm.user = default_user
510 reg_perm.permission = self.sa.query(Permission)\
512 reg_perm.permission = self.sa.query(Permission)\
511 .filter(Permission.permission_name == 'hg.register.manual_activate')\
513 .filter(Permission.permission_name == 'hg.register.manual_activate')\
512 .scalar()
514 .scalar()
513
515
514 create_repo_perm = UserToPerm()
516 create_repo_perm = UserToPerm()
515 create_repo_perm.user = default_user
517 create_repo_perm.user = default_user
516 create_repo_perm.permission = self.sa.query(Permission)\
518 create_repo_perm.permission = self.sa.query(Permission)\
517 .filter(Permission.permission_name == 'hg.create.repository')\
519 .filter(Permission.permission_name == 'hg.create.repository')\
518 .scalar()
520 .scalar()
519
521
520 default_repo_perm = UserToPerm()
522 default_repo_perm = UserToPerm()
521 default_repo_perm.user = default_user
523 default_repo_perm.user = default_user
522 default_repo_perm.permission = self.sa.query(Permission)\
524 default_repo_perm.permission = self.sa.query(Permission)\
523 .filter(Permission.permission_name == 'repository.read')\
525 .filter(Permission.permission_name == 'repository.read')\
524 .scalar()
526 .scalar()
525
527
526 try:
528 try:
527 self.sa.add(reg_perm)
529 self.sa.add(reg_perm)
528 self.sa.add(create_repo_perm)
530 self.sa.add(create_repo_perm)
529 self.sa.add(default_repo_perm)
531 self.sa.add(default_repo_perm)
530 self.sa.commit()
532 self.sa.commit()
531 except:
533 except:
532 self.sa.rollback()
534 self.sa.rollback()
533 raise
535 raise
534
536
@@ -1,225 +1,230 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
13 # This program is free software; you can redistribute it and/or
14 # modify it under the terms of the GNU General Public License
14 # modify it under the terms of the GNU General Public License
15 # as published by the Free Software Foundation; version 2
15 # as published by the Free Software Foundation; version 2
16 # of the License or (at your opinion) any later version of the license.
16 # of the License or (at your opinion) any later version of the license.
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, write to the Free Software
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 # MA 02110-1301, USA.
26 # MA 02110-1301, USA.
27
27
28 import logging
28 import logging
29 import traceback
29 import traceback
30
30
31 from pylons.i18n.translation import _
31 from pylons.i18n.translation import _
32
32
33 from rhodecode.model import BaseModel
33 from rhodecode.model import BaseModel
34 from rhodecode.model.caching_query import FromCache
34 from rhodecode.model.caching_query import FromCache
35 from rhodecode.model.db import User
35 from rhodecode.model.db import User
36
36
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
37 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
38
38
39 from sqlalchemy.exc import DatabaseError
39 from sqlalchemy.exc import DatabaseError
40 from rhodecode.lib import generate_api_key
40
41
41 log = logging.getLogger(__name__)
42 log = logging.getLogger(__name__)
42
43
43 class UserModel(BaseModel):
44 class UserModel(BaseModel):
44
45
45 def get(self, user_id, cache=False):
46 def get(self, user_id, cache=False):
46 user = self.sa.query(User)
47 user = self.sa.query(User)
47 if cache:
48 if cache:
48 user = user.options(FromCache("sql_cache_short",
49 user = user.options(FromCache("sql_cache_short",
49 "get_user_%s" % user_id))
50 "get_user_%s" % user_id))
50 return user.get(user_id)
51 return user.get(user_id)
51
52
52
53
53 def get_by_username(self, username, cache=False, case_insensitive=False):
54 def get_by_username(self, username, cache=False, case_insensitive=False):
54
55
55 if case_insensitive:
56 if case_insensitive:
56 user = self.sa.query(User).filter(User.username.ilike(username))
57 user = self.sa.query(User).filter(User.username.ilike(username))
57 else:
58 else:
58 user = self.sa.query(User)\
59 user = self.sa.query(User)\
59 .filter(User.username == username)
60 .filter(User.username == username)
60 if cache:
61 if cache:
61 user = user.options(FromCache("sql_cache_short",
62 user = user.options(FromCache("sql_cache_short",
62 "get_user_%s" % username))
63 "get_user_%s" % username))
63 return user.scalar()
64 return user.scalar()
64
65
65 def create(self, form_data):
66 def create(self, form_data):
66 try:
67 try:
67 new_user = User()
68 new_user = User()
68 for k, v in form_data.items():
69 for k, v in form_data.items():
69 setattr(new_user, k, v)
70 setattr(new_user, k, v)
70
71
72 new_user.api_key = generate_api_key(form_data['username'])
71 self.sa.add(new_user)
73 self.sa.add(new_user)
72 self.sa.commit()
74 self.sa.commit()
73 except:
75 except:
74 log.error(traceback.format_exc())
76 log.error(traceback.format_exc())
75 self.sa.rollback()
77 self.sa.rollback()
76 raise
78 raise
77
79
78 def create_ldap(self, username, password, user_dn, attrs):
80 def create_ldap(self, username, password, user_dn, attrs):
79 """
81 """
80 Checks if user is in database, if not creates this user marked
82 Checks if user is in database, if not creates this user marked
81 as ldap user
83 as ldap user
82 :param username:
84 :param username:
83 :param password:
85 :param password:
84 :param user_dn:
86 :param user_dn:
85 :param attrs:
87 :param attrs:
86 """
88 """
87 from rhodecode.lib.auth import get_crypt_password
89 from rhodecode.lib.auth import get_crypt_password
88 log.debug('Checking for such ldap account in RhodeCode database')
90 log.debug('Checking for such ldap account in RhodeCode database')
89 if self.get_by_username(username, case_insensitive=True) is None:
91 if self.get_by_username(username, case_insensitive=True) is None:
90 try:
92 try:
91 new_user = User()
93 new_user = User()
92 new_user.username = username.lower() # add ldap account always lowercase
94 new_user.username = username.lower() # add ldap account always lowercase
93 new_user.password = get_crypt_password(password)
95 new_user.password = get_crypt_password(password)
96 new_user.api_key = generate_api_key(username)
94 new_user.email = attrs['email']
97 new_user.email = attrs['email']
95 new_user.active = True
98 new_user.active = True
96 new_user.ldap_dn = user_dn
99 new_user.ldap_dn = user_dn
97 new_user.name = attrs['name']
100 new_user.name = attrs['name']
98 new_user.lastname = attrs['lastname']
101 new_user.lastname = attrs['lastname']
99
102
100
103
101 self.sa.add(new_user)
104 self.sa.add(new_user)
102 self.sa.commit()
105 self.sa.commit()
103 return True
106 return True
104 except (DatabaseError,):
107 except (DatabaseError,):
105 log.error(traceback.format_exc())
108 log.error(traceback.format_exc())
106 self.sa.rollback()
109 self.sa.rollback()
107 raise
110 raise
108 log.debug('this %s user exists skipping creation of ldap account',
111 log.debug('this %s user exists skipping creation of ldap account',
109 username)
112 username)
110 return False
113 return False
111
114
112 def create_registration(self, form_data):
115 def create_registration(self, form_data):
113 from rhodecode.lib.celerylib import tasks, run_task
116 from rhodecode.lib.celerylib import tasks, run_task
114 try:
117 try:
115 new_user = User()
118 new_user = User()
116 for k, v in form_data.items():
119 for k, v in form_data.items():
117 if k != 'admin':
120 if k != 'admin':
118 setattr(new_user, k, v)
121 setattr(new_user, k, v)
119
122
120 self.sa.add(new_user)
123 self.sa.add(new_user)
121 self.sa.commit()
124 self.sa.commit()
122 body = ('New user registration\n'
125 body = ('New user registration\n'
123 'username: %s\n'
126 'username: %s\n'
124 'email: %s\n')
127 'email: %s\n')
125 body = body % (form_data['username'], form_data['email'])
128 body = body % (form_data['username'], form_data['email'])
126
129
127 run_task(tasks.send_email, None,
130 run_task(tasks.send_email, None,
128 _('[RhodeCode] New User registration'),
131 _('[RhodeCode] New User registration'),
129 body)
132 body)
130 except:
133 except:
131 log.error(traceback.format_exc())
134 log.error(traceback.format_exc())
132 self.sa.rollback()
135 self.sa.rollback()
133 raise
136 raise
134
137
135 def update(self, user_id, form_data):
138 def update(self, user_id, form_data):
136 try:
139 try:
137 new_user = self.get(user_id, cache=False)
140 user = self.get(user_id, cache=False)
138 if new_user.username == 'default':
141 if user.username == 'default':
139 raise DefaultUserException(
142 raise DefaultUserException(
140 _("You can't Edit this user since it's"
143 _("You can't Edit this user since it's"
141 " crucial for entire application"))
144 " crucial for entire application"))
142
145
143 for k, v in form_data.items():
146 for k, v in form_data.items():
144 if k == 'new_password' and v != '':
147 if k == 'new_password' and v != '':
145 new_user.password = v
148 user.password = v
149 user.api_key = generate_api_key(user.username)
146 else:
150 else:
147 setattr(new_user, k, v)
151 setattr(user, k, v)
148
152
149 self.sa.add(new_user)
153 self.sa.add(user)
150 self.sa.commit()
154 self.sa.commit()
151 except:
155 except:
152 log.error(traceback.format_exc())
156 log.error(traceback.format_exc())
153 self.sa.rollback()
157 self.sa.rollback()
154 raise
158 raise
155
159
156 def update_my_account(self, user_id, form_data):
160 def update_my_account(self, user_id, form_data):
157 try:
161 try:
158 new_user = self.get(user_id, cache=False)
162 user = self.get(user_id, cache=False)
159 if new_user.username == 'default':
163 if user.username == 'default':
160 raise DefaultUserException(
164 raise DefaultUserException(
161 _("You can't Edit this user since it's"
165 _("You can't Edit this user since it's"
162 " crucial for entire application"))
166 " crucial for entire application"))
163 for k, v in form_data.items():
167 for k, v in form_data.items():
164 if k == 'new_password' and v != '':
168 if k == 'new_password' and v != '':
165 new_user.password = v
169 user.password = v
170 user.api_key = generate_api_key(user.username)
166 else:
171 else:
167 if k not in ['admin', 'active']:
172 if k not in ['admin', 'active']:
168 setattr(new_user, k, v)
173 setattr(user, k, v)
169
174
170 self.sa.add(new_user)
175 self.sa.add(user)
171 self.sa.commit()
176 self.sa.commit()
172 except:
177 except:
173 log.error(traceback.format_exc())
178 log.error(traceback.format_exc())
174 self.sa.rollback()
179 self.sa.rollback()
175 raise
180 raise
176
181
177 def delete(self, user_id):
182 def delete(self, user_id):
178 try:
183 try:
179 user = self.get(user_id, cache=False)
184 user = self.get(user_id, cache=False)
180 if user.username == 'default':
185 if user.username == 'default':
181 raise DefaultUserException(
186 raise DefaultUserException(
182 _("You can't remove this user since it's"
187 _("You can't remove this user since it's"
183 " crucial for entire application"))
188 " crucial for entire application"))
184 if user.repositories:
189 if user.repositories:
185 raise UserOwnsReposException(_('This user still owns %s '
190 raise UserOwnsReposException(_('This user still owns %s '
186 'repositories and cannot be '
191 'repositories and cannot be '
187 'removed. Switch owners or '
192 'removed. Switch owners or '
188 'remove those repositories') \
193 'remove those repositories') \
189 % user.repositories)
194 % user.repositories)
190 self.sa.delete(user)
195 self.sa.delete(user)
191 self.sa.commit()
196 self.sa.commit()
192 except:
197 except:
193 log.error(traceback.format_exc())
198 log.error(traceback.format_exc())
194 self.sa.rollback()
199 self.sa.rollback()
195 raise
200 raise
196
201
197 def reset_password(self, data):
202 def reset_password(self, data):
198 from rhodecode.lib.celerylib import tasks, run_task
203 from rhodecode.lib.celerylib import tasks, run_task
199 run_task(tasks.reset_user_password, data['email'])
204 run_task(tasks.reset_user_password, data['email'])
200
205
201
206
202 def fill_data(self, user):
207 def fill_data(self, user):
203 """
208 """
204 Fills user data with those from database and log out user if not
209 Fills user data with those from database and log out user if not
205 present in database
210 present in database
206 :param user:
211 :param user:
207 """
212 """
208
213
209 if not hasattr(user, 'user_id') or user.user_id is None:
214 if not hasattr(user, 'user_id') or user.user_id is None:
210 raise Exception('passed in user has to have the user_id attribute')
215 raise Exception('passed in user has to have the user_id attribute')
211
216
212
217
213 log.debug('filling auth user data')
218 log.debug('filling auth user data')
214 try:
219 try:
215 dbuser = self.get(user.user_id)
220 dbuser = self.get(user.user_id)
216 user.username = dbuser.username
221 user.username = dbuser.username
217 user.is_admin = dbuser.admin
222 user.is_admin = dbuser.admin
218 user.name = dbuser.name
223 user.name = dbuser.name
219 user.lastname = dbuser.lastname
224 user.lastname = dbuser.lastname
220 user.email = dbuser.email
225 user.email = dbuser.email
221 except:
226 except:
222 log.error(traceback.format_exc())
227 log.error(traceback.format_exc())
223 user.is_authenticated = False
228 user.is_authenticated = False
224
229
225 return user
230 return user
@@ -1,2516 +1,2516 b''
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td {
2 border:0;
2 border:0;
3 outline:0;
3 outline:0;
4 font-size:100%;
4 font-size:100%;
5 vertical-align:baseline;
5 vertical-align:baseline;
6 background:transparent;
6 background:transparent;
7 margin:0;
7 margin:0;
8 padding:0;
8 padding:0;
9 }
9 }
10
10
11 body {
11 body {
12 line-height:1;
12 line-height:1;
13 height:100%;
13 height:100%;
14 background:url("../images/background.png") repeat scroll 0 0 #B0B0B0;
14 background:url("../images/background.png") repeat scroll 0 0 #B0B0B0;
15 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
15 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
16 font-size:12px;
16 font-size:12px;
17 color:#000;
17 color:#000;
18 margin:0;
18 margin:0;
19 padding:0;
19 padding:0;
20 }
20 }
21
21
22 ol,ul {
22 ol,ul {
23 list-style:none;
23 list-style:none;
24 }
24 }
25
25
26 blockquote,q {
26 blockquote,q {
27 quotes:none;
27 quotes:none;
28 }
28 }
29
29
30 blockquote:before,blockquote:after,q:before,q:after {
30 blockquote:before,blockquote:after,q:before,q:after {
31 content:none;
31 content:none;
32 }
32 }
33
33
34 :focus {
34 :focus {
35 outline:0;
35 outline:0;
36 }
36 }
37
37
38 del {
38 del {
39 text-decoration:line-through;
39 text-decoration:line-through;
40 }
40 }
41
41
42 table {
42 table {
43 border-collapse:collapse;
43 border-collapse:collapse;
44 border-spacing:0;
44 border-spacing:0;
45 }
45 }
46
46
47 html {
47 html {
48 height:100%;
48 height:100%;
49 }
49 }
50
50
51 a {
51 a {
52 color:#003367;
52 color:#003367;
53 text-decoration:none;
53 text-decoration:none;
54 cursor:pointer;
54 cursor:pointer;
55 font-weight:700;
55 font-weight:700;
56 }
56 }
57
57
58 a:hover {
58 a:hover {
59 color:#316293;
59 color:#316293;
60 text-decoration:underline;
60 text-decoration:underline;
61 }
61 }
62
62
63 h1,h2,h3,h4,h5,h6 {
63 h1,h2,h3,h4,h5,h6 {
64 color:#292929;
64 color:#292929;
65 font-weight:700;
65 font-weight:700;
66 }
66 }
67
67
68 h1 {
68 h1 {
69 font-size:22px;
69 font-size:22px;
70 }
70 }
71
71
72 h2 {
72 h2 {
73 font-size:20px;
73 font-size:20px;
74 }
74 }
75
75
76 h3 {
76 h3 {
77 font-size:18px;
77 font-size:18px;
78 }
78 }
79
79
80 h4 {
80 h4 {
81 font-size:16px;
81 font-size:16px;
82 }
82 }
83
83
84 h5 {
84 h5 {
85 font-size:14px;
85 font-size:14px;
86 }
86 }
87
87
88 h6 {
88 h6 {
89 font-size:11px;
89 font-size:11px;
90 }
90 }
91
91
92 ul.circle {
92 ul.circle {
93 list-style-type:circle;
93 list-style-type:circle;
94 }
94 }
95
95
96 ul.disc {
96 ul.disc {
97 list-style-type:disc;
97 list-style-type:disc;
98 }
98 }
99
99
100 ul.square {
100 ul.square {
101 list-style-type:square;
101 list-style-type:square;
102 }
102 }
103
103
104 ol.lower-roman {
104 ol.lower-roman {
105 list-style-type:lower-roman;
105 list-style-type:lower-roman;
106 }
106 }
107
107
108 ol.upper-roman {
108 ol.upper-roman {
109 list-style-type:upper-roman;
109 list-style-type:upper-roman;
110 }
110 }
111
111
112 ol.lower-alpha {
112 ol.lower-alpha {
113 list-style-type:lower-alpha;
113 list-style-type:lower-alpha;
114 }
114 }
115
115
116 ol.upper-alpha {
116 ol.upper-alpha {
117 list-style-type:upper-alpha;
117 list-style-type:upper-alpha;
118 }
118 }
119
119
120 ol.decimal {
120 ol.decimal {
121 list-style-type:decimal;
121 list-style-type:decimal;
122 }
122 }
123
123
124 div.color {
124 div.color {
125 clear:both;
125 clear:both;
126 overflow:hidden;
126 overflow:hidden;
127 position:absolute;
127 position:absolute;
128 background:#FFF;
128 background:#FFF;
129 margin:7px 0 0 60px;
129 margin:7px 0 0 60px;
130 padding:1px 1px 1px 0;
130 padding:1px 1px 1px 0;
131 }
131 }
132
132
133 div.color a {
133 div.color a {
134 width:15px;
134 width:15px;
135 height:15px;
135 height:15px;
136 display:block;
136 display:block;
137 float:left;
137 float:left;
138 margin:0 0 0 1px;
138 margin:0 0 0 1px;
139 padding:0;
139 padding:0;
140 }
140 }
141
141
142 div.options {
142 div.options {
143 clear:both;
143 clear:both;
144 overflow:hidden;
144 overflow:hidden;
145 position:absolute;
145 position:absolute;
146 background:#FFF;
146 background:#FFF;
147 margin:7px 0 0 162px;
147 margin:7px 0 0 162px;
148 padding:0;
148 padding:0;
149 }
149 }
150
150
151 div.options a {
151 div.options a {
152 height:1%;
152 height:1%;
153 display:block;
153 display:block;
154 text-decoration:none;
154 text-decoration:none;
155 margin:0;
155 margin:0;
156 padding:3px 8px;
156 padding:3px 8px;
157 }
157 }
158
158
159 .top-left-rounded-corner {
159 .top-left-rounded-corner {
160 -webkit-border-top-left-radius: 8px;
160 -webkit-border-top-left-radius: 8px;
161 -khtml-border-radius-topleft: 8px;
161 -khtml-border-radius-topleft: 8px;
162 -moz-border-radius-topleft: 8px;
162 -moz-border-radius-topleft: 8px;
163 border-top-left-radius: 8px;
163 border-top-left-radius: 8px;
164 }
164 }
165
165
166 .top-right-rounded-corner {
166 .top-right-rounded-corner {
167 -webkit-border-top-right-radius: 8px;
167 -webkit-border-top-right-radius: 8px;
168 -khtml-border-radius-topright: 8px;
168 -khtml-border-radius-topright: 8px;
169 -moz-border-radius-topright: 8px;
169 -moz-border-radius-topright: 8px;
170 border-top-right-radius: 8px;
170 border-top-right-radius: 8px;
171 }
171 }
172
172
173 .bottom-left-rounded-corner {
173 .bottom-left-rounded-corner {
174 -webkit-border-bottom-left-radius: 8px;
174 -webkit-border-bottom-left-radius: 8px;
175 -khtml-border-radius-bottomleft: 8px;
175 -khtml-border-radius-bottomleft: 8px;
176 -moz-border-radius-bottomleft: 8px;
176 -moz-border-radius-bottomleft: 8px;
177 border-bottom-left-radius: 8px;
177 border-bottom-left-radius: 8px;
178 }
178 }
179
179
180 .bottom-right-rounded-corner {
180 .bottom-right-rounded-corner {
181 -webkit-border-bottom-right-radius: 8px;
181 -webkit-border-bottom-right-radius: 8px;
182 -khtml-border-radius-bottomright: 8px;
182 -khtml-border-radius-bottomright: 8px;
183 -moz-border-radius-bottomright: 8px;
183 -moz-border-radius-bottomright: 8px;
184 border-bottom-right-radius: 8px;
184 border-bottom-right-radius: 8px;
185 }
185 }
186
186
187
187
188 #header {
188 #header {
189 margin:0;
189 margin:0;
190 padding:0 30px;
190 padding:0 30px;
191 }
191 }
192
192
193
193
194 #header ul#logged-user{
194 #header ul#logged-user{
195 margin-bottom:5px !important;
195 margin-bottom:5px !important;
196 -webkit-border-radius: 0px 0px 8px 8px;
196 -webkit-border-radius: 0px 0px 8px 8px;
197 -khtml-border-radius: 0px 0px 8px 8px;
197 -khtml-border-radius: 0px 0px 8px 8px;
198 -moz-border-radius: 0px 0px 8px 8px;
198 -moz-border-radius: 0px 0px 8px 8px;
199 border-radius: 0px 0px 8px 8px;
199 border-radius: 0px 0px 8px 8px;
200 height:37px;
200 height:37px;
201 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367
201 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367
202 }
202 }
203
203
204 #header ul#logged-user li {
204 #header ul#logged-user li {
205 list-style:none;
205 list-style:none;
206 float:left;
206 float:left;
207 margin:8px 0 0;
207 margin:8px 0 0;
208 padding:4px 12px;
208 padding:4px 12px;
209 border-left: 1px solid #316293;
209 border-left: 1px solid #316293;
210 }
210 }
211
211
212 #header ul#logged-user li.first {
212 #header ul#logged-user li.first {
213 border-left:none;
213 border-left:none;
214 margin:4px;
214 margin:4px;
215 }
215 }
216
216
217 #header ul#logged-user li.first div.gravatar {
217 #header ul#logged-user li.first div.gravatar {
218 margin-top:-2px;
218 margin-top:-2px;
219 }
219 }
220
220
221 #header ul#logged-user li.first div.account {
221 #header ul#logged-user li.first div.account {
222 padding-top:4px;
222 padding-top:4px;
223 float:left;
223 float:left;
224 }
224 }
225
225
226 #header ul#logged-user li.last {
226 #header ul#logged-user li.last {
227 border-right:none;
227 border-right:none;
228 }
228 }
229
229
230 #header ul#logged-user li a {
230 #header ul#logged-user li a {
231 color:#fff;
231 color:#fff;
232 font-weight:700;
232 font-weight:700;
233 text-decoration:none;
233 text-decoration:none;
234 }
234 }
235
235
236 #header ul#logged-user li a:hover {
236 #header ul#logged-user li a:hover {
237 text-decoration:underline;
237 text-decoration:underline;
238 }
238 }
239
239
240 #header ul#logged-user li.highlight a {
240 #header ul#logged-user li.highlight a {
241 color:#fff;
241 color:#fff;
242 }
242 }
243
243
244 #header ul#logged-user li.highlight a:hover {
244 #header ul#logged-user li.highlight a:hover {
245 color:#FFF;
245 color:#FFF;
246 }
246 }
247
247
248 #header #header-inner {
248 #header #header-inner {
249 height:40px;
249 height:40px;
250 clear:both;
250 clear:both;
251 position:relative;
251 position:relative;
252 background:#003367 url("../images/header_inner.png") repeat-x;
252 background:#003367 url("../images/header_inner.png") repeat-x;
253 border-bottom:2px solid #fff;
253 border-bottom:2px solid #fff;
254 margin:0;
254 margin:0;
255 padding:0;
255 padding:0;
256 }
256 }
257
257
258 #header #header-inner #home a {
258 #header #header-inner #home a {
259 height:40px;
259 height:40px;
260 width:46px;
260 width:46px;
261 display:block;
261 display:block;
262 background:url("../images/button_home.png");
262 background:url("../images/button_home.png");
263 background-position:0 0;
263 background-position:0 0;
264 margin:0;
264 margin:0;
265 padding:0;
265 padding:0;
266 }
266 }
267
267
268 #header #header-inner #home a:hover {
268 #header #header-inner #home a:hover {
269 background-position:0 -40px;
269 background-position:0 -40px;
270 }
270 }
271
271
272 #header #header-inner #logo h1 {
272 #header #header-inner #logo h1 {
273 color:#FFF;
273 color:#FFF;
274 font-size:18px;
274 font-size:18px;
275 margin:10px 0 0 13px;
275 margin:10px 0 0 13px;
276 padding:0;
276 padding:0;
277 }
277 }
278
278
279 #header #header-inner #logo a {
279 #header #header-inner #logo a {
280 color:#fff;
280 color:#fff;
281 text-decoration:none;
281 text-decoration:none;
282 }
282 }
283
283
284 #header #header-inner #logo a:hover {
284 #header #header-inner #logo a:hover {
285 color:#bfe3ff;
285 color:#bfe3ff;
286 }
286 }
287
287
288 #header #header-inner #quick,#header #header-inner #quick ul {
288 #header #header-inner #quick,#header #header-inner #quick ul {
289 position:relative;
289 position:relative;
290 float:right;
290 float:right;
291 list-style-type:none;
291 list-style-type:none;
292 list-style-position:outside;
292 list-style-position:outside;
293 margin:10px 5px 0 0;
293 margin:10px 5px 0 0;
294 padding:0;
294 padding:0;
295 }
295 }
296
296
297 #header #header-inner #quick li {
297 #header #header-inner #quick li {
298 position:relative;
298 position:relative;
299 float:left;
299 float:left;
300 margin:0 5px 0 0;
300 margin:0 5px 0 0;
301 padding:0;
301 padding:0;
302 }
302 }
303
303
304 #header #header-inner #quick li a {
304 #header #header-inner #quick li a {
305 top:0;
305 top:0;
306 left:0;
306 left:0;
307 height:1%;
307 height:1%;
308 display:block;
308 display:block;
309 clear:both;
309 clear:both;
310 overflow:hidden;
310 overflow:hidden;
311 color:#FFF;
311 color:#FFF;
312 font-weight:700;
312 font-weight:700;
313 text-decoration:none;
313 text-decoration:none;
314 background:#369 url("../images/quick_l.png") no-repeat top left;
314 background:#369 url("../images/quick_l.png") no-repeat top left;
315 padding:0;
315 padding:0;
316 }
316 }
317
317
318 #header #header-inner #quick li span.short {
318 #header #header-inner #quick li span.short {
319 padding:9px 6px 8px 6px;
319 padding:9px 6px 8px 6px;
320 }
320 }
321
321
322 #header #header-inner #quick li span {
322 #header #header-inner #quick li span {
323 top:0;
323 top:0;
324 right:0;
324 right:0;
325 height:1%;
325 height:1%;
326 display:block;
326 display:block;
327 float:left;
327 float:left;
328 background:url("../images/quick_r.png") no-repeat top right;
328 background:url("../images/quick_r.png") no-repeat top right;
329 border-left:1px solid #3f6f9f;
329 border-left:1px solid #3f6f9f;
330 margin:0;
330 margin:0;
331 padding:10px 12px 8px 10px;
331 padding:10px 12px 8px 10px;
332 }
332 }
333
333
334 #header #header-inner #quick li span.normal {
334 #header #header-inner #quick li span.normal {
335 border:none;
335 border:none;
336 padding:10px 12px 8px;
336 padding:10px 12px 8px;
337 }
337 }
338
338
339 #header #header-inner #quick li span.icon {
339 #header #header-inner #quick li span.icon {
340 top:0;
340 top:0;
341 left:0;
341 left:0;
342 border-left:none;
342 border-left:none;
343 background:url("../images/quick_l.png") no-repeat top left;
343 background:url("../images/quick_l.png") no-repeat top left;
344 border-right:1px solid #2e5c89;
344 border-right:1px solid #2e5c89;
345 padding:8px 8px 4px;
345 padding:8px 8px 4px;
346 }
346 }
347
347
348 #header #header-inner #quick li span.icon_short {
348 #header #header-inner #quick li span.icon_short {
349 top:0;
349 top:0;
350 left:0;
350 left:0;
351 border-left:none;
351 border-left:none;
352 background:url("../images/quick_l.png") no-repeat top left;
352 background:url("../images/quick_l.png") no-repeat top left;
353 border-right:1px solid #2e5c89;
353 border-right:1px solid #2e5c89;
354 padding:9px 4px 4px;
354 padding:9px 4px 4px;
355 }
355 }
356
356
357 #header #header-inner #quick li a:hover {
357 #header #header-inner #quick li a:hover {
358 background:#4e4e4e url("../images/quick_l_selected.png") no-repeat top left;
358 background:#4e4e4e url("../images/quick_l_selected.png") no-repeat top left;
359 }
359 }
360
360
361 #header #header-inner #quick li a:hover span {
361 #header #header-inner #quick li a:hover span {
362 border-left:1px solid #545454;
362 border-left:1px solid #545454;
363 background:url("../images/quick_r_selected.png") no-repeat top right;
363 background:url("../images/quick_r_selected.png") no-repeat top right;
364 }
364 }
365
365
366 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short {
366 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short {
367 border-left:none;
367 border-left:none;
368 border-right:1px solid #464646;
368 border-right:1px solid #464646;
369 background:url("../images/quick_l_selected.png") no-repeat top left;
369 background:url("../images/quick_l_selected.png") no-repeat top left;
370 }
370 }
371
371
372
372
373 #header #header-inner #quick ul {
373 #header #header-inner #quick ul {
374 top:29px;
374 top:29px;
375 right:0;
375 right:0;
376 min-width:200px;
376 min-width:200px;
377 display:none;
377 display:none;
378 position:absolute;
378 position:absolute;
379 background:#FFF;
379 background:#FFF;
380 border:1px solid #666;
380 border:1px solid #666;
381 border-top:1px solid #003367;
381 border-top:1px solid #003367;
382 z-index:100;
382 z-index:100;
383 margin:0;
383 margin:0;
384 padding:0;
384 padding:0;
385 }
385 }
386
386
387 #header #header-inner #quick ul.repo_switcher {
387 #header #header-inner #quick ul.repo_switcher {
388 max-height:275px;
388 max-height:275px;
389 overflow-x:hidden;
389 overflow-x:hidden;
390 overflow-y:auto;
390 overflow-y:auto;
391 }
391 }
392
392
393 #header #header-inner #quick .repo_switcher_type{
393 #header #header-inner #quick .repo_switcher_type{
394 position:absolute;
394 position:absolute;
395 left:0;
395 left:0;
396 top:9px;
396 top:9px;
397
397
398 }
398 }
399 #header #header-inner #quick li ul li {
399 #header #header-inner #quick li ul li {
400 border-bottom:1px solid #ddd;
400 border-bottom:1px solid #ddd;
401 }
401 }
402
402
403 #header #header-inner #quick li ul li a {
403 #header #header-inner #quick li ul li a {
404 width:182px;
404 width:182px;
405 height:auto;
405 height:auto;
406 display:block;
406 display:block;
407 float:left;
407 float:left;
408 background:#FFF;
408 background:#FFF;
409 color:#003367;
409 color:#003367;
410 font-weight:400;
410 font-weight:400;
411 margin:0;
411 margin:0;
412 padding:7px 9px;
412 padding:7px 9px;
413 }
413 }
414
414
415 #header #header-inner #quick li ul li a:hover {
415 #header #header-inner #quick li ul li a:hover {
416 color:#000;
416 color:#000;
417 background:#FFF;
417 background:#FFF;
418 }
418 }
419
419
420 #header #header-inner #quick ul ul {
420 #header #header-inner #quick ul ul {
421 top:auto;
421 top:auto;
422 }
422 }
423
423
424 #header #header-inner #quick li ul ul {
424 #header #header-inner #quick li ul ul {
425 right:200px;
425 right:200px;
426 max-height:275px;
426 max-height:275px;
427 overflow:auto;
427 overflow:auto;
428 overflow-x:hidden;
428 overflow-x:hidden;
429 white-space:normal;
429 white-space:normal;
430 }
430 }
431
431
432 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
432 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover {
433 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
433 background:url("../images/icons/book.png") no-repeat scroll 4px 9px #FFF;
434 width:167px;
434 width:167px;
435 margin:0;
435 margin:0;
436 padding:12px 9px 7px 24px;
436 padding:12px 9px 7px 24px;
437 }
437 }
438
438
439 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
439 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover {
440 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
440 background:url("../images/icons/lock.png") no-repeat scroll 4px 9px #FFF;
441 min-width:167px;
441 min-width:167px;
442 margin:0;
442 margin:0;
443 padding:12px 9px 7px 24px;
443 padding:12px 9px 7px 24px;
444 }
444 }
445
445
446 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
446 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover {
447 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
447 background:url("../images/icons/lock_open.png") no-repeat scroll 4px 9px #FFF;
448 min-width:167px;
448 min-width:167px;
449 margin:0;
449 margin:0;
450 padding:12px 9px 7px 24px;
450 padding:12px 9px 7px 24px;
451 }
451 }
452
452
453 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover {
453 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover {
454 background:url("../images/icons/hgicon.png") no-repeat scroll 4px 9px #FFF;
454 background:url("../images/icons/hgicon.png") no-repeat scroll 4px 9px #FFF;
455 min-width:167px;
455 min-width:167px;
456 margin:0 0 0 14px;
456 margin:0 0 0 14px;
457 padding:12px 9px 7px 24px;
457 padding:12px 9px 7px 24px;
458 }
458 }
459
459
460 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover {
460 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover {
461 background:url("../images/icons/giticon.png") no-repeat scroll 4px 9px #FFF;
461 background:url("../images/icons/giticon.png") no-repeat scroll 4px 9px #FFF;
462 min-width:167px;
462 min-width:167px;
463 margin:0 0 0 14px;
463 margin:0 0 0 14px;
464 padding:12px 9px 7px 24px;
464 padding:12px 9px 7px 24px;
465 }
465 }
466
466
467 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
467 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
468 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
468 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
469 width:167px;
469 width:167px;
470 margin:0;
470 margin:0;
471 padding:12px 9px 7px 24px;
471 padding:12px 9px 7px 24px;
472 }
472 }
473
473
474 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
474 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover {
475 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
475 background:#FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
476 width:167px;
476 width:167px;
477 margin:0;
477 margin:0;
478 padding:12px 9px 7px 24px;
478 padding:12px 9px 7px 24px;
479 }
479 }
480
480
481 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover {
481 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover {
482 background:#FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
482 background:#FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
483 width:167px;
483 width:167px;
484 margin:0;
484 margin:0;
485 padding:12px 9px 7px 24px;
485 padding:12px 9px 7px 24px;
486 }
486 }
487
487
488 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
488 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover {
489 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
489 background:#FFF url("../images/icons/cog.png") no-repeat 4px 9px;
490 width:167px;
490 width:167px;
491 margin:0;
491 margin:0;
492 padding:12px 9px 7px 24px;
492 padding:12px 9px 7px 24px;
493 }
493 }
494
494
495 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
495 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover {
496 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
496 background:#FFF url("../images/icons/key.png") no-repeat 4px 9px;
497 width:167px;
497 width:167px;
498 margin:0;
498 margin:0;
499 padding:12px 9px 7px 24px;
499 padding:12px 9px 7px 24px;
500 }
500 }
501
501
502 #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover {
502 #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover {
503 background:#FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
503 background:#FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
504 width:167px;
504 width:167px;
505 margin:0;
505 margin:0;
506 padding:12px 9px 7px 24px;
506 padding:12px 9px 7px 24px;
507 }
507 }
508
508
509 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
509 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover {
510 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
510 background:#FFF url("../images/icons/arrow_divide.png") no-repeat 4px 9px;
511 width:167px;
511 width:167px;
512 margin:0;
512 margin:0;
513 padding:12px 9px 7px 24px;
513 padding:12px 9px 7px 24px;
514 }
514 }
515
515
516 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
516 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover {
517 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
517 background:#FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
518 width:167px;
518 width:167px;
519 margin:0;
519 margin:0;
520 padding:12px 9px 7px 24px;
520 padding:12px 9px 7px 24px;
521 }
521 }
522
522
523 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
523 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover {
524 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
524 background:#FFF url("../images/icons/delete.png") no-repeat 4px 9px;
525 width:167px;
525 width:167px;
526 margin:0;
526 margin:0;
527 padding:12px 9px 7px 24px;
527 padding:12px 9px 7px 24px;
528 }
528 }
529
529
530 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
530 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover {
531 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
531 background:#FFF url("../images/icons/arrow_branch.png") no-repeat 4px 9px;
532 width:167px;
532 width:167px;
533 margin:0;
533 margin:0;
534 padding:12px 9px 7px 24px;
534 padding:12px 9px 7px 24px;
535 }
535 }
536
536
537 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
537 #header #header-inner #quick li ul li a.tags,#header #header-inner #quick li ul li a.tags:hover {
538 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
538 background:#FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
539 width:167px;
539 width:167px;
540 margin:0;
540 margin:0;
541 padding:12px 9px 7px 24px;
541 padding:12px 9px 7px 24px;
542 }
542 }
543
543
544 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
544 #header #header-inner #quick li ul li a.admin,#header #header-inner #quick li ul li a.admin:hover {
545 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
545 background:#FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
546 width:167px;
546 width:167px;
547 margin:0;
547 margin:0;
548 padding:12px 9px 7px 24px;
548 padding:12px 9px 7px 24px;
549 }
549 }
550
550
551 #content #left {
551 #content #left {
552 left:0;
552 left:0;
553 width:280px;
553 width:280px;
554 position:absolute;
554 position:absolute;
555 }
555 }
556
556
557 #content #right {
557 #content #right {
558 margin:0 60px 10px 290px;
558 margin:0 60px 10px 290px;
559 }
559 }
560
560
561 #content div.box {
561 #content div.box {
562 clear:both;
562 clear:both;
563 overflow:hidden;
563 overflow:hidden;
564 background:#fff;
564 background:#fff;
565 margin:0 0 10px;
565 margin:0 0 10px;
566 padding:0 0 10px;
566 padding:0 0 10px;
567 }
567 }
568
568
569 #content div.box-left {
569 #content div.box-left {
570 width:49%;
570 width:49%;
571 clear:none;
571 clear:none;
572 float:left;
572 float:left;
573 margin:0 0 10px;
573 margin:0 0 10px;
574 }
574 }
575
575
576 #content div.box-right {
576 #content div.box-right {
577 width:49%;
577 width:49%;
578 clear:none;
578 clear:none;
579 float:right;
579 float:right;
580 margin:0 0 10px;
580 margin:0 0 10px;
581 }
581 }
582
582
583 #content div.box div.title {
583 #content div.box div.title {
584 clear:both;
584 clear:both;
585 overflow:hidden;
585 overflow:hidden;
586 background:#369 url("../images/header_inner.png") repeat-x;
586 background:#369 url("../images/header_inner.png") repeat-x;
587 margin:0 0 20px;
587 margin:0 0 20px;
588 padding:0;
588 padding:0;
589 }
589 }
590
590
591 #content div.box div.title h5 {
591 #content div.box div.title h5 {
592 float:left;
592 float:left;
593 border:none;
593 border:none;
594 color:#fff;
594 color:#fff;
595 text-transform:uppercase;
595 text-transform:uppercase;
596 margin:0;
596 margin:0;
597 padding:11px 0 11px 10px;
597 padding:11px 0 11px 10px;
598 }
598 }
599
599
600 #content div.box div.title ul.links li {
600 #content div.box div.title ul.links li {
601 list-style:none;
601 list-style:none;
602 float:left;
602 float:left;
603 margin:0;
603 margin:0;
604 padding:0;
604 padding:0;
605 }
605 }
606
606
607 #content div.box div.title ul.links li a {
607 #content div.box div.title ul.links li a {
608 border-left: 1px solid #316293;
608 border-left: 1px solid #316293;
609 color: #FFFFFF;
609 color: #FFFFFF;
610 display: block;
610 display: block;
611 float: left;
611 float: left;
612 font-size: 13px;
612 font-size: 13px;
613 font-weight: 700;
613 font-weight: 700;
614 height: 1%;
614 height: 1%;
615 margin: 0;
615 margin: 0;
616 padding: 11px 22px 12px;
616 padding: 11px 22px 12px;
617 text-decoration: none;
617 text-decoration: none;
618 }
618 }
619
619
620 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
620 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6 {
621 clear:both;
621 clear:both;
622 overflow:hidden;
622 overflow:hidden;
623 border-bottom:1px solid #DDD;
623 border-bottom:1px solid #DDD;
624 margin:10px 20px;
624 margin:10px 20px;
625 padding:0 0 15px;
625 padding:0 0 15px;
626 }
626 }
627
627
628 #content div.box p {
628 #content div.box p {
629 color:#5f5f5f;
629 color:#5f5f5f;
630 font-size:12px;
630 font-size:12px;
631 line-height:150%;
631 line-height:150%;
632 margin:0 24px 10px;
632 margin:0 24px 10px;
633 padding:0;
633 padding:0;
634 }
634 }
635
635
636 #content div.box blockquote {
636 #content div.box blockquote {
637 border-left:4px solid #DDD;
637 border-left:4px solid #DDD;
638 color:#5f5f5f;
638 color:#5f5f5f;
639 font-size:11px;
639 font-size:11px;
640 line-height:150%;
640 line-height:150%;
641 margin:0 34px;
641 margin:0 34px;
642 padding:0 0 0 14px;
642 padding:0 0 0 14px;
643 }
643 }
644
644
645 #content div.box blockquote p {
645 #content div.box blockquote p {
646 margin:10px 0;
646 margin:10px 0;
647 padding:0;
647 padding:0;
648 }
648 }
649
649
650 #content div.box dl {
650 #content div.box dl {
651 margin:10px 24px;
651 margin:10px 24px;
652 }
652 }
653
653
654 #content div.box dt {
654 #content div.box dt {
655 font-size:12px;
655 font-size:12px;
656 margin:0;
656 margin:0;
657 }
657 }
658
658
659 #content div.box dd {
659 #content div.box dd {
660 font-size:12px;
660 font-size:12px;
661 margin:0;
661 margin:0;
662 padding:8px 0 8px 15px;
662 padding:8px 0 8px 15px;
663 }
663 }
664
664
665 #content div.box li {
665 #content div.box li {
666 font-size:12px;
666 font-size:12px;
667 padding:4px 0;
667 padding:4px 0;
668 }
668 }
669
669
670 #content div.box ul.disc,#content div.box ul.circle {
670 #content div.box ul.disc,#content div.box ul.circle {
671 margin:10px 24px 10px 38px;
671 margin:10px 24px 10px 38px;
672 }
672 }
673
673
674 #content div.box ul.square {
674 #content div.box ul.square {
675 margin:10px 24px 10px 40px;
675 margin:10px 24px 10px 40px;
676 }
676 }
677
677
678 #content div.box img.left {
678 #content div.box img.left {
679 border:none;
679 border:none;
680 float:left;
680 float:left;
681 margin:10px 10px 10px 0;
681 margin:10px 10px 10px 0;
682 }
682 }
683
683
684 #content div.box img.right {
684 #content div.box img.right {
685 border:none;
685 border:none;
686 float:right;
686 float:right;
687 margin:10px 0 10px 10px;
687 margin:10px 0 10px 10px;
688 }
688 }
689
689
690 #content div.box div.messages {
690 #content div.box div.messages {
691 clear:both;
691 clear:both;
692 overflow:hidden;
692 overflow:hidden;
693 margin:0 20px;
693 margin:0 20px;
694 padding:0;
694 padding:0;
695 }
695 }
696
696
697 #content div.box div.message {
697 #content div.box div.message {
698 clear:both;
698 clear:both;
699 overflow:hidden;
699 overflow:hidden;
700 margin:0;
700 margin:0;
701 padding:10px 0;
701 padding:10px 0;
702 }
702 }
703
703
704 #content div.box div.message a {
704 #content div.box div.message a {
705 font-weight:400 !important;
705 font-weight:400 !important;
706 }
706 }
707
707
708 #content div.box div.message div.image {
708 #content div.box div.message div.image {
709 float:left;
709 float:left;
710 margin:9px 0 0 5px;
710 margin:9px 0 0 5px;
711 padding:6px;
711 padding:6px;
712 }
712 }
713
713
714 #content div.box div.message div.image img {
714 #content div.box div.message div.image img {
715 vertical-align:middle;
715 vertical-align:middle;
716 margin:0;
716 margin:0;
717 }
717 }
718
718
719 #content div.box div.message div.text {
719 #content div.box div.message div.text {
720 float:left;
720 float:left;
721 margin:0;
721 margin:0;
722 padding:9px 6px;
722 padding:9px 6px;
723 }
723 }
724
724
725 #content div.box div.message div.dismiss a {
725 #content div.box div.message div.dismiss a {
726 height:16px;
726 height:16px;
727 width:16px;
727 width:16px;
728 display:block;
728 display:block;
729 background:url("../images/icons/cross.png") no-repeat;
729 background:url("../images/icons/cross.png") no-repeat;
730 margin:15px 14px 0 0;
730 margin:15px 14px 0 0;
731 padding:0;
731 padding:0;
732 }
732 }
733
733
734 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 {
734 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 {
735 border:none;
735 border:none;
736 margin:0;
736 margin:0;
737 padding:0;
737 padding:0;
738 }
738 }
739
739
740 #content div.box div.message div.text span {
740 #content div.box div.message div.text span {
741 height:1%;
741 height:1%;
742 display:block;
742 display:block;
743 margin:0;
743 margin:0;
744 padding:5px 0 0;
744 padding:5px 0 0;
745 }
745 }
746
746
747 #content div.box div.message-error {
747 #content div.box div.message-error {
748 height:1%;
748 height:1%;
749 clear:both;
749 clear:both;
750 overflow:hidden;
750 overflow:hidden;
751 background:#FBE3E4;
751 background:#FBE3E4;
752 border:1px solid #FBC2C4;
752 border:1px solid #FBC2C4;
753 color:#860006;
753 color:#860006;
754 }
754 }
755
755
756 #content div.box div.message-error h6 {
756 #content div.box div.message-error h6 {
757 color:#860006;
757 color:#860006;
758 }
758 }
759
759
760 #content div.box div.message-warning {
760 #content div.box div.message-warning {
761 height:1%;
761 height:1%;
762 clear:both;
762 clear:both;
763 overflow:hidden;
763 overflow:hidden;
764 background:#FFF6BF;
764 background:#FFF6BF;
765 border:1px solid #FFD324;
765 border:1px solid #FFD324;
766 color:#5f5200;
766 color:#5f5200;
767 }
767 }
768
768
769 #content div.box div.message-warning h6 {
769 #content div.box div.message-warning h6 {
770 color:#5f5200;
770 color:#5f5200;
771 }
771 }
772
772
773 #content div.box div.message-notice {
773 #content div.box div.message-notice {
774 height:1%;
774 height:1%;
775 clear:both;
775 clear:both;
776 overflow:hidden;
776 overflow:hidden;
777 background:#8FBDE0;
777 background:#8FBDE0;
778 border:1px solid #6BACDE;
778 border:1px solid #6BACDE;
779 color:#003863;
779 color:#003863;
780 }
780 }
781
781
782 #content div.box div.message-notice h6 {
782 #content div.box div.message-notice h6 {
783 color:#003863;
783 color:#003863;
784 }
784 }
785
785
786 #content div.box div.message-success {
786 #content div.box div.message-success {
787 height:1%;
787 height:1%;
788 clear:both;
788 clear:both;
789 overflow:hidden;
789 overflow:hidden;
790 background:#E6EFC2;
790 background:#E6EFC2;
791 border:1px solid #C6D880;
791 border:1px solid #C6D880;
792 color:#4e6100;
792 color:#4e6100;
793 }
793 }
794
794
795 #content div.box div.message-success h6 {
795 #content div.box div.message-success h6 {
796 color:#4e6100;
796 color:#4e6100;
797 }
797 }
798
798
799 #content div.box div.form div.fields div.field {
799 #content div.box div.form div.fields div.field {
800 height:1%;
800 height:1%;
801 border-bottom:1px solid #DDD;
801 border-bottom:1px solid #DDD;
802 clear:both;
802 clear:both;
803 margin:0;
803 margin:0;
804 padding:10px 0;
804 padding:10px 0;
805 }
805 }
806
806
807 #content div.box div.form div.fields div.field-first {
807 #content div.box div.form div.fields div.field-first {
808 padding:0 0 10px;
808 padding:0 0 10px;
809 }
809 }
810
810
811 #content div.box div.form div.fields div.field-noborder {
811 #content div.box div.form div.fields div.field-noborder {
812 border-bottom:0 !important;
812 border-bottom:0 !important;
813 }
813 }
814
814
815 #content div.box div.form div.fields div.field span.error-message {
815 #content div.box div.form div.fields div.field span.error-message {
816 height:1%;
816 height:1%;
817 display:inline-block;
817 display:inline-block;
818 color:red;
818 color:red;
819 margin:8px 0 0 4px;
819 margin:8px 0 0 4px;
820 padding:0;
820 padding:0;
821 }
821 }
822
822
823 #content div.box div.form div.fields div.field span.success {
823 #content div.box div.form div.fields div.field span.success {
824 height:1%;
824 height:1%;
825 display:block;
825 display:block;
826 color:#316309;
826 color:#316309;
827 margin:8px 0 0;
827 margin:8px 0 0;
828 padding:0;
828 padding:0;
829 }
829 }
830
830
831 #content div.box div.form div.fields div.field div.label {
831 #content div.box div.form div.fields div.field div.label {
832 left:80px;
832 left:80px;
833 width:auto;
833 width:auto;
834 position:absolute;
834 position:absolute;
835 margin:0;
835 margin:0;
836 padding:8px 0 0 5px;
836 padding:8px 0 0 5px;
837 }
837 }
838
838
839 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
839 #content div.box-left div.form div.fields div.field div.label,#content div.box-right div.form div.fields div.field div.label {
840 clear:both;
840 clear:both;
841 overflow:hidden;
841 overflow:hidden;
842 left:0;
842 left:0;
843 width:auto;
843 width:auto;
844 position:relative;
844 position:relative;
845 margin:0;
845 margin:0;
846 padding:0 0 8px;
846 padding:0 0 8px;
847 }
847 }
848
848
849 #content div.box div.form div.fields div.field div.label-select {
849 #content div.box div.form div.fields div.field div.label-select {
850 padding:5px 0 0 5px;
850 padding:5px 0 0 5px;
851 }
851 }
852
852
853 #content div.box-left div.form div.fields div.field div.label-select,#content div.box-right div.form div.fields div.field div.label-select {
853 #content div.box-left div.form div.fields div.field div.label-select,#content div.box-right div.form div.fields div.field div.label-select {
854 padding:0 0 8px;
854 padding:0 0 8px;
855 }
855 }
856
856
857 #content div.box-left div.form div.fields div.field div.label-textarea,#content div.box-right div.form div.fields div.field div.label-textarea {
857 #content div.box-left div.form div.fields div.field div.label-textarea,#content div.box-right div.form div.fields div.field div.label-textarea {
858 padding:0 0 8px !important;
858 padding:0 0 8px !important;
859 }
859 }
860
860
861 #content div.box div.form div.fields div.field div.label label {
861 #content div.box div.form div.fields div.field div.label label, div.label label{
862 color:#393939;
862 color:#393939;
863 font-weight:700;
863 font-weight:700;
864 }
864 }
865
865
866 #content div.box div.form div.fields div.field div.input {
866 #content div.box div.form div.fields div.field div.input {
867 margin:0 0 0 200px;
867 margin:0 0 0 200px;
868 }
868 }
869 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
869 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input {
870 margin:0 0 0 0px;
870 margin:0 0 0 0px;
871 }
871 }
872
872
873 #content div.box div.form div.fields div.field div.input input {
873 #content div.box div.form div.fields div.field div.input input {
874 background:#FFF;
874 background:#FFF;
875 border-top:1px solid #b3b3b3;
875 border-top:1px solid #b3b3b3;
876 border-left:1px solid #b3b3b3;
876 border-left:1px solid #b3b3b3;
877 border-right:1px solid #eaeaea;
877 border-right:1px solid #eaeaea;
878 border-bottom:1px solid #eaeaea;
878 border-bottom:1px solid #eaeaea;
879 color:#000;
879 color:#000;
880 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
880 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
881 font-size:11px;
881 font-size:11px;
882 margin:0;
882 margin:0;
883 padding:7px 7px 6px;
883 padding:7px 7px 6px;
884 }
884 }
885
885
886
886
887
887
888 #content div.box div.form div.fields div.field div.input input.small {
888 #content div.box div.form div.fields div.field div.input input.small {
889 width:30%;
889 width:30%;
890 }
890 }
891
891
892 #content div.box div.form div.fields div.field div.input input.medium {
892 #content div.box div.form div.fields div.field div.input input.medium {
893 width:55%;
893 width:55%;
894 }
894 }
895
895
896 #content div.box div.form div.fields div.field div.input input.large {
896 #content div.box div.form div.fields div.field div.input input.large {
897 width:85%;
897 width:85%;
898 }
898 }
899
899
900 #content div.box div.form div.fields div.field div.input input.date {
900 #content div.box div.form div.fields div.field div.input input.date {
901 width:177px;
901 width:177px;
902 }
902 }
903
903
904 #content div.box div.form div.fields div.field div.input input.button {
904 #content div.box div.form div.fields div.field div.input input.button {
905 background:#D4D0C8;
905 background:#D4D0C8;
906 border-top:1px solid #FFF;
906 border-top:1px solid #FFF;
907 border-left:1px solid #FFF;
907 border-left:1px solid #FFF;
908 border-right:1px solid #404040;
908 border-right:1px solid #404040;
909 border-bottom:1px solid #404040;
909 border-bottom:1px solid #404040;
910 color:#000;
910 color:#000;
911 margin:0;
911 margin:0;
912 padding:4px 8px;
912 padding:4px 8px;
913 }
913 }
914
914
915 #content div.box div.form div.fields div.field div.textarea {
915 #content div.box div.form div.fields div.field div.textarea {
916 border-top:1px solid #b3b3b3;
916 border-top:1px solid #b3b3b3;
917 border-left:1px solid #b3b3b3;
917 border-left:1px solid #b3b3b3;
918 border-right:1px solid #eaeaea;
918 border-right:1px solid #eaeaea;
919 border-bottom:1px solid #eaeaea;
919 border-bottom:1px solid #eaeaea;
920 margin:0 0 0 200px;
920 margin:0 0 0 200px;
921 padding:10px;
921 padding:10px;
922 }
922 }
923
923
924 #content div.box div.form div.fields div.field div.textarea-editor {
924 #content div.box div.form div.fields div.field div.textarea-editor {
925 border:1px solid #ddd;
925 border:1px solid #ddd;
926 padding:0;
926 padding:0;
927 }
927 }
928
928
929 #content div.box div.form div.fields div.field div.textarea textarea {
929 #content div.box div.form div.fields div.field div.textarea textarea {
930 width:100%;
930 width:100%;
931 height:220px;
931 height:220px;
932 overflow:hidden;
932 overflow:hidden;
933 background:#FFF;
933 background:#FFF;
934 color:#000;
934 color:#000;
935 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
935 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
936 font-size:11px;
936 font-size:11px;
937 outline:none;
937 outline:none;
938 border-width:0;
938 border-width:0;
939 margin:0;
939 margin:0;
940 padding:0;
940 padding:0;
941 }
941 }
942
942
943 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea {
943 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea {
944 width:100%;
944 width:100%;
945 height:100px;
945 height:100px;
946 }
946 }
947
947
948 #content div.box div.form div.fields div.field div.textarea table {
948 #content div.box div.form div.fields div.field div.textarea table {
949 width:100%;
949 width:100%;
950 border:none;
950 border:none;
951 margin:0;
951 margin:0;
952 padding:0;
952 padding:0;
953 }
953 }
954
954
955 #content div.box div.form div.fields div.field div.textarea table td {
955 #content div.box div.form div.fields div.field div.textarea table td {
956 background:#DDD;
956 background:#DDD;
957 border:none;
957 border:none;
958 padding:0;
958 padding:0;
959 }
959 }
960
960
961 #content div.box div.form div.fields div.field div.textarea table td table {
961 #content div.box div.form div.fields div.field div.textarea table td table {
962 width:auto;
962 width:auto;
963 border:none;
963 border:none;
964 margin:0;
964 margin:0;
965 padding:0;
965 padding:0;
966 }
966 }
967
967
968 #content div.box div.form div.fields div.field div.textarea table td table td {
968 #content div.box div.form div.fields div.field div.textarea table td table td {
969 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
969 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
970 font-size:11px;
970 font-size:11px;
971 padding:5px 5px 5px 0;
971 padding:5px 5px 5px 0;
972 }
972 }
973
973
974 #content div.box div.form div.fields div.field input[type=text]:focus,#content div.box div.form div.fields div.field input[type=password]:focus,#content div.box div.form div.fields div.field input[type=file]:focus,#content div.box div.form div.fields div.field textarea:focus,#content div.box div.form div.fields div.field select:focus {
974 #content div.box div.form div.fields div.field input[type=text]:focus,#content div.box div.form div.fields div.field input[type=password]:focus,#content div.box div.form div.fields div.field input[type=file]:focus,#content div.box div.form div.fields div.field textarea:focus,#content div.box div.form div.fields div.field select:focus {
975 background:#f6f6f6;
975 background:#f6f6f6;
976 border-color:#666;
976 border-color:#666;
977 }
977 }
978
978
979 div.form div.fields div.field div.button {
979 div.form div.fields div.field div.button {
980 margin:0;
980 margin:0;
981 padding:0 0 0 8px;
981 padding:0 0 0 8px;
982 }
982 }
983
983
984 div.form div.fields div.field div.highlight .ui-button {
984 div.form div.fields div.field div.highlight .ui-button {
985 background:#4e85bb url("../images/button_highlight.png") repeat-x;
985 background:#4e85bb url("../images/button_highlight.png") repeat-x;
986 border-top:1px solid #5c91a4;
986 border-top:1px solid #5c91a4;
987 border-left:1px solid #2a6f89;
987 border-left:1px solid #2a6f89;
988 border-right:1px solid #2b7089;
988 border-right:1px solid #2b7089;
989 border-bottom:1px solid #1a6480;
989 border-bottom:1px solid #1a6480;
990 color:#FFF;
990 color:#FFF;
991 margin:0;
991 margin:0;
992 padding:6px 12px;
992 padding:6px 12px;
993 }
993 }
994
994
995 div.form div.fields div.field div.highlight .ui-state-hover {
995 div.form div.fields div.field div.highlight .ui-state-hover {
996 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
996 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
997 border-top:1px solid #78acbf;
997 border-top:1px solid #78acbf;
998 border-left:1px solid #34819e;
998 border-left:1px solid #34819e;
999 border-right:1px solid #35829f;
999 border-right:1px solid #35829f;
1000 border-bottom:1px solid #257897;
1000 border-bottom:1px solid #257897;
1001 color:#FFF;
1001 color:#FFF;
1002 margin:0;
1002 margin:0;
1003 padding:6px 12px;
1003 padding:6px 12px;
1004 }
1004 }
1005
1005
1006 #content div.box div.form div.fields div.buttons div.highlight input.ui-button {
1006 #content div.box div.form div.fields div.buttons div.highlight input.ui-button {
1007 background:#4e85bb url("../images/button_highlight.png") repeat-x;
1007 background:#4e85bb url("../images/button_highlight.png") repeat-x;
1008 border-top:1px solid #5c91a4;
1008 border-top:1px solid #5c91a4;
1009 border-left:1px solid #2a6f89;
1009 border-left:1px solid #2a6f89;
1010 border-right:1px solid #2b7089;
1010 border-right:1px solid #2b7089;
1011 border-bottom:1px solid #1a6480;
1011 border-bottom:1px solid #1a6480;
1012 color:#fff;
1012 color:#fff;
1013 margin:0;
1013 margin:0;
1014 padding:6px 12px;
1014 padding:6px 12px;
1015 }
1015 }
1016
1016
1017 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
1017 #content div.box div.form div.fields div.buttons div.highlight input.ui-state-hover {
1018 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
1018 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
1019 border-top:1px solid #78acbf;
1019 border-top:1px solid #78acbf;
1020 border-left:1px solid #34819e;
1020 border-left:1px solid #34819e;
1021 border-right:1px solid #35829f;
1021 border-right:1px solid #35829f;
1022 border-bottom:1px solid #257897;
1022 border-bottom:1px solid #257897;
1023 color:#fff;
1023 color:#fff;
1024 margin:0;
1024 margin:0;
1025 padding:6px 12px;
1025 padding:6px 12px;
1026 }
1026 }
1027
1027
1028 #content div.box table {
1028 #content div.box table {
1029 width:100%;
1029 width:100%;
1030 border-collapse:collapse;
1030 border-collapse:collapse;
1031 margin:0;
1031 margin:0;
1032 padding:0;
1032 padding:0;
1033 }
1033 }
1034
1034
1035 #content div.box table th {
1035 #content div.box table th {
1036 background:#eee;
1036 background:#eee;
1037 border-bottom:1px solid #ddd;
1037 border-bottom:1px solid #ddd;
1038 padding:5px 0px 5px 5px;
1038 padding:5px 0px 5px 5px;
1039 }
1039 }
1040
1040
1041 #content div.box table th.left {
1041 #content div.box table th.left {
1042 text-align:left;
1042 text-align:left;
1043 }
1043 }
1044
1044
1045 #content div.box table th.right {
1045 #content div.box table th.right {
1046 text-align:right;
1046 text-align:right;
1047 }
1047 }
1048
1048
1049 #content div.box table th.center {
1049 #content div.box table th.center {
1050 text-align:center;
1050 text-align:center;
1051 }
1051 }
1052
1052
1053 #content div.box table th.selected {
1053 #content div.box table th.selected {
1054 vertical-align:middle;
1054 vertical-align:middle;
1055 padding:0;
1055 padding:0;
1056 }
1056 }
1057
1057
1058 #content div.box table td {
1058 #content div.box table td {
1059 background:#fff;
1059 background:#fff;
1060 border-bottom:1px solid #cdcdcd;
1060 border-bottom:1px solid #cdcdcd;
1061 vertical-align:middle;
1061 vertical-align:middle;
1062 padding:5px;
1062 padding:5px;
1063 }
1063 }
1064
1064
1065 #content div.box table tr.selected td {
1065 #content div.box table tr.selected td {
1066 background:#FFC;
1066 background:#FFC;
1067 }
1067 }
1068
1068
1069 #content div.box table td.selected {
1069 #content div.box table td.selected {
1070 width:3%;
1070 width:3%;
1071 text-align:center;
1071 text-align:center;
1072 vertical-align:middle;
1072 vertical-align:middle;
1073 padding:0;
1073 padding:0;
1074 }
1074 }
1075
1075
1076 #content div.box table td.action {
1076 #content div.box table td.action {
1077 width:45%;
1077 width:45%;
1078 text-align:left;
1078 text-align:left;
1079 }
1079 }
1080
1080
1081 #content div.box table td.date {
1081 #content div.box table td.date {
1082 width:33%;
1082 width:33%;
1083 text-align:center;
1083 text-align:center;
1084 }
1084 }
1085
1085
1086 #content div.box div.action {
1086 #content div.box div.action {
1087 float:right;
1087 float:right;
1088 background:#FFF;
1088 background:#FFF;
1089 text-align:right;
1089 text-align:right;
1090 margin:10px 0 0;
1090 margin:10px 0 0;
1091 padding:0;
1091 padding:0;
1092 }
1092 }
1093
1093
1094 #content div.box div.action select {
1094 #content div.box div.action select {
1095 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1095 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1096 font-size:11px;
1096 font-size:11px;
1097 margin:0;
1097 margin:0;
1098 }
1098 }
1099
1099
1100 #content div.box div.action .ui-selectmenu {
1100 #content div.box div.action .ui-selectmenu {
1101 margin:0;
1101 margin:0;
1102 padding:0;
1102 padding:0;
1103 }
1103 }
1104
1104
1105 #content div.box div.pagination {
1105 #content div.box div.pagination {
1106 height:1%;
1106 height:1%;
1107 clear:both;
1107 clear:both;
1108 overflow:hidden;
1108 overflow:hidden;
1109 margin:10px 0 0;
1109 margin:10px 0 0;
1110 padding:0;
1110 padding:0;
1111 }
1111 }
1112
1112
1113 #content div.box div.pagination ul.pager {
1113 #content div.box div.pagination ul.pager {
1114 float:right;
1114 float:right;
1115 text-align:right;
1115 text-align:right;
1116 margin:0;
1116 margin:0;
1117 padding:0;
1117 padding:0;
1118 }
1118 }
1119
1119
1120 #content div.box div.pagination ul.pager li {
1120 #content div.box div.pagination ul.pager li {
1121 height:1%;
1121 height:1%;
1122 float:left;
1122 float:left;
1123 list-style:none;
1123 list-style:none;
1124 background:#ebebeb url("../images/pager.png") repeat-x;
1124 background:#ebebeb url("../images/pager.png") repeat-x;
1125 border-top:1px solid #dedede;
1125 border-top:1px solid #dedede;
1126 border-left:1px solid #cfcfcf;
1126 border-left:1px solid #cfcfcf;
1127 border-right:1px solid #c4c4c4;
1127 border-right:1px solid #c4c4c4;
1128 border-bottom:1px solid #c4c4c4;
1128 border-bottom:1px solid #c4c4c4;
1129 color:#4A4A4A;
1129 color:#4A4A4A;
1130 font-weight:700;
1130 font-weight:700;
1131 margin:0 0 0 4px;
1131 margin:0 0 0 4px;
1132 padding:0;
1132 padding:0;
1133 }
1133 }
1134
1134
1135 #content div.box div.pagination ul.pager li.separator {
1135 #content div.box div.pagination ul.pager li.separator {
1136 padding:6px;
1136 padding:6px;
1137 }
1137 }
1138
1138
1139 #content div.box div.pagination ul.pager li.current {
1139 #content div.box div.pagination ul.pager li.current {
1140 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1140 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1141 border-top:1px solid #ccc;
1141 border-top:1px solid #ccc;
1142 border-left:1px solid #bebebe;
1142 border-left:1px solid #bebebe;
1143 border-right:1px solid #b1b1b1;
1143 border-right:1px solid #b1b1b1;
1144 border-bottom:1px solid #afafaf;
1144 border-bottom:1px solid #afafaf;
1145 color:#515151;
1145 color:#515151;
1146 padding:6px;
1146 padding:6px;
1147 }
1147 }
1148
1148
1149 #content div.box div.pagination ul.pager li a {
1149 #content div.box div.pagination ul.pager li a {
1150 height:1%;
1150 height:1%;
1151 display:block;
1151 display:block;
1152 float:left;
1152 float:left;
1153 color:#515151;
1153 color:#515151;
1154 text-decoration:none;
1154 text-decoration:none;
1155 margin:0;
1155 margin:0;
1156 padding:6px;
1156 padding:6px;
1157 }
1157 }
1158
1158
1159 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1159 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active {
1160 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1160 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1161 border-top:1px solid #ccc;
1161 border-top:1px solid #ccc;
1162 border-left:1px solid #bebebe;
1162 border-left:1px solid #bebebe;
1163 border-right:1px solid #b1b1b1;
1163 border-right:1px solid #b1b1b1;
1164 border-bottom:1px solid #afafaf;
1164 border-bottom:1px solid #afafaf;
1165 margin:-1px;
1165 margin:-1px;
1166 }
1166 }
1167
1167
1168 #content div.box div.pagination-wh {
1168 #content div.box div.pagination-wh {
1169 height:1%;
1169 height:1%;
1170 clear:both;
1170 clear:both;
1171 overflow:hidden;
1171 overflow:hidden;
1172 text-align:right;
1172 text-align:right;
1173 margin:10px 0 0;
1173 margin:10px 0 0;
1174 padding:0;
1174 padding:0;
1175 }
1175 }
1176
1176
1177 #content div.box div.pagination-right {
1177 #content div.box div.pagination-right {
1178 float:right;
1178 float:right;
1179 }
1179 }
1180
1180
1181 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1181 #content div.box div.pagination-wh a,#content div.box div.pagination-wh span.pager_dotdot {
1182 height:1%;
1182 height:1%;
1183 float:left;
1183 float:left;
1184 background:#ebebeb url("../images/pager.png") repeat-x;
1184 background:#ebebeb url("../images/pager.png") repeat-x;
1185 border-top:1px solid #dedede;
1185 border-top:1px solid #dedede;
1186 border-left:1px solid #cfcfcf;
1186 border-left:1px solid #cfcfcf;
1187 border-right:1px solid #c4c4c4;
1187 border-right:1px solid #c4c4c4;
1188 border-bottom:1px solid #c4c4c4;
1188 border-bottom:1px solid #c4c4c4;
1189 color:#4A4A4A;
1189 color:#4A4A4A;
1190 font-weight:700;
1190 font-weight:700;
1191 margin:0 0 0 4px;
1191 margin:0 0 0 4px;
1192 padding:6px;
1192 padding:6px;
1193 }
1193 }
1194
1194
1195 #content div.box div.pagination-wh span.pager_curpage {
1195 #content div.box div.pagination-wh span.pager_curpage {
1196 height:1%;
1196 height:1%;
1197 float:left;
1197 float:left;
1198 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1198 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1199 border-top:1px solid #ccc;
1199 border-top:1px solid #ccc;
1200 border-left:1px solid #bebebe;
1200 border-left:1px solid #bebebe;
1201 border-right:1px solid #b1b1b1;
1201 border-right:1px solid #b1b1b1;
1202 border-bottom:1px solid #afafaf;
1202 border-bottom:1px solid #afafaf;
1203 color:#515151;
1203 color:#515151;
1204 font-weight:700;
1204 font-weight:700;
1205 margin:0 0 0 4px;
1205 margin:0 0 0 4px;
1206 padding:6px;
1206 padding:6px;
1207 }
1207 }
1208
1208
1209 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1209 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active {
1210 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1210 background:#b4b4b4 url("../images/pager_selected.png") repeat-x;
1211 border-top:1px solid #ccc;
1211 border-top:1px solid #ccc;
1212 border-left:1px solid #bebebe;
1212 border-left:1px solid #bebebe;
1213 border-right:1px solid #b1b1b1;
1213 border-right:1px solid #b1b1b1;
1214 border-bottom:1px solid #afafaf;
1214 border-bottom:1px solid #afafaf;
1215 text-decoration:none;
1215 text-decoration:none;
1216 }
1216 }
1217
1217
1218 #content div.box div.traffic div.legend {
1218 #content div.box div.traffic div.legend {
1219 clear:both;
1219 clear:both;
1220 overflow:hidden;
1220 overflow:hidden;
1221 border-bottom:1px solid #ddd;
1221 border-bottom:1px solid #ddd;
1222 margin:0 0 10px;
1222 margin:0 0 10px;
1223 padding:0 0 10px;
1223 padding:0 0 10px;
1224 }
1224 }
1225
1225
1226 #content div.box div.traffic div.legend h6 {
1226 #content div.box div.traffic div.legend h6 {
1227 float:left;
1227 float:left;
1228 border:none;
1228 border:none;
1229 margin:0;
1229 margin:0;
1230 padding:0;
1230 padding:0;
1231 }
1231 }
1232
1232
1233 #content div.box div.traffic div.legend li {
1233 #content div.box div.traffic div.legend li {
1234 list-style:none;
1234 list-style:none;
1235 float:left;
1235 float:left;
1236 font-size:11px;
1236 font-size:11px;
1237 margin:0;
1237 margin:0;
1238 padding:0 8px 0 4px;
1238 padding:0 8px 0 4px;
1239 }
1239 }
1240
1240
1241 #content div.box div.traffic div.legend li.visits {
1241 #content div.box div.traffic div.legend li.visits {
1242 border-left:12px solid #edc240;
1242 border-left:12px solid #edc240;
1243 }
1243 }
1244
1244
1245 #content div.box div.traffic div.legend li.pageviews {
1245 #content div.box div.traffic div.legend li.pageviews {
1246 border-left:12px solid #afd8f8;
1246 border-left:12px solid #afd8f8;
1247 }
1247 }
1248
1248
1249 #content div.box div.traffic table {
1249 #content div.box div.traffic table {
1250 width:auto;
1250 width:auto;
1251 }
1251 }
1252
1252
1253 #content div.box div.traffic table td {
1253 #content div.box div.traffic table td {
1254 background:transparent;
1254 background:transparent;
1255 border:none;
1255 border:none;
1256 padding:2px 3px 3px;
1256 padding:2px 3px 3px;
1257 }
1257 }
1258
1258
1259 #content div.box div.traffic table td.legendLabel {
1259 #content div.box div.traffic table td.legendLabel {
1260 padding:0 3px 2px;
1260 padding:0 3px 2px;
1261 }
1261 }
1262
1262
1263 #footer {
1263 #footer {
1264 clear:both;
1264 clear:both;
1265 overflow:hidden;
1265 overflow:hidden;
1266 text-align:right;
1266 text-align:right;
1267 margin:0;
1267 margin:0;
1268 padding:0 30px 4px;
1268 padding:0 30px 4px;
1269 margin:-10px 0 0;
1269 margin:-10px 0 0;
1270 }
1270 }
1271
1271
1272 #footer div#footer-inner {
1272 #footer div#footer-inner {
1273 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1273 background:url("../images/header_inner.png") repeat-x scroll 0 0 #003367;
1274 border-top:2px solid #FFFFFF;
1274 border-top:2px solid #FFFFFF;
1275 }
1275 }
1276
1276
1277 #footer div#footer-inner p {
1277 #footer div#footer-inner p {
1278 padding:15px 25px 15px 0;
1278 padding:15px 25px 15px 0;
1279 color:#FFF;
1279 color:#FFF;
1280 font-weight:700;
1280 font-weight:700;
1281 }
1281 }
1282 #footer div#footer-inner .footer-link {
1282 #footer div#footer-inner .footer-link {
1283 float:left;
1283 float:left;
1284 padding-left:10px;
1284 padding-left:10px;
1285 }
1285 }
1286 #footer div#footer-inner .footer-link a {
1286 #footer div#footer-inner .footer-link a {
1287 color:#FFF;
1287 color:#FFF;
1288 }
1288 }
1289
1289
1290 #login div.title {
1290 #login div.title {
1291 width:420px;
1291 width:420px;
1292 clear:both;
1292 clear:both;
1293 overflow:hidden;
1293 overflow:hidden;
1294 position:relative;
1294 position:relative;
1295 background:#003367 url("../images/header_inner.png") repeat-x;
1295 background:#003367 url("../images/header_inner.png") repeat-x;
1296 margin:0 auto;
1296 margin:0 auto;
1297 padding:0;
1297 padding:0;
1298 }
1298 }
1299
1299
1300 #login div.inner {
1300 #login div.inner {
1301 width:380px;
1301 width:380px;
1302 background:#FFF url("../images/login.png") no-repeat top left;
1302 background:#FFF url("../images/login.png") no-repeat top left;
1303 border-top:none;
1303 border-top:none;
1304 border-bottom:none;
1304 border-bottom:none;
1305 margin:0 auto;
1305 margin:0 auto;
1306 padding:20px;
1306 padding:20px;
1307 }
1307 }
1308
1308
1309 #login div.form div.fields div.field div.label {
1309 #login div.form div.fields div.field div.label {
1310 width:173px;
1310 width:173px;
1311 float:left;
1311 float:left;
1312 text-align:right;
1312 text-align:right;
1313 margin:2px 10px 0 0;
1313 margin:2px 10px 0 0;
1314 padding:5px 0 0 5px;
1314 padding:5px 0 0 5px;
1315 }
1315 }
1316
1316
1317 #login div.form div.fields div.field div.input input {
1317 #login div.form div.fields div.field div.input input {
1318 width:176px;
1318 width:176px;
1319 background:#FFF;
1319 background:#FFF;
1320 border-top:1px solid #b3b3b3;
1320 border-top:1px solid #b3b3b3;
1321 border-left:1px solid #b3b3b3;
1321 border-left:1px solid #b3b3b3;
1322 border-right:1px solid #eaeaea;
1322 border-right:1px solid #eaeaea;
1323 border-bottom:1px solid #eaeaea;
1323 border-bottom:1px solid #eaeaea;
1324 color:#000;
1324 color:#000;
1325 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1325 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1326 font-size:11px;
1326 font-size:11px;
1327 margin:0;
1327 margin:0;
1328 padding:7px 7px 6px;
1328 padding:7px 7px 6px;
1329 }
1329 }
1330
1330
1331 #login div.form div.fields div.buttons {
1331 #login div.form div.fields div.buttons {
1332 clear:both;
1332 clear:both;
1333 overflow:hidden;
1333 overflow:hidden;
1334 border-top:1px solid #DDD;
1334 border-top:1px solid #DDD;
1335 text-align:right;
1335 text-align:right;
1336 margin:0;
1336 margin:0;
1337 padding:10px 0 0;
1337 padding:10px 0 0;
1338 }
1338 }
1339
1339
1340 #login div.form div.links {
1340 #login div.form div.links {
1341 clear:both;
1341 clear:both;
1342 overflow:hidden;
1342 overflow:hidden;
1343 margin:10px 0 0;
1343 margin:10px 0 0;
1344 padding:0 0 2px;
1344 padding:0 0 2px;
1345 }
1345 }
1346
1346
1347 #register div.title {
1347 #register div.title {
1348 clear:both;
1348 clear:both;
1349 overflow:hidden;
1349 overflow:hidden;
1350 position:relative;
1350 position:relative;
1351 background:#003367 url("../images/header_inner.png") repeat-x;
1351 background:#003367 url("../images/header_inner.png") repeat-x;
1352 margin:0 auto;
1352 margin:0 auto;
1353 padding:0;
1353 padding:0;
1354 }
1354 }
1355
1355
1356 #register div.inner {
1356 #register div.inner {
1357 background:#FFF;
1357 background:#FFF;
1358 border-top:none;
1358 border-top:none;
1359 border-bottom:none;
1359 border-bottom:none;
1360 margin:0 auto;
1360 margin:0 auto;
1361 padding:20px;
1361 padding:20px;
1362 }
1362 }
1363
1363
1364 #register div.form div.fields div.field div.label {
1364 #register div.form div.fields div.field div.label {
1365 width:135px;
1365 width:135px;
1366 float:left;
1366 float:left;
1367 text-align:right;
1367 text-align:right;
1368 margin:2px 10px 0 0;
1368 margin:2px 10px 0 0;
1369 padding:5px 0 0 5px;
1369 padding:5px 0 0 5px;
1370 }
1370 }
1371
1371
1372 #register div.form div.fields div.field div.input input {
1372 #register div.form div.fields div.field div.input input {
1373 width:300px;
1373 width:300px;
1374 background:#FFF;
1374 background:#FFF;
1375 border-top:1px solid #b3b3b3;
1375 border-top:1px solid #b3b3b3;
1376 border-left:1px solid #b3b3b3;
1376 border-left:1px solid #b3b3b3;
1377 border-right:1px solid #eaeaea;
1377 border-right:1px solid #eaeaea;
1378 border-bottom:1px solid #eaeaea;
1378 border-bottom:1px solid #eaeaea;
1379 color:#000;
1379 color:#000;
1380 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1380 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
1381 font-size:11px;
1381 font-size:11px;
1382 margin:0;
1382 margin:0;
1383 padding:7px 7px 6px;
1383 padding:7px 7px 6px;
1384 }
1384 }
1385
1385
1386 #register div.form div.fields div.buttons {
1386 #register div.form div.fields div.buttons {
1387 clear:both;
1387 clear:both;
1388 overflow:hidden;
1388 overflow:hidden;
1389 border-top:1px solid #DDD;
1389 border-top:1px solid #DDD;
1390 text-align:left;
1390 text-align:left;
1391 margin:0;
1391 margin:0;
1392 padding:10px 0 0 150px;
1392 padding:10px 0 0 150px;
1393 }
1393 }
1394
1394
1395 #register div.form div.fields div.buttons div.highlight input.ui-button {
1395 #register div.form div.fields div.buttons div.highlight input.ui-button {
1396 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1396 background:url("../images/button_highlight.png") repeat-x scroll 0 0 #4E85BB;
1397 color:#FFF;
1397 color:#FFF;
1398 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1398 border-color:#5C91A4 #2B7089 #1A6480 #2A6F89;
1399 border-style:solid;
1399 border-style:solid;
1400 border-width:1px;
1400 border-width:1px;
1401 }
1401 }
1402
1402
1403 #register div.form div.activation_msg {
1403 #register div.form div.activation_msg {
1404 padding-top:4px;
1404 padding-top:4px;
1405 padding-bottom:4px;
1405 padding-bottom:4px;
1406 }
1406 }
1407
1407
1408 #journal .journal_day{
1408 #journal .journal_day{
1409 font-size:20px;
1409 font-size:20px;
1410 padding:10px 0px;
1410 padding:10px 0px;
1411 border-bottom:2px solid #DDD;
1411 border-bottom:2px solid #DDD;
1412 margin-left:10px;
1412 margin-left:10px;
1413 margin-right:10px;
1413 margin-right:10px;
1414 }
1414 }
1415
1415
1416 #journal .journal_container{
1416 #journal .journal_container{
1417 padding:5px;
1417 padding:5px;
1418 clear:both;
1418 clear:both;
1419 margin:0px 5px 0px 10px;
1419 margin:0px 5px 0px 10px;
1420 }
1420 }
1421
1421
1422 #journal .journal_action_container{
1422 #journal .journal_action_container{
1423 padding-left:38px;
1423 padding-left:38px;
1424 }
1424 }
1425
1425
1426 #journal .journal_user{
1426 #journal .journal_user{
1427 color: #747474;
1427 color: #747474;
1428 font-size: 14px;
1428 font-size: 14px;
1429 font-weight: bold;
1429 font-weight: bold;
1430 height: 30px;
1430 height: 30px;
1431 }
1431 }
1432 #journal .journal_icon{
1432 #journal .journal_icon{
1433 clear: both;
1433 clear: both;
1434 float: left;
1434 float: left;
1435 padding-right: 4px;
1435 padding-right: 4px;
1436 padding-top: 3px;
1436 padding-top: 3px;
1437 }
1437 }
1438 #journal .journal_action{
1438 #journal .journal_action{
1439 padding-top:4px;
1439 padding-top:4px;
1440 min-height:2px;
1440 min-height:2px;
1441 float:left
1441 float:left
1442 }
1442 }
1443 #journal .journal_action_params{
1443 #journal .journal_action_params{
1444 clear: left;
1444 clear: left;
1445 padding-left: 22px;
1445 padding-left: 22px;
1446 }
1446 }
1447 #journal .journal_repo{
1447 #journal .journal_repo{
1448 float: left;
1448 float: left;
1449 margin-left: 6px;
1449 margin-left: 6px;
1450 padding-top: 3px;
1450 padding-top: 3px;
1451 }
1451 }
1452 #journal .date{
1452 #journal .date{
1453 clear: both;
1453 clear: both;
1454 color: #777777;
1454 color: #777777;
1455 font-size: 11px;
1455 font-size: 11px;
1456 padding-left: 22px;
1456 padding-left: 22px;
1457 }
1457 }
1458 #journal .journal_repo .journal_repo_name{
1458 #journal .journal_repo .journal_repo_name{
1459 font-weight: bold;
1459 font-weight: bold;
1460 font-size: 1.1em;
1460 font-size: 1.1em;
1461 }
1461 }
1462 #journal .compare_view{
1462 #journal .compare_view{
1463 padding: 5px 0px 5px 0px;
1463 padding: 5px 0px 5px 0px;
1464 width: 95px;
1464 width: 95px;
1465 }
1465 }
1466 .journal_highlight{
1466 .journal_highlight{
1467 font-weight: bold;
1467 font-weight: bold;
1468 padding: 0 2px;
1468 padding: 0 2px;
1469 vertical-align: bottom;
1469 vertical-align: bottom;
1470 }
1470 }
1471 .trending_language_tbl,.trending_language_tbl td {
1471 .trending_language_tbl,.trending_language_tbl td {
1472 border:0 !important;
1472 border:0 !important;
1473 margin:0 !important;
1473 margin:0 !important;
1474 padding:0 !important;
1474 padding:0 !important;
1475 }
1475 }
1476
1476
1477 .trending_language {
1477 .trending_language {
1478 background-color:#003367;
1478 background-color:#003367;
1479 color:#FFF;
1479 color:#FFF;
1480 display:block;
1480 display:block;
1481 min-width:20px;
1481 min-width:20px;
1482 text-decoration:none;
1482 text-decoration:none;
1483 height:12px;
1483 height:12px;
1484 margin-bottom:4px;
1484 margin-bottom:4px;
1485 margin-left:5px;
1485 margin-left:5px;
1486 white-space:pre;
1486 white-space:pre;
1487 padding:3px;
1487 padding:3px;
1488 }
1488 }
1489
1489
1490 h3.files_location {
1490 h3.files_location {
1491 font-size:1.8em;
1491 font-size:1.8em;
1492 font-weight:700;
1492 font-weight:700;
1493 border-bottom:none !important;
1493 border-bottom:none !important;
1494 margin:10px 0 !important;
1494 margin:10px 0 !important;
1495 }
1495 }
1496
1496
1497 #files_data dl dt {
1497 #files_data dl dt {
1498 float:left;
1498 float:left;
1499 width:115px;
1499 width:115px;
1500 margin:0 !important;
1500 margin:0 !important;
1501 padding:5px;
1501 padding:5px;
1502 }
1502 }
1503
1503
1504 #files_data dl dd {
1504 #files_data dl dd {
1505 margin:0 !important;
1505 margin:0 !important;
1506 padding:5px !important;
1506 padding:5px !important;
1507 }
1507 }
1508
1508
1509 #changeset_content {
1509 #changeset_content {
1510 border:1px solid #CCC;
1510 border:1px solid #CCC;
1511 padding:5px;
1511 padding:5px;
1512 }
1512 }
1513 #changeset_compare_view_content{
1513 #changeset_compare_view_content{
1514 border:1px solid #CCC;
1514 border:1px solid #CCC;
1515 padding:5px;
1515 padding:5px;
1516 }
1516 }
1517
1517
1518 #changeset_content .container {
1518 #changeset_content .container {
1519 min-height:120px;
1519 min-height:120px;
1520 font-size:1.2em;
1520 font-size:1.2em;
1521 overflow:hidden;
1521 overflow:hidden;
1522 }
1522 }
1523
1523
1524 #changeset_compare_view_content .compare_view_commits{
1524 #changeset_compare_view_content .compare_view_commits{
1525 width: auto !important;
1525 width: auto !important;
1526 }
1526 }
1527
1527
1528 #changeset_compare_view_content .compare_view_commits td{
1528 #changeset_compare_view_content .compare_view_commits td{
1529 padding:0px 0px 0px 12px !important;
1529 padding:0px 0px 0px 12px !important;
1530 }
1530 }
1531
1531
1532 #changeset_content .container .right {
1532 #changeset_content .container .right {
1533 float:right;
1533 float:right;
1534 width:25%;
1534 width:25%;
1535 text-align:right;
1535 text-align:right;
1536 }
1536 }
1537
1537
1538 #changeset_content .container .left .message {
1538 #changeset_content .container .left .message {
1539 font-style:italic;
1539 font-style:italic;
1540 color:#556CB5;
1540 color:#556CB5;
1541 white-space:pre-wrap;
1541 white-space:pre-wrap;
1542 }
1542 }
1543
1543
1544 .cs_files .cur_cs{
1544 .cs_files .cur_cs{
1545 margin:10px 2px;
1545 margin:10px 2px;
1546 font-weight: bold;
1546 font-weight: bold;
1547 }
1547 }
1548
1548
1549 .cs_files .cs_added {
1549 .cs_files .cs_added {
1550 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1550 background:url("../images/icons/page_white_add.png") no-repeat scroll 3px;
1551 height:16px;
1551 height:16px;
1552 padding-left:20px;
1552 padding-left:20px;
1553 margin-top:7px;
1553 margin-top:7px;
1554 text-align:left;
1554 text-align:left;
1555 }
1555 }
1556
1556
1557 .cs_files .cs_changed {
1557 .cs_files .cs_changed {
1558 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1558 background:url("../images/icons/page_white_edit.png") no-repeat scroll 3px;
1559 height:16px;
1559 height:16px;
1560 padding-left:20px;
1560 padding-left:20px;
1561 margin-top:7px;
1561 margin-top:7px;
1562 text-align:left;
1562 text-align:left;
1563 }
1563 }
1564
1564
1565 .cs_files .cs_removed {
1565 .cs_files .cs_removed {
1566 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1566 background:url("../images/icons/page_white_delete.png") no-repeat scroll 3px;
1567 height:16px;
1567 height:16px;
1568 padding-left:20px;
1568 padding-left:20px;
1569 margin-top:7px;
1569 margin-top:7px;
1570 text-align:left;
1570 text-align:left;
1571 }
1571 }
1572
1572
1573 #graph {
1573 #graph {
1574 overflow:hidden;
1574 overflow:hidden;
1575 }
1575 }
1576
1576
1577 #graph_nodes {
1577 #graph_nodes {
1578 width:160px;
1578 width:160px;
1579 float:left;
1579 float:left;
1580 margin-left:-50px;
1580 margin-left:-50px;
1581 margin-top:5px;
1581 margin-top:5px;
1582 }
1582 }
1583
1583
1584 #graph_content {
1584 #graph_content {
1585 width:800px;
1585 width:800px;
1586 float:left;
1586 float:left;
1587 }
1587 }
1588
1588
1589 #graph_content .container_header {
1589 #graph_content .container_header {
1590 border:1px solid #CCC;
1590 border:1px solid #CCC;
1591 padding:10px;
1591 padding:10px;
1592 }
1592 }
1593 #graph_content #rev_range_container{
1593 #graph_content #rev_range_container{
1594 padding:10px 0px;
1594 padding:10px 0px;
1595 }
1595 }
1596 #graph_content .container {
1596 #graph_content .container {
1597 border-bottom:1px solid #CCC;
1597 border-bottom:1px solid #CCC;
1598 border-left:1px solid #CCC;
1598 border-left:1px solid #CCC;
1599 border-right:1px solid #CCC;
1599 border-right:1px solid #CCC;
1600 min-height:80px;
1600 min-height:80px;
1601 overflow:hidden;
1601 overflow:hidden;
1602 font-size:1.2em;
1602 font-size:1.2em;
1603 }
1603 }
1604
1604
1605 #graph_content .container .right {
1605 #graph_content .container .right {
1606 float:right;
1606 float:right;
1607 width:28%;
1607 width:28%;
1608 text-align:right;
1608 text-align:right;
1609 padding-bottom:5px;
1609 padding-bottom:5px;
1610 }
1610 }
1611
1611
1612 #graph_content .container .left .date {
1612 #graph_content .container .left .date {
1613 font-weight:700;
1613 font-weight:700;
1614 padding-bottom:5px;
1614 padding-bottom:5px;
1615 }
1615 }
1616 #graph_content .container .left .date span{
1616 #graph_content .container .left .date span{
1617 vertical-align: text-top;
1617 vertical-align: text-top;
1618 }
1618 }
1619
1619
1620 #graph_content .container .left .message {
1620 #graph_content .container .left .message {
1621 font-size:100%;
1621 font-size:100%;
1622 padding-top:3px;
1622 padding-top:3px;
1623 white-space:pre-wrap;
1623 white-space:pre-wrap;
1624 }
1624 }
1625
1625
1626 .right div {
1626 .right div {
1627 clear:both;
1627 clear:both;
1628 }
1628 }
1629
1629
1630 .right .changes .added,.changed,.removed {
1630 .right .changes .added,.changed,.removed {
1631 border:1px solid #DDD;
1631 border:1px solid #DDD;
1632 display:block;
1632 display:block;
1633 float:right;
1633 float:right;
1634 text-align:center;
1634 text-align:center;
1635 min-width:15px;
1635 min-width:15px;
1636 cursor: help;
1636 cursor: help;
1637 }
1637 }
1638
1638
1639 .right .changes .added {
1639 .right .changes .added {
1640 background:#BFB;
1640 background:#BFB;
1641 }
1641 }
1642
1642
1643 .right .changes .changed {
1643 .right .changes .changed {
1644 background:#FD8;
1644 background:#FD8;
1645 }
1645 }
1646
1646
1647 .right .changes .removed {
1647 .right .changes .removed {
1648 background:#F88;
1648 background:#F88;
1649 }
1649 }
1650
1650
1651 .right .merge {
1651 .right .merge {
1652 vertical-align:top;
1652 vertical-align:top;
1653 font-size:0.75em;
1653 font-size:0.75em;
1654 font-weight:700;
1654 font-weight:700;
1655 }
1655 }
1656
1656
1657 .right .parent {
1657 .right .parent {
1658 font-size:90%;
1658 font-size:90%;
1659 font-family:monospace;
1659 font-family:monospace;
1660 }
1660 }
1661
1661
1662 .right .logtags .branchtag {
1662 .right .logtags .branchtag {
1663 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1663 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1664 display:block;
1664 display:block;
1665 font-size:0.8em;
1665 font-size:0.8em;
1666 padding:11px 16px 0 0;
1666 padding:11px 16px 0 0;
1667 }
1667 }
1668
1668
1669 .right .logtags .tagtag {
1669 .right .logtags .tagtag {
1670 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1670 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1671 display:block;
1671 display:block;
1672 font-size:0.8em;
1672 font-size:0.8em;
1673 padding:11px 16px 0 0;
1673 padding:11px 16px 0 0;
1674 }
1674 }
1675
1675
1676 div.browserblock {
1676 div.browserblock {
1677 overflow:hidden;
1677 overflow:hidden;
1678 border:1px solid #ccc;
1678 border:1px solid #ccc;
1679 background:#f8f8f8;
1679 background:#f8f8f8;
1680 font-size:100%;
1680 font-size:100%;
1681 line-height:125%;
1681 line-height:125%;
1682 padding:0;
1682 padding:0;
1683 }
1683 }
1684
1684
1685 div.browserblock .browser-header {
1685 div.browserblock .browser-header {
1686 background:#FFF;
1686 background:#FFF;
1687 padding:10px 0px 35px 0px;
1687 padding:10px 0px 35px 0px;
1688 width: 100%;
1688 width: 100%;
1689 }
1689 }
1690 div.browserblock .browser-nav {
1690 div.browserblock .browser-nav {
1691 float:left
1691 float:left
1692 }
1692 }
1693
1693
1694 div.browserblock .browser-branch {
1694 div.browserblock .browser-branch {
1695 padding:10px 0 0 0;
1695 padding:10px 0 0 0;
1696 float:left;
1696 float:left;
1697 }
1697 }
1698 div.browserblock .browser-branch label {
1698 div.browserblock .browser-branch label {
1699 color:#4A4A4A;
1699 color:#4A4A4A;
1700 vertical-align:text-top;
1700 vertical-align:text-top;
1701 }
1701 }
1702
1702
1703 div.browserblock .browser-header span {
1703 div.browserblock .browser-header span {
1704 margin-left:25px;
1704 margin-left:25px;
1705 font-weight:700;
1705 font-weight:700;
1706 }
1706 }
1707
1707
1708 div.browserblock .browser-body {
1708 div.browserblock .browser-body {
1709 background:#EEE;
1709 background:#EEE;
1710 border-top:1px solid #CCC;
1710 border-top:1px solid #CCC;
1711 }
1711 }
1712
1712
1713 table.code-browser {
1713 table.code-browser {
1714 border-collapse:collapse;
1714 border-collapse:collapse;
1715 width:100%;
1715 width:100%;
1716 }
1716 }
1717
1717
1718 table.code-browser tr {
1718 table.code-browser tr {
1719 margin:3px;
1719 margin:3px;
1720 }
1720 }
1721
1721
1722 table.code-browser thead th {
1722 table.code-browser thead th {
1723 background-color:#EEE;
1723 background-color:#EEE;
1724 height:20px;
1724 height:20px;
1725 font-size:1.1em;
1725 font-size:1.1em;
1726 font-weight:700;
1726 font-weight:700;
1727 text-align:left;
1727 text-align:left;
1728 padding-left:10px;
1728 padding-left:10px;
1729 }
1729 }
1730
1730
1731 table.code-browser tbody td {
1731 table.code-browser tbody td {
1732 padding-left:10px;
1732 padding-left:10px;
1733 height:20px;
1733 height:20px;
1734 }
1734 }
1735
1735
1736 table.code-browser .browser-file {
1736 table.code-browser .browser-file {
1737 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1737 background:url("../images/icons/document_16.png") no-repeat scroll 3px;
1738 height:16px;
1738 height:16px;
1739 padding-left:20px;
1739 padding-left:20px;
1740 text-align:left;
1740 text-align:left;
1741 }
1741 }
1742 .diffblock .changeset_file{
1742 .diffblock .changeset_file{
1743 background:url("../images/icons/file.png") no-repeat scroll 3px;
1743 background:url("../images/icons/file.png") no-repeat scroll 3px;
1744 height:16px;
1744 height:16px;
1745 padding-left:22px;
1745 padding-left:22px;
1746 text-align:left;
1746 text-align:left;
1747 font-size: 14px;
1747 font-size: 14px;
1748 }
1748 }
1749
1749
1750 .diffblock .changeset_header{
1750 .diffblock .changeset_header{
1751 margin-left: 6px !important;
1751 margin-left: 6px !important;
1752 }
1752 }
1753
1753
1754 table.code-browser .browser-dir {
1754 table.code-browser .browser-dir {
1755 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1755 background:url("../images/icons/folder_16.png") no-repeat scroll 3px;
1756 height:16px;
1756 height:16px;
1757 padding-left:20px;
1757 padding-left:20px;
1758 text-align:left;
1758 text-align:left;
1759 }
1759 }
1760
1760
1761 .box .search {
1761 .box .search {
1762 clear:both;
1762 clear:both;
1763 overflow:hidden;
1763 overflow:hidden;
1764 margin:0;
1764 margin:0;
1765 padding:0 20px 10px;
1765 padding:0 20px 10px;
1766 }
1766 }
1767
1767
1768 .box .search div.search_path {
1768 .box .search div.search_path {
1769 background:none repeat scroll 0 0 #EEE;
1769 background:none repeat scroll 0 0 #EEE;
1770 border:1px solid #CCC;
1770 border:1px solid #CCC;
1771 color:blue;
1771 color:blue;
1772 margin-bottom:10px;
1772 margin-bottom:10px;
1773 padding:10px 0;
1773 padding:10px 0;
1774 }
1774 }
1775
1775
1776 .box .search div.search_path div.link {
1776 .box .search div.search_path div.link {
1777 font-weight:700;
1777 font-weight:700;
1778 margin-left:25px;
1778 margin-left:25px;
1779 }
1779 }
1780
1780
1781 .box .search div.search_path div.link a {
1781 .box .search div.search_path div.link a {
1782 color:#003367;
1782 color:#003367;
1783 cursor:pointer;
1783 cursor:pointer;
1784 text-decoration:none;
1784 text-decoration:none;
1785 }
1785 }
1786
1786
1787 #path_unlock {
1787 #path_unlock {
1788 color:red;
1788 color:red;
1789 font-size:1.2em;
1789 font-size:1.2em;
1790 padding-left:4px;
1790 padding-left:4px;
1791 }
1791 }
1792
1792
1793 .info_box * {
1793 .info_box * {
1794 background:url("../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1794 background:url("../images/pager.png") repeat-x scroll 0 0 #EBEBEB;
1795 color:#4A4A4A;
1795 color:#4A4A4A;
1796 font-weight:700;
1796 font-weight:700;
1797 height:1%;
1797 height:1%;
1798 display:inline;
1798 display:inline;
1799 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1799 border-color:#DEDEDE #C4C4C4 #C4C4C4 #CFCFCF;
1800 border-style:solid;
1800 border-style:solid;
1801 border-width:1px;
1801 border-width:1px;
1802 padding:4px 6px;
1802 padding:4px 6px;
1803 }
1803 }
1804
1804
1805 .info_box span {
1805 .info_box span {
1806 margin-left:3px;
1806 margin-left:3px;
1807 margin-right:3px;
1807 margin-right:3px;
1808 }
1808 }
1809
1809
1810 .info_box input#at_rev {
1810 .info_box input#at_rev {
1811 text-align:center;
1811 text-align:center;
1812 padding:5px 3px 3px 2px;
1812 padding:5px 3px 3px 2px;
1813 }
1813 }
1814
1814
1815 .info_box input#view {
1815 .info_box input#view {
1816 text-align:center;
1816 text-align:center;
1817 padding:4px 3px 2px 2px;
1817 padding:4px 3px 2px 2px;
1818 }
1818 }
1819
1819
1820 .yui-overlay,.yui-panel-container {
1820 .yui-overlay,.yui-panel-container {
1821 visibility:hidden;
1821 visibility:hidden;
1822 position:absolute;
1822 position:absolute;
1823 z-index:2;
1823 z-index:2;
1824 }
1824 }
1825
1825
1826 .yui-tt {
1826 .yui-tt {
1827 visibility:hidden;
1827 visibility:hidden;
1828 position:absolute;
1828 position:absolute;
1829 color:#666;
1829 color:#666;
1830 background-color:#FFF;
1830 background-color:#FFF;
1831 font-family:arial, helvetica, verdana, sans-serif;
1831 font-family:arial, helvetica, verdana, sans-serif;
1832 border:2px solid #003367;
1832 border:2px solid #003367;
1833 font:100% sans-serif;
1833 font:100% sans-serif;
1834 width:auto;
1834 width:auto;
1835 opacity:1px;
1835 opacity:1px;
1836 padding:8px;
1836 padding:8px;
1837 white-space: pre;
1837 white-space: pre;
1838 -webkit-border-radius: 8px 8px 8px 8px;
1838 -webkit-border-radius: 8px 8px 8px 8px;
1839 -khtml-border-radius: 8px 8px 8px 8px;
1839 -khtml-border-radius: 8px 8px 8px 8px;
1840 -moz-border-radius: 8px 8px 8px 8px;
1840 -moz-border-radius: 8px 8px 8px 8px;
1841 border-radius: 8px 8px 8px 8px;
1841 border-radius: 8px 8px 8px 8px;
1842 }
1842 }
1843
1843
1844 .ac {
1844 .ac {
1845 vertical-align:top;
1845 vertical-align:top;
1846 }
1846 }
1847
1847
1848 .ac .yui-ac {
1848 .ac .yui-ac {
1849 position:relative;
1849 position:relative;
1850 font-family:arial;
1850 font-family:arial;
1851 font-size:100%;
1851 font-size:100%;
1852 }
1852 }
1853
1853
1854 .ac .perm_ac {
1854 .ac .perm_ac {
1855 width:15em;
1855 width:15em;
1856 }
1856 }
1857
1857
1858 .ac .yui-ac-input {
1858 .ac .yui-ac-input {
1859 width:100%;
1859 width:100%;
1860 }
1860 }
1861
1861
1862 .ac .yui-ac-container {
1862 .ac .yui-ac-container {
1863 position:absolute;
1863 position:absolute;
1864 top:1.6em;
1864 top:1.6em;
1865 width:100%;
1865 width:100%;
1866 }
1866 }
1867
1867
1868 .ac .yui-ac-content {
1868 .ac .yui-ac-content {
1869 position:absolute;
1869 position:absolute;
1870 width:100%;
1870 width:100%;
1871 border:1px solid gray;
1871 border:1px solid gray;
1872 background:#fff;
1872 background:#fff;
1873 overflow:hidden;
1873 overflow:hidden;
1874 z-index:9050;
1874 z-index:9050;
1875 }
1875 }
1876
1876
1877 .ac .yui-ac-shadow {
1877 .ac .yui-ac-shadow {
1878 position:absolute;
1878 position:absolute;
1879 width:100%;
1879 width:100%;
1880 background:#000;
1880 background:#000;
1881 -moz-opacity:0.1px;
1881 -moz-opacity:0.1px;
1882 opacity:.10;
1882 opacity:.10;
1883 filter:alpha(opacity = 10);
1883 filter:alpha(opacity = 10);
1884 z-index:9049;
1884 z-index:9049;
1885 margin:.3em;
1885 margin:.3em;
1886 }
1886 }
1887
1887
1888 .ac .yui-ac-content ul {
1888 .ac .yui-ac-content ul {
1889 width:100%;
1889 width:100%;
1890 margin:0;
1890 margin:0;
1891 padding:0;
1891 padding:0;
1892 }
1892 }
1893
1893
1894 .ac .yui-ac-content li {
1894 .ac .yui-ac-content li {
1895 cursor:default;
1895 cursor:default;
1896 white-space:nowrap;
1896 white-space:nowrap;
1897 margin:0;
1897 margin:0;
1898 padding:2px 5px;
1898 padding:2px 5px;
1899 }
1899 }
1900
1900
1901 .ac .yui-ac-content li.yui-ac-prehighlight {
1901 .ac .yui-ac-content li.yui-ac-prehighlight {
1902 background:#B3D4FF;
1902 background:#B3D4FF;
1903 }
1903 }
1904
1904
1905 .ac .yui-ac-content li.yui-ac-highlight {
1905 .ac .yui-ac-content li.yui-ac-highlight {
1906 background:#556CB5;
1906 background:#556CB5;
1907 color:#FFF;
1907 color:#FFF;
1908 }
1908 }
1909
1909
1910 .follow{
1910 .follow{
1911 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1911 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1912 height: 16px;
1912 height: 16px;
1913 width: 20px;
1913 width: 20px;
1914 cursor: pointer;
1914 cursor: pointer;
1915 display: block;
1915 display: block;
1916 float: right;
1916 float: right;
1917 margin-top: 2px;
1917 margin-top: 2px;
1918 }
1918 }
1919
1919
1920 .following{
1920 .following{
1921 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
1921 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
1922 height: 16px;
1922 height: 16px;
1923 width: 20px;
1923 width: 20px;
1924 cursor: pointer;
1924 cursor: pointer;
1925 display: block;
1925 display: block;
1926 float: right;
1926 float: right;
1927 margin-top: 2px;
1927 margin-top: 2px;
1928 }
1928 }
1929
1929
1930 .currently_following{
1930 .currently_following{
1931 padding-left: 10px;
1931 padding-left: 10px;
1932 padding-bottom:5px;
1932 padding-bottom:5px;
1933 }
1933 }
1934
1934
1935 .add_icon {
1935 .add_icon {
1936 background:url("../images/icons/add.png") no-repeat scroll 3px;
1936 background:url("../images/icons/add.png") no-repeat scroll 3px;
1937 height:16px;
1937 height:16px;
1938 padding-left:20px;
1938 padding-left:20px;
1939 padding-top:1px;
1939 padding-top:1px;
1940 text-align:left;
1940 text-align:left;
1941 }
1941 }
1942
1942
1943 .edit_icon {
1943 .edit_icon {
1944 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1944 background:url("../images/icons/folder_edit.png") no-repeat scroll 3px;
1945 height:16px;
1945 height:16px;
1946 padding-left:20px;
1946 padding-left:20px;
1947 padding-top:1px;
1947 padding-top:1px;
1948 text-align:left;
1948 text-align:left;
1949 }
1949 }
1950
1950
1951 .delete_icon {
1951 .delete_icon {
1952 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1952 background:url("../images/icons/delete.png") no-repeat scroll 3px;
1953 height:16px;
1953 height:16px;
1954 padding-left:20px;
1954 padding-left:20px;
1955 padding-top:1px;
1955 padding-top:1px;
1956 text-align:left;
1956 text-align:left;
1957 }
1957 }
1958
1958
1959 .refresh_icon {
1959 .refresh_icon {
1960 background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
1960 background:url("../images/icons/arrow_refresh.png") no-repeat scroll 3px;
1961 height:16px;
1961 height:16px;
1962 padding-left:20px;
1962 padding-left:20px;
1963 padding-top:1px;
1963 padding-top:1px;
1964 text-align:left;
1964 text-align:left;
1965 }
1965 }
1966
1966
1967 .pull_icon {
1967 .pull_icon {
1968 background:url("../images/icons/connect.png") no-repeat scroll 3px;
1968 background:url("../images/icons/connect.png") no-repeat scroll 3px;
1969 height:16px;
1969 height:16px;
1970 padding-left:20px;
1970 padding-left:20px;
1971 padding-top:1px;
1971 padding-top:1px;
1972 text-align:left;
1972 text-align:left;
1973 }
1973 }
1974
1974
1975 .rss_icon {
1975 .rss_icon {
1976 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1976 background:url("../images/icons/rss_16.png") no-repeat scroll 3px;
1977 height:16px;
1977 height:16px;
1978 padding-left:20px;
1978 padding-left:20px;
1979 padding-top:1px;
1979 padding-top:1px;
1980 text-align:left;
1980 text-align:left;
1981 }
1981 }
1982
1982
1983 .atom_icon {
1983 .atom_icon {
1984 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1984 background:url("../images/icons/atom.png") no-repeat scroll 3px;
1985 height:16px;
1985 height:16px;
1986 padding-left:20px;
1986 padding-left:20px;
1987 padding-top:1px;
1987 padding-top:1px;
1988 text-align:left;
1988 text-align:left;
1989 }
1989 }
1990
1990
1991 .archive_icon {
1991 .archive_icon {
1992 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1992 background:url("../images/icons/compress.png") no-repeat scroll 3px;
1993 height:16px;
1993 height:16px;
1994 padding-left:20px;
1994 padding-left:20px;
1995 text-align:left;
1995 text-align:left;
1996 padding-top:1px;
1996 padding-top:1px;
1997 }
1997 }
1998 .start_following_icon {
1998 .start_following_icon {
1999 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
1999 background:url("../images/icons/heart_add.png") no-repeat scroll 3px;
2000 height:16px;
2000 height:16px;
2001 padding-left:20px;
2001 padding-left:20px;
2002 text-align:left;
2002 text-align:left;
2003 padding-top:1px;
2003 padding-top:1px;
2004 }
2004 }
2005 .stop_following_icon {
2005 .stop_following_icon {
2006 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
2006 background:url("../images/icons/heart_delete.png") no-repeat scroll 3px;
2007 height:16px;
2007 height:16px;
2008 padding-left:20px;
2008 padding-left:20px;
2009 text-align:left;
2009 text-align:left;
2010 padding-top:1px;
2010 padding-top:1px;
2011 }
2011 }
2012
2012
2013 .action_button {
2013 .action_button {
2014 border:0;
2014 border:0;
2015 display:block;
2015 display:block;
2016 }
2016 }
2017
2017
2018 .action_button:hover {
2018 .action_button:hover {
2019 border:0;
2019 border:0;
2020 text-decoration:underline;
2020 text-decoration:underline;
2021 cursor:pointer;
2021 cursor:pointer;
2022 }
2022 }
2023
2023
2024 #switch_repos {
2024 #switch_repos {
2025 position:absolute;
2025 position:absolute;
2026 height:25px;
2026 height:25px;
2027 z-index:1;
2027 z-index:1;
2028 }
2028 }
2029
2029
2030 #switch_repos select {
2030 #switch_repos select {
2031 min-width:150px;
2031 min-width:150px;
2032 max-height:250px;
2032 max-height:250px;
2033 z-index:1;
2033 z-index:1;
2034 }
2034 }
2035
2035
2036 .breadcrumbs {
2036 .breadcrumbs {
2037 border:medium none;
2037 border:medium none;
2038 color:#FFF;
2038 color:#FFF;
2039 float:left;
2039 float:left;
2040 text-transform:uppercase;
2040 text-transform:uppercase;
2041 font-weight:700;
2041 font-weight:700;
2042 font-size:14px;
2042 font-size:14px;
2043 margin:0;
2043 margin:0;
2044 padding:11px 0 11px 10px;
2044 padding:11px 0 11px 10px;
2045 }
2045 }
2046
2046
2047 .breadcrumbs a {
2047 .breadcrumbs a {
2048 color:#FFF;
2048 color:#FFF;
2049 }
2049 }
2050
2050
2051 .flash_msg ul {
2051 .flash_msg ul {
2052 margin:0;
2052 margin:0;
2053 padding:0 0 10px;
2053 padding:0 0 10px;
2054 }
2054 }
2055
2055
2056 .error_msg {
2056 .error_msg {
2057 background-color:#FFCFCF;
2057 background-color:#FFCFCF;
2058 background-image:url("../images/icons/error_msg.png");
2058 background-image:url("../images/icons/error_msg.png");
2059 border:1px solid #FF9595;
2059 border:1px solid #FF9595;
2060 color:#C30;
2060 color:#C30;
2061 }
2061 }
2062
2062
2063 .warning_msg {
2063 .warning_msg {
2064 background-color:#FFFBCC;
2064 background-color:#FFFBCC;
2065 background-image:url("../images/icons/warning_msg.png");
2065 background-image:url("../images/icons/warning_msg.png");
2066 border:1px solid #FFF35E;
2066 border:1px solid #FFF35E;
2067 color:#C69E00;
2067 color:#C69E00;
2068 }
2068 }
2069
2069
2070 .success_msg {
2070 .success_msg {
2071 background-color:#D5FFCF;
2071 background-color:#D5FFCF;
2072 background-image:url("../images/icons/success_msg.png");
2072 background-image:url("../images/icons/success_msg.png");
2073 border:1px solid #97FF88;
2073 border:1px solid #97FF88;
2074 color:#090;
2074 color:#090;
2075 }
2075 }
2076
2076
2077 .notice_msg {
2077 .notice_msg {
2078 background-color:#DCE3FF;
2078 background-color:#DCE3FF;
2079 background-image:url("../images/icons/notice_msg.png");
2079 background-image:url("../images/icons/notice_msg.png");
2080 border:1px solid #93A8FF;
2080 border:1px solid #93A8FF;
2081 color:#556CB5;
2081 color:#556CB5;
2082 }
2082 }
2083
2083
2084 .success_msg,.error_msg,.notice_msg,.warning_msg {
2084 .success_msg,.error_msg,.notice_msg,.warning_msg {
2085 background-position:10px center;
2085 background-position:10px center;
2086 background-repeat:no-repeat;
2086 background-repeat:no-repeat;
2087 font-size:12px;
2087 font-size:12px;
2088 font-weight:700;
2088 font-weight:700;
2089 min-height:14px;
2089 min-height:14px;
2090 line-height:14px;
2090 line-height:14px;
2091 margin-bottom:0;
2091 margin-bottom:0;
2092 margin-top:0;
2092 margin-top:0;
2093 display:block;
2093 display:block;
2094 overflow:auto;
2094 overflow:auto;
2095 padding:6px 10px 6px 40px;
2095 padding:6px 10px 6px 40px;
2096 }
2096 }
2097
2097
2098 #msg_close {
2098 #msg_close {
2099 background:transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
2099 background:transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
2100 cursor:pointer;
2100 cursor:pointer;
2101 height:16px;
2101 height:16px;
2102 position:absolute;
2102 position:absolute;
2103 right:5px;
2103 right:5px;
2104 top:5px;
2104 top:5px;
2105 width:16px;
2105 width:16px;
2106 }
2106 }
2107
2107
2108 div#legend_container table,div#legend_choices table {
2108 div#legend_container table,div#legend_choices table {
2109 width:auto !important;
2109 width:auto !important;
2110 }
2110 }
2111
2111
2112 table#permissions_manage {
2112 table#permissions_manage {
2113 width:0 !important;
2113 width:0 !important;
2114 }
2114 }
2115
2115
2116 table#permissions_manage span.private_repo_msg {
2116 table#permissions_manage span.private_repo_msg {
2117 font-size:0.8em;
2117 font-size:0.8em;
2118 opacity:0.6px;
2118 opacity:0.6px;
2119 }
2119 }
2120
2120
2121 table#permissions_manage td.private_repo_msg {
2121 table#permissions_manage td.private_repo_msg {
2122 font-size:0.8em;
2122 font-size:0.8em;
2123 }
2123 }
2124
2124
2125 table#permissions_manage tr#add_perm_input td {
2125 table#permissions_manage tr#add_perm_input td {
2126 vertical-align:middle;
2126 vertical-align:middle;
2127 }
2127 }
2128
2128
2129 div.gravatar {
2129 div.gravatar {
2130 background-color:#FFF;
2130 background-color:#FFF;
2131 border:1px solid #D0D0D0;
2131 border:1px solid #D0D0D0;
2132 float:left;
2132 float:left;
2133 margin-right:0.7em;
2133 margin-right:0.7em;
2134 padding:2px 2px 0;
2134 padding:2px 2px 0;
2135 }
2135 }
2136
2136
2137 #header,#content,#footer {
2137 #header,#content,#footer {
2138 min-width:1024px;
2138 min-width:1024px;
2139 }
2139 }
2140
2140
2141 #content {
2141 #content {
2142 min-height:100%;
2142 min-height:100%;
2143 clear:both;
2143 clear:both;
2144 overflow:hidden;
2144 overflow:hidden;
2145 padding:14px 30px;
2145 padding:14px 30px;
2146 }
2146 }
2147
2147
2148 #content div.box div.title div.search {
2148 #content div.box div.title div.search {
2149 background:url("../images/title_link.png") no-repeat top left;
2149 background:url("../images/title_link.png") no-repeat top left;
2150 border-left:1px solid #316293;
2150 border-left:1px solid #316293;
2151 }
2151 }
2152
2152
2153 #content div.box div.title div.search div.input input {
2153 #content div.box div.title div.search div.input input {
2154 border:1px solid #316293;
2154 border:1px solid #316293;
2155 }
2155 }
2156
2156
2157 #content div.box div.title div.search div.button input.ui-button {
2157 #content div.box div.title div.search div.button input.ui-button {
2158 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2158 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2159 border:1px solid #316293;
2159 border:1px solid #316293;
2160 border-left:none;
2160 border-left:none;
2161 color:#FFF;
2161 color:#FFF;
2162 }
2162 }
2163
2163
2164 #content div.box div.title div.search div.button input.ui-state-hover {
2164 #content div.box div.title div.search div.button input.ui-state-hover {
2165 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2165 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2166 border:1px solid #316293;
2166 border:1px solid #316293;
2167 border-left:none;
2167 border-left:none;
2168 color:#FFF;
2168 color:#FFF;
2169 }
2169 }
2170
2170
2171 #content div.box div.form div.fields div.field div.highlight .ui-button {
2171 #content div.box div.form div.fields div.field div.highlight .ui-button {
2172 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2172 background:#4e85bb url("../images/button_highlight.png") repeat-x;
2173 border-top:1px solid #5c91a4;
2173 border-top:1px solid #5c91a4;
2174 border-left:1px solid #2a6f89;
2174 border-left:1px solid #2a6f89;
2175 border-right:1px solid #2b7089;
2175 border-right:1px solid #2b7089;
2176 border-bottom:1px solid #1a6480;
2176 border-bottom:1px solid #1a6480;
2177 color:#fff;
2177 color:#fff;
2178 }
2178 }
2179
2179
2180 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
2180 #content div.box div.form div.fields div.field div.highlight .ui-state-hover {
2181 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2181 background:#46a0c1 url("../images/button_highlight_selected.png") repeat-x;
2182 border-top:1px solid #78acbf;
2182 border-top:1px solid #78acbf;
2183 border-left:1px solid #34819e;
2183 border-left:1px solid #34819e;
2184 border-right:1px solid #35829f;
2184 border-right:1px solid #35829f;
2185 border-bottom:1px solid #257897;
2185 border-bottom:1px solid #257897;
2186 color:#fff;
2186 color:#fff;
2187 }
2187 }
2188
2188
2189 ins,div.options a:hover {
2189 ins,div.options a:hover {
2190 text-decoration:none;
2190 text-decoration:none;
2191 }
2191 }
2192
2192
2193 img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
2193 img,#header #header-inner #quick li a:hover span.normal,#header #header-inner #quick li ul li.last,#content div.box div.form div.fields div.field div.textarea table td table td a,#clone_url {
2194 border:none;
2194 border:none;
2195 }
2195 }
2196
2196
2197 img.icon,.right .merge img {
2197 img.icon,.right .merge img {
2198 vertical-align:bottom;
2198 vertical-align:bottom;
2199 }
2199 }
2200
2200
2201 #header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
2201 #header ul#logged-user,#content div.box div.title ul.links,#content div.box div.message div.dismiss,#content div.box div.traffic div.legend ul {
2202 float:right;
2202 float:right;
2203 margin:0;
2203 margin:0;
2204 padding:0;
2204 padding:0;
2205 }
2205 }
2206
2206
2207 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
2207 #header #header-inner #home,#header #header-inner #logo,#content div.box ul.left,#content div.box ol.left,#content div.box div.pagination-left,div#commit_history,div#legend_data,div#legend_container,div#legend_choices {
2208 float:left;
2208 float:left;
2209 }
2209 }
2210
2210
2211 #header #header-inner #quick li:hover ul ul,#header #header-inner #quick li:hover ul ul ul,#header #header-inner #quick li:hover ul ul ul ul,#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow {
2211 #header #header-inner #quick li:hover ul ul,#header #header-inner #quick li:hover ul ul ul,#header #header-inner #quick li:hover ul ul ul ul,#content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow {
2212 display:none;
2212 display:none;
2213 }
2213 }
2214
2214
2215 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded {
2215 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded {
2216 display:block;
2216 display:block;
2217 }
2217 }
2218
2218
2219 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2219 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2220 color:#bfe3ff;
2220 color:#bfe3ff;
2221 }
2221 }
2222
2222
2223 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal {
2223 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal {
2224 margin:10px 24px 10px 44px;
2224 margin:10px 24px 10px 44px;
2225 }
2225 }
2226
2226
2227 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2227 #content div.box div.form,#content div.box div.table,#content div.box div.traffic {
2228 clear:both;
2228 clear:both;
2229 overflow:hidden;
2229 overflow:hidden;
2230 margin:0;
2230 margin:0;
2231 padding:0 20px 10px;
2231 padding:0 20px 10px;
2232 }
2232 }
2233
2233
2234 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2234 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields {
2235 clear:both;
2235 clear:both;
2236 overflow:hidden;
2236 overflow:hidden;
2237 margin:0;
2237 margin:0;
2238 padding:0;
2238 padding:0;
2239 }
2239 }
2240
2240
2241 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span {
2241 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span {
2242 height:1%;
2242 height:1%;
2243 display:block;
2243 display:block;
2244 color:#363636;
2244 color:#363636;
2245 margin:0;
2245 margin:0;
2246 padding:2px 0 0;
2246 padding:2px 0 0;
2247 }
2247 }
2248
2248
2249 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error {
2249 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error {
2250 background:#FBE3E4;
2250 background:#FBE3E4;
2251 border-top:1px solid #e1b2b3;
2251 border-top:1px solid #e1b2b3;
2252 border-left:1px solid #e1b2b3;
2252 border-left:1px solid #e1b2b3;
2253 border-right:1px solid #FBC2C4;
2253 border-right:1px solid #FBC2C4;
2254 border-bottom:1px solid #FBC2C4;
2254 border-bottom:1px solid #FBC2C4;
2255 }
2255 }
2256
2256
2257 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success {
2257 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success {
2258 background:#E6EFC2;
2258 background:#E6EFC2;
2259 border-top:1px solid #cebb98;
2259 border-top:1px solid #cebb98;
2260 border-left:1px solid #cebb98;
2260 border-left:1px solid #cebb98;
2261 border-right:1px solid #c6d880;
2261 border-right:1px solid #c6d880;
2262 border-bottom:1px solid #c6d880;
2262 border-bottom:1px solid #c6d880;
2263 }
2263 }
2264
2264
2265 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input {
2265 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input {
2266 margin:0;
2266 margin:0;
2267 }
2267 }
2268
2268
2269 #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios{
2269 #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios{
2270 margin:0 0 0 0px !important;
2270 margin:0 0 0 0px !important;
2271 padding:0;
2271 padding:0;
2272 }
2272 }
2273
2273
2274 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios {
2274 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios {
2275 margin:0 0 0 200px;
2275 margin:0 0 0 200px;
2276 padding:0;
2276 padding:0;
2277 }
2277 }
2278
2278
2279
2279
2280 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover {
2280 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover {
2281 color:#000;
2281 color:#000;
2282 text-decoration:none;
2282 text-decoration:none;
2283 }
2283 }
2284
2284
2285 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2285 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus {
2286 border:1px solid #666;
2286 border:1px solid #666;
2287 }
2287 }
2288
2288
2289 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio {
2289 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio {
2290 clear:both;
2290 clear:both;
2291 overflow:hidden;
2291 overflow:hidden;
2292 margin:0;
2292 margin:0;
2293 padding:8px 0 2px;
2293 padding:8px 0 2px;
2294 }
2294 }
2295
2295
2296 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
2296 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input {
2297 float:left;
2297 float:left;
2298 margin:0;
2298 margin:0;
2299 }
2299 }
2300
2300
2301 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label {
2301 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label {
2302 height:1%;
2302 height:1%;
2303 display:block;
2303 display:block;
2304 float:left;
2304 float:left;
2305 margin:2px 0 0 4px;
2305 margin:2px 0 0 4px;
2306 }
2306 }
2307
2307
2308 div.form div.fields div.field div.button input,#content div.box div.form div.fields div.buttons input,div.form div.fields div.buttons input,#content div.box div.action div.button input {
2308 div.form div.fields div.field div.button input,#content div.box div.form div.fields div.buttons input,div.form div.fields div.buttons input,#content div.box div.action div.button input {
2309 color:#000;
2309 color:#000;
2310 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2310 font-family:Lucida Grande, Verdana, Lucida Sans Regular, Lucida Sans Unicode, Arial, sans-serif;
2311 font-size:11px;
2311 font-size:11px;
2312 font-weight:700;
2312 font-weight:700;
2313 margin:0;
2313 margin:0;
2314 }
2314 }
2315
2315
2316 div.form div.fields div.field div.button .ui-button,#content div.box div.form div.fields div.buttons input.ui-button {
2316 div.form div.fields div.field div.button .ui-button,#content div.box div.form div.fields div.buttons input.ui-button {
2317 background:#e5e3e3 url("../images/button.png") repeat-x;
2317 background:#e5e3e3 url("../images/button.png") repeat-x;
2318 border-top:1px solid #DDD;
2318 border-top:1px solid #DDD;
2319 border-left:1px solid #c6c6c6;
2319 border-left:1px solid #c6c6c6;
2320 border-right:1px solid #DDD;
2320 border-right:1px solid #DDD;
2321 border-bottom:1px solid #c6c6c6;
2321 border-bottom:1px solid #c6c6c6;
2322 color:#515151;
2322 color:#515151;
2323 outline:none;
2323 outline:none;
2324 margin:0;
2324 margin:0;
2325 padding:6px 12px;
2325 padding:6px 12px;
2326 }
2326 }
2327
2327
2328 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2328 div.form div.fields div.field div.button .ui-state-hover,#content div.box div.form div.fields div.buttons input.ui-state-hover {
2329 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2329 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2330 border-top:1px solid #ccc;
2330 border-top:1px solid #ccc;
2331 border-left:1px solid #bebebe;
2331 border-left:1px solid #bebebe;
2332 border-right:1px solid #b1b1b1;
2332 border-right:1px solid #b1b1b1;
2333 border-bottom:1px solid #afafaf;
2333 border-bottom:1px solid #afafaf;
2334 color:#515151;
2334 color:#515151;
2335 outline:none;
2335 outline:none;
2336 margin:0;
2336 margin:0;
2337 padding:6px 12px;
2337 padding:6px 12px;
2338 }
2338 }
2339
2339
2340 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2340 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight {
2341 display:inline;
2341 display:inline;
2342 }
2342 }
2343
2343
2344 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2344 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons {
2345 margin:10px 0 0 200px;
2345 margin:10px 0 0 200px;
2346 padding:0;
2346 padding:0;
2347 }
2347 }
2348
2348
2349 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons {
2349 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons {
2350 margin:10px 0 0;
2350 margin:10px 0 0;
2351 }
2351 }
2352
2352
2353 #content div.box table td.user,#content div.box table td.address {
2353 #content div.box table td.user,#content div.box table td.address {
2354 width:10%;
2354 width:10%;
2355 text-align:center;
2355 text-align:center;
2356 }
2356 }
2357
2357
2358 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link {
2358 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link {
2359 text-align:right;
2359 text-align:right;
2360 margin:6px 0 0;
2360 margin:6px 0 0;
2361 padding:0;
2361 padding:0;
2362 }
2362 }
2363
2363
2364 #content div.box div.action div.button input.ui-button,#login div.form div.fields div.buttons input.ui-button,#register div.form div.fields div.buttons input.ui-button {
2364 #content div.box div.action div.button input.ui-button,#login div.form div.fields div.buttons input.ui-button,#register div.form div.fields div.buttons input.ui-button {
2365 background:#e5e3e3 url("../images/button.png") repeat-x;
2365 background:#e5e3e3 url("../images/button.png") repeat-x;
2366 border-top:1px solid #DDD;
2366 border-top:1px solid #DDD;
2367 border-left:1px solid #c6c6c6;
2367 border-left:1px solid #c6c6c6;
2368 border-right:1px solid #DDD;
2368 border-right:1px solid #DDD;
2369 border-bottom:1px solid #c6c6c6;
2369 border-bottom:1px solid #c6c6c6;
2370 color:#515151;
2370 color:#515151;
2371 margin:0;
2371 margin:0;
2372 padding:6px 12px;
2372 padding:6px 12px;
2373 }
2373 }
2374
2374
2375 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
2375 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover {
2376 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2376 background:#b4b4b4 url("../images/button_selected.png") repeat-x;
2377 border-top:1px solid #ccc;
2377 border-top:1px solid #ccc;
2378 border-left:1px solid #bebebe;
2378 border-left:1px solid #bebebe;
2379 border-right:1px solid #b1b1b1;
2379 border-right:1px solid #b1b1b1;
2380 border-bottom:1px solid #afafaf;
2380 border-bottom:1px solid #afafaf;
2381 color:#515151;
2381 color:#515151;
2382 margin:0;
2382 margin:0;
2383 padding:6px 12px;
2383 padding:6px 12px;
2384 }
2384 }
2385
2385
2386 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2386 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results {
2387 text-align:left;
2387 text-align:left;
2388 float:left;
2388 float:left;
2389 margin:0;
2389 margin:0;
2390 padding:0;
2390 padding:0;
2391 }
2391 }
2392
2392
2393 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2393 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span {
2394 height:1%;
2394 height:1%;
2395 display:block;
2395 display:block;
2396 float:left;
2396 float:left;
2397 background:#ebebeb url("../images/pager.png") repeat-x;
2397 background:#ebebeb url("../images/pager.png") repeat-x;
2398 border-top:1px solid #dedede;
2398 border-top:1px solid #dedede;
2399 border-left:1px solid #cfcfcf;
2399 border-left:1px solid #cfcfcf;
2400 border-right:1px solid #c4c4c4;
2400 border-right:1px solid #c4c4c4;
2401 border-bottom:1px solid #c4c4c4;
2401 border-bottom:1px solid #c4c4c4;
2402 color:#4A4A4A;
2402 color:#4A4A4A;
2403 font-weight:700;
2403 font-weight:700;
2404 margin:0;
2404 margin:0;
2405 padding:6px 8px;
2405 padding:6px 8px;
2406 }
2406 }
2407
2407
2408 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2408 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled {
2409 color:#B4B4B4;
2409 color:#B4B4B4;
2410 padding:6px;
2410 padding:6px;
2411 }
2411 }
2412
2412
2413 #login,#register {
2413 #login,#register {
2414 width:520px;
2414 width:520px;
2415 margin:10% auto 0;
2415 margin:10% auto 0;
2416 padding:0;
2416 padding:0;
2417 }
2417 }
2418
2418
2419 #login div.color,#register div.color {
2419 #login div.color,#register div.color {
2420 clear:both;
2420 clear:both;
2421 overflow:hidden;
2421 overflow:hidden;
2422 background:#FFF;
2422 background:#FFF;
2423 margin:10px auto 0;
2423 margin:10px auto 0;
2424 padding:3px 3px 3px 0;
2424 padding:3px 3px 3px 0;
2425 }
2425 }
2426
2426
2427 #login div.color a,#register div.color a {
2427 #login div.color a,#register div.color a {
2428 width:20px;
2428 width:20px;
2429 height:20px;
2429 height:20px;
2430 display:block;
2430 display:block;
2431 float:left;
2431 float:left;
2432 margin:0 0 0 3px;
2432 margin:0 0 0 3px;
2433 padding:0;
2433 padding:0;
2434 }
2434 }
2435
2435
2436 #login div.title h5,#register div.title h5 {
2436 #login div.title h5,#register div.title h5 {
2437 color:#fff;
2437 color:#fff;
2438 margin:10px;
2438 margin:10px;
2439 padding:0;
2439 padding:0;
2440 }
2440 }
2441
2441
2442 #login div.form div.fields div.field,#register div.form div.fields div.field {
2442 #login div.form div.fields div.field,#register div.form div.fields div.field {
2443 clear:both;
2443 clear:both;
2444 overflow:hidden;
2444 overflow:hidden;
2445 margin:0;
2445 margin:0;
2446 padding:0 0 10px;
2446 padding:0 0 10px;
2447 }
2447 }
2448
2448
2449 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2449 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message {
2450 height:1%;
2450 height:1%;
2451 display:block;
2451 display:block;
2452 color:red;
2452 color:red;
2453 margin:8px 0 0;
2453 margin:8px 0 0;
2454 padding:0;
2454 padding:0;
2455 max-width: 320px;
2455 max-width: 320px;
2456 }
2456 }
2457
2457
2458 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2458 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label {
2459 color:#000;
2459 color:#000;
2460 font-weight:700;
2460 font-weight:700;
2461 }
2461 }
2462
2462
2463 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2463 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input {
2464 float:left;
2464 float:left;
2465 margin:0;
2465 margin:0;
2466 padding:0;
2466 padding:0;
2467 }
2467 }
2468
2468
2469 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2469 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox {
2470 margin:0 0 0 184px;
2470 margin:0 0 0 184px;
2471 padding:0;
2471 padding:0;
2472 }
2472 }
2473
2473
2474 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2474 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label {
2475 color:#565656;
2475 color:#565656;
2476 font-weight:700;
2476 font-weight:700;
2477 }
2477 }
2478
2478
2479 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2479 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input {
2480 color:#000;
2480 color:#000;
2481 font-size:1em;
2481 font-size:1em;
2482 font-weight:700;
2482 font-weight:700;
2483 font-family:Verdana, Helvetica, Sans-Serif;
2483 font-family:Verdana, Helvetica, Sans-Serif;
2484 margin:0;
2484 margin:0;
2485 }
2485 }
2486
2486
2487 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2487 #changeset_content .container .wrapper,#graph_content .container .wrapper {
2488 width:600px;
2488 width:600px;
2489 }
2489 }
2490
2490
2491 #changeset_content .container .left,#graph_content .container .left {
2491 #changeset_content .container .left,#graph_content .container .left {
2492 float:left;
2492 float:left;
2493 width:70%;
2493 width:70%;
2494 padding-left:5px;
2494 padding-left:5px;
2495 }
2495 }
2496
2496
2497 #changeset_content .container .left .date,.ac .match {
2497 #changeset_content .container .left .date,.ac .match {
2498 font-weight:700;
2498 font-weight:700;
2499 padding-top: 5px;
2499 padding-top: 5px;
2500 padding-bottom:5px;
2500 padding-bottom:5px;
2501 }
2501 }
2502
2502
2503 div#legend_container table td,div#legend_choices table td {
2503 div#legend_container table td,div#legend_choices table td {
2504 border:none !important;
2504 border:none !important;
2505 height:20px !important;
2505 height:20px !important;
2506 padding:0 !important;
2506 padding:0 !important;
2507 }
2507 }
2508
2508
2509 #q_filter{
2509 #q_filter{
2510 border:0 none;
2510 border:0 none;
2511 color:#AAAAAA;
2511 color:#AAAAAA;
2512 margin-bottom:-4px;
2512 margin-bottom:-4px;
2513 margin-top:-4px;
2513 margin-top:-4px;
2514 padding-left:3px;
2514 padding-left:3px;
2515 }
2515 }
2516
2516
@@ -1,243 +1,149 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit user')} ${c.user.username} - ${c.rhodecode_name}
5 ${_('Edit user')} ${c.user.username} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('Users'),h.url('users'))}
11 ${h.link_to(_('Users'),h.url('users'))}
12 &raquo;
12 &raquo;
13 ${_('edit')} "${c.user.username}"
13 ${_('edit')} "${c.user.username}"
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box box-left">
21 <div class="box box-left">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 <!-- end box / title -->
26 <!-- end box / title -->
27 ${h.form(url('user', id=c.user.user_id),method='put')}
27 ${h.form(url('user', id=c.user.user_id),method='put')}
28 <div class="form">
28 <div class="form">
29 <!-- fields -->
30 <div class="fields">
31 <div class="field">
29 <div class="field">
32 <div class="gravatar_box">
30 <div class="gravatar_box">
33 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
31 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
34 <p>
32 <p>
35 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
33 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
36 ${_('Using')} ${c.user.email}
34 ${_('Using')} ${c.user.email}
37 </p>
35 </p>
38 </div>
36 </div>
39 </div>
37 </div>
38 <div class="field">
39 <div class="label">
40 <label>${_('API key')}</label> ${c.user.api_key}
41 </div>
42 </div>
40
43
44 <div class="fields">
41 <div class="field">
45 <div class="field">
42 <div class="label">
46 <div class="label">
43 <label for="username">${_('Username')}:</label>
47 <label for="username">${_('Username')}:</label>
44 </div>
48 </div>
45 <div class="input">
49 <div class="input">
46 ${h.text('username',class_='medium')}
50 ${h.text('username',class_='medium')}
47 </div>
51 </div>
48 </div>
52 </div>
49
53
50 <div class="field">
54 <div class="field">
51 <div class="label">
55 <div class="label">
52 <label for="ldap_dn">${_('LDAP DN')}:</label>
56 <label for="ldap_dn">${_('LDAP DN')}:</label>
53 </div>
57 </div>
54 <div class="input">
58 <div class="input">
55 ${h.text('ldap_dn',class_='small')}
59 ${h.text('ldap_dn',class_='medium')}
56 </div>
60 </div>
57 </div>
61 </div>
58
62
59 <div class="field">
63 <div class="field">
60 <div class="label">
64 <div class="label">
61 <label for="new_password">${_('New password')}:</label>
65 <label for="new_password">${_('New password')}:</label>
62 </div>
66 </div>
63 <div class="input">
67 <div class="input">
64 ${h.password('new_password',class_='medium')}
68 ${h.password('new_password',class_='medium')}
65 </div>
69 </div>
66 </div>
70 </div>
67
71
68 <div class="field">
72 <div class="field">
69 <div class="label">
73 <div class="label">
70 <label for="name">${_('First Name')}:</label>
74 <label for="name">${_('First Name')}:</label>
71 </div>
75 </div>
72 <div class="input">
76 <div class="input">
73 ${h.text('name',class_='medium')}
77 ${h.text('name',class_='medium')}
74 </div>
78 </div>
75 </div>
79 </div>
76
80
77 <div class="field">
81 <div class="field">
78 <div class="label">
82 <div class="label">
79 <label for="lastname">${_('Last Name')}:</label>
83 <label for="lastname">${_('Last Name')}:</label>
80 </div>
84 </div>
81 <div class="input">
85 <div class="input">
82 ${h.text('lastname',class_='medium')}
86 ${h.text('lastname',class_='medium')}
83 </div>
87 </div>
84 </div>
88 </div>
85
89
86 <div class="field">
90 <div class="field">
87 <div class="label">
91 <div class="label">
88 <label for="email">${_('Email')}:</label>
92 <label for="email">${_('Email')}:</label>
89 </div>
93 </div>
90 <div class="input">
94 <div class="input">
91 ${h.text('email',class_='medium')}
95 ${h.text('email',class_='medium')}
92 </div>
96 </div>
93 </div>
97 </div>
94
98
95 <div class="field">
99 <div class="field">
96 <div class="label label-checkbox">
100 <div class="label label-checkbox">
97 <label for="active">${_('Active')}:</label>
101 <label for="active">${_('Active')}:</label>
98 </div>
102 </div>
99 <div class="checkboxes">
103 <div class="checkboxes">
100 ${h.checkbox('active',value=True)}
104 ${h.checkbox('active',value=True)}
101 </div>
105 </div>
102 </div>
106 </div>
103
107
104 <div class="field">
108 <div class="field">
105 <div class="label label-checkbox">
109 <div class="label label-checkbox">
106 <label for="admin">${_('Admin')}:</label>
110 <label for="admin">${_('Admin')}:</label>
107 </div>
111 </div>
108 <div class="checkboxes">
112 <div class="checkboxes">
109 ${h.checkbox('admin',value=True)}
113 ${h.checkbox('admin',value=True)}
110 </div>
114 </div>
111 </div>
115 </div>
112 <div class="buttons">
116 <div class="buttons">
113 ${h.submit('save','Save',class_="ui-button")}
117 ${h.submit('save','Save',class_="ui-button")}
114 ${h.reset('reset','Reset',class_="ui-button")}
118 ${h.reset('reset','Reset',class_="ui-button")}
115 </div>
119 </div>
116 </div>
120 </div>
117 </div>
121 </div>
118 ${h.end_form()}
122 ${h.end_form()}
119 </div>
123 </div>
120 <div class="box box-right">
124 <div class="box box-right">
121 <!-- box / title -->
125 <!-- box / title -->
122 <div class="title">
126 <div class="title">
123 <h5>${_('Permissions')}</h5>
127 <h5>${_('Permissions')}</h5>
124 </div>
128 </div>
125 <form id="map_form" method="post" action="{%url update_permissions %}">
129 ${h.form(url('user', id=c.user.user_id),method='put')}
126 <div class="form">
130 <div class="form">
131 <!-- fields -->
127 <div class="fields">
132 <div class="fields">
128
133 <div class="field">
129
134 <div class="label label-checkbox">
130
135 <label for="">${_('Create repositories')}:</label>
131 <table>
132 <tr>
133 <td class="label">${_('Permissions')}:</td>
134 <td>
135 <div>
136 <div style="float:left">
137 <div class="text">${_('Granted permissions')}</div>
138 ${h.select('granted_permissions',[],c.granted_permissions,multiple=True,size=8,style="min-width:210px")}
139 </div>
136 </div>
140 <div style="float:left;width:20px;padding-top:50px">
137 <div class="checkboxes">
141 <img alt="add" id="add_element"
138 ${h.checkbox('create',value=True)}
142 style="padding:2px;cursor:pointer"
143 src="${h.url("/images/icons/arrow_left.png")}">
144 <br />
145 <img alt="remove" id="remove_element"
146 style="padding:2px;cursor:pointer"
147 src="${h.url("/images/icons/arrow_right.png")}">
148 </div>
149 <div style="float:left">
150 <div class="text">${_('Available permissions')}</div>
151 ${h.select('available_permissions',[],c.available_permissions,multiple=True,size=8,style="min-width:210px")}
152 </div>
139 </div>
153 </div>
140 </div>
154 </td>
155 </tr>
156
157 </table>
158 <div class="buttons">
141 <div class="buttons">
159 ${h.submit('Save','Save',class_="ui-button")}
142 ${h.submit('save','Save',class_="ui-button")}
143 ${h.reset('reset','Reset',class_="ui-button")}
160 </div>
144 </div>
161 </div>
145 </div>
162 </div>
146 </div>
163 </form>
147 ${h.end_form()}
164
165
166 <script type="text/javascript">
167 YAHOO.util.Event.onDOMReady(function(){
168
169 var D = YAHOO.util.Dom;
170 var E = YAHOO.util.Event;
171
172 //temp container for storage.
173 var cache = new Array();
174 var c = D.get('id_granted_permissions');
175
176 //get only selected options for further fullfilment
177 for(var i = 0;node =c.options[i];i++){
178 if(node.selected){
179 //push selected to my temp storage left overs :)
180 cache.push(node);
181 }
182 }
183
184 //clear select
185 c.options.length = 0;
186
187 //fill it with remembered options
188 for(var i = 0;node = cache[i];i++){
189 c.options[i]=new Option(node.text, node.value, false, false);
190 }
191
192 function target_callback(e){
193 window.location='/admin/t4?g='+e.target.value;
194 }
195
196 function prompts_action_callback(e){
197
198 var choosen = D.get('id_granted_permissions');
199 var availible = D.get('id_available_permissions');
200
201 if (this.id=='add_element'){
202 for(var i=0; node = availible.options[i];i++){
203 if(node.selected){
204 choosen.appendChild(new Option(node.text, node.value, false, false));
205 }
206 }
207 }
208 else if (this.id=='remove_element'){
209
210 //temp container for storage.
211 cache = new Array();
212
213 for(var i = 0;node = choosen.options[i];i++){
214 if(!node.selected){
215 //push left overs :)
216 cache.push(node);
217 }
218 }
219 //clear select
220 choosen.options.length = 0;
221 for(var i = 0;node = cache[i];i++){
222 choosen.options[i]=new Option(node.text, node.value, false, false);
223 }
224 }
225 else{
226
227 }
228 }
229
230 E.addListener('id_groups','change',target_callback);
231
232 E.addListener(['add_element','remove_element'],'click',prompts_action_callback)
233
234 E.addListener('map_form','submit',function(){
235 var choosen = D.get('id_granted_permissions');
236 for (var i = 0; i < choosen.options.length; i++) {
237 choosen.options[i].selected = 'selected';
238 }
239 })
240 });
241 </script>
242 </div>
148 </div>
243 </%def>
149 </%def>
@@ -1,207 +1,211 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('My account')} ${c.rhodecode_user.username} - ${c.rhodecode_name}
5 ${_('My account')} ${c.rhodecode_user.username} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${_('My Account')}
9 ${_('My Account')}
10 </%def>
10 </%def>
11
11
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 </%def>
14 </%def>
15
15
16 <%def name="main()">
16 <%def name="main()">
17
17
18 <div class="box box-left">
18 <div class="box box-left">
19 <!-- box / title -->
19 <!-- box / title -->
20 <div class="title">
20 <div class="title">
21 ${self.breadcrumbs()}
21 ${self.breadcrumbs()}
22 </div>
22 </div>
23 <!-- end box / title -->
23 <!-- end box / title -->
24 <div>
24 <div>
25 ${h.form(url('admin_settings_my_account_update'),method='put')}
25 ${h.form(url('admin_settings_my_account_update'),method='put')}
26 <div class="form">
26 <div class="form">
27
27
28 <div class="field">
28 <div class="field">
29 <div class="gravatar_box">
29 <div class="gravatar_box">
30 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
30 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div>
31 <p>
31 <p>
32 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
32 <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/>
33 ${_('Using')} ${c.user.email}
33 ${_('Using')} ${c.user.email}
34 </p>
34 </p>
35 </div>
35 </div>
36 </div>
36 </div>
37
37 <div class="field">
38 <div class="label">
39 <label>${_('API key')}</label> ${c.user.api_key}
40 </div>
41 </div>
38 <div class="fields">
42 <div class="fields">
39 <div class="field">
43 <div class="field">
40 <div class="label">
44 <div class="label">
41 <label for="username">${_('Username')}:</label>
45 <label for="username">${_('Username')}:</label>
42 </div>
46 </div>
43 <div class="input">
47 <div class="input">
44 ${h.text('username',class_="medium")}
48 ${h.text('username',class_="medium")}
45 </div>
49 </div>
46 </div>
50 </div>
47
51
48 <div class="field">
52 <div class="field">
49 <div class="label">
53 <div class="label">
50 <label for="new_password">${_('New password')}:</label>
54 <label for="new_password">${_('New password')}:</label>
51 </div>
55 </div>
52 <div class="input">
56 <div class="input">
53 ${h.password('new_password',class_="medium")}
57 ${h.password('new_password',class_="medium")}
54 </div>
58 </div>
55 </div>
59 </div>
56
60
57 <div class="field">
61 <div class="field">
58 <div class="label">
62 <div class="label">
59 <label for="name">${_('First Name')}:</label>
63 <label for="name">${_('First Name')}:</label>
60 </div>
64 </div>
61 <div class="input">
65 <div class="input">
62 ${h.text('name',class_="medium")}
66 ${h.text('name',class_="medium")}
63 </div>
67 </div>
64 </div>
68 </div>
65
69
66 <div class="field">
70 <div class="field">
67 <div class="label">
71 <div class="label">
68 <label for="lastname">${_('Last Name')}:</label>
72 <label for="lastname">${_('Last Name')}:</label>
69 </div>
73 </div>
70 <div class="input">
74 <div class="input">
71 ${h.text('lastname',class_="medium")}
75 ${h.text('lastname',class_="medium")}
72 </div>
76 </div>
73 </div>
77 </div>
74
78
75 <div class="field">
79 <div class="field">
76 <div class="label">
80 <div class="label">
77 <label for="email">${_('Email')}:</label>
81 <label for="email">${_('Email')}:</label>
78 </div>
82 </div>
79 <div class="input">
83 <div class="input">
80 ${h.text('email',class_="medium")}
84 ${h.text('email',class_="medium")}
81 </div>
85 </div>
82 </div>
86 </div>
83
87
84 <div class="buttons">
88 <div class="buttons">
85 ${h.submit('save','Save',class_="ui-button")}
89 ${h.submit('save','Save',class_="ui-button")}
86 ${h.reset('reset','Reset',class_="ui-button")}
90 ${h.reset('reset','Reset',class_="ui-button")}
87 </div>
91 </div>
88 </div>
92 </div>
89 </div>
93 </div>
90 ${h.end_form()}
94 ${h.end_form()}
91 </div>
95 </div>
92 </div>
96 </div>
93
97
94 <div class="box box-right">
98 <div class="box box-right">
95 <!-- box / title -->
99 <!-- box / title -->
96 <div class="title">
100 <div class="title">
97 <h5>${_('My repositories')}
101 <h5>${_('My repositories')}
98 <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
102 <input class="top-right-rounded-corner top-left-rounded-corner bottom-left-rounded-corner bottom-right-rounded-corner" id="q_filter" size="15" type="text" name="filter" value="${_('quick filter...')}"/>
99 </h5>
103 </h5>
100 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
104 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
101 <ul class="links">
105 <ul class="links">
102 <li>
106 <li>
103 <span>${h.link_to(_('ADD REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
107 <span>${h.link_to(_('ADD REPOSITORY'),h.url('admin_settings_create_repository'))}</span>
104 </li>
108 </li>
105 </ul>
109 </ul>
106 %endif
110 %endif
107 </div>
111 </div>
108 <!-- end box / title -->
112 <!-- end box / title -->
109 <div class="table">
113 <div class="table">
110 <table>
114 <table>
111 <thead>
115 <thead>
112 <tr>
116 <tr>
113 <th class="left">${_('Name')}</th>
117 <th class="left">${_('Name')}</th>
114 <th class="left">${_('revision')}</th>
118 <th class="left">${_('revision')}</th>
115 <th colspan="2" class="left">${_('action')}</th>
119 <th colspan="2" class="left">${_('action')}</th>
116 </thead>
120 </thead>
117 <tbody>
121 <tbody>
118 %if c.user_repos:
122 %if c.user_repos:
119 %for repo in c.user_repos:
123 %for repo in c.user_repos:
120 <tr>
124 <tr>
121 <td>
125 <td>
122 %if repo['dbrepo']['repo_type'] =='hg':
126 %if repo['dbrepo']['repo_type'] =='hg':
123 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
127 <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url("/images/icons/hgicon.png")}"/>
124 %elif repo['dbrepo']['repo_type'] =='git':
128 %elif repo['dbrepo']['repo_type'] =='git':
125 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
129 <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url("/images/icons/giticon.png")}"/>
126 %else:
130 %else:
127
131
128 %endif
132 %endif
129 %if repo['dbrepo']['private']:
133 %if repo['dbrepo']['private']:
130 <img class="icon" alt="${_('private')}" src="${h.url("/images/icons/lock.png")}"/>
134 <img class="icon" alt="${_('private')}" src="${h.url("/images/icons/lock.png")}"/>
131 %else:
135 %else:
132 <img class="icon" alt="${_('public')}" src="${h.url("/images/icons/lock_open.png")}"/>
136 <img class="icon" alt="${_('public')}" src="${h.url("/images/icons/lock_open.png")}"/>
133 %endif
137 %endif
134
138
135 ${h.link_to(repo['repo'].name, h.url('summary_home',repo_name=repo['repo'].name),class_="repo_name")}
139 ${h.link_to(repo['repo'].name, h.url('summary_home',repo_name=repo['repo'].name),class_="repo_name")}
136 %if repo['dbrepo_fork']:
140 %if repo['dbrepo_fork']:
137 <a href="${h.url('summary_home',repo_name=repo['dbrepo_fork']['repo_name'])}">
141 <a href="${h.url('summary_home',repo_name=repo['dbrepo_fork']['repo_name'])}">
138 <img class="icon" alt="${_('public')}"
142 <img class="icon" alt="${_('public')}"
139 title="${_('Fork of')} ${repo['dbrepo_fork']['repo_name']}"
143 title="${_('Fork of')} ${repo['dbrepo_fork']['repo_name']}"
140 src="${h.url("/images/icons/arrow_divide.png")}"/></a>
144 src="${h.url("/images/icons/arrow_divide.png")}"/></a>
141 %endif
145 %endif
142 </td>
146 </td>
143 <td><span class="tooltip" title="${repo['repo'].last_change}">${("r%s:%s") % (h.get_changeset_safe(repo['repo'],'tip').revision,h.short_id(h.get_changeset_safe(repo['repo'],'tip').raw_id))}</span></td>
147 <td><span class="tooltip" title="${repo['repo'].last_change}">${("r%s:%s") % (h.get_changeset_safe(repo['repo'],'tip').revision,h.short_id(h.get_changeset_safe(repo['repo'],'tip').raw_id))}</span></td>
144 <td><a href="${h.url('repo_settings_home',repo_name=repo['repo'].name)}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url("/images/icons/application_form_edit.png")}"/></a></td>
148 <td><a href="${h.url('repo_settings_home',repo_name=repo['repo'].name)}" title="${_('edit')}"><img class="icon" alt="${_('private')}" src="${h.url("/images/icons/application_form_edit.png")}"/></a></td>
145 <td>
149 <td>
146 ${h.form(url('repo_settings_delete', repo_name=repo['repo'].name),method='delete')}
150 ${h.form(url('repo_settings_delete', repo_name=repo['repo'].name),method='delete')}
147 ${h.submit('remove_%s' % repo['repo'].name,'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
151 ${h.submit('remove_%s' % repo['repo'].name,'',class_="delete_icon action_button",onclick="return confirm('Confirm to delete this repository');")}
148 ${h.end_form()}
152 ${h.end_form()}
149 </td>
153 </td>
150 </tr>
154 </tr>
151 %endfor
155 %endfor
152 %else:
156 %else:
153 ${_('No repositories yet')}
157 ${_('No repositories yet')}
154 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
158 %if h.HasPermissionAny('hg.admin','hg.create.repository')():
155 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
159 ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))}
156 %endif
160 %endif
157 %endif
161 %endif
158 </tbody>
162 </tbody>
159 </table>
163 </table>
160 </div>
164 </div>
161
165
162 </div>
166 </div>
163 <script type="text/javascript">
167 <script type="text/javascript">
164 var D = YAHOO.util.Dom;
168 var D = YAHOO.util.Dom;
165 var E = YAHOO.util.Event;
169 var E = YAHOO.util.Event;
166 var S = YAHOO.util.Selector;
170 var S = YAHOO.util.Selector;
167
171
168 var q_filter = D.get('q_filter');
172 var q_filter = D.get('q_filter');
169 var F = YAHOO.namespace('q_filter');
173 var F = YAHOO.namespace('q_filter');
170
174
171 E.on(q_filter,'click',function(){
175 E.on(q_filter,'click',function(){
172 q_filter.value = '';
176 q_filter.value = '';
173 });
177 });
174
178
175 F.filterTimeout = null;
179 F.filterTimeout = null;
176
180
177 F.updateFilter = function() {
181 F.updateFilter = function() {
178 // Reset timeout
182 // Reset timeout
179 F.filterTimeout = null;
183 F.filterTimeout = null;
180
184
181 var obsolete = [];
185 var obsolete = [];
182 var nodes = S.query('div.table tr td a.repo_name');
186 var nodes = S.query('div.table tr td a.repo_name');
183 var req = D.get('q_filter').value;
187 var req = D.get('q_filter').value;
184 for (n in nodes){
188 for (n in nodes){
185 D.setStyle(nodes[n].parentNode.parentNode,'display','')
189 D.setStyle(nodes[n].parentNode.parentNode,'display','')
186 }
190 }
187 if (req){
191 if (req){
188 for (n in nodes){
192 for (n in nodes){
189 if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
193 if (nodes[n].innerHTML.toLowerCase().indexOf(req) == -1) {
190 obsolete.push(nodes[n]);
194 obsolete.push(nodes[n]);
191 }
195 }
192 }
196 }
193 if(obsolete){
197 if(obsolete){
194 for (n in obsolete){
198 for (n in obsolete){
195 D.setStyle(obsolete[n].parentNode.parentNode,'display','none');
199 D.setStyle(obsolete[n].parentNode.parentNode,'display','none');
196 }
200 }
197 }
201 }
198 }
202 }
199 }
203 }
200
204
201 E.on(q_filter,'keyup',function(e){
205 E.on(q_filter,'keyup',function(e){
202 clearTimeout(F.filterTimeout);
206 clearTimeout(F.filterTimeout);
203 setTimeout(F.updateFilter,600);
207 setTimeout(F.updateFilter,600);
204 });
208 });
205
209
206 </script>
210 </script>
207 </%def> No newline at end of file
211 </%def>
General Comments 0
You need to be logged in to leave comments. Login now