##// END OF EJS Templates
whitespace cleanup
marcink -
r3216:81bbb808 beta
parent child Browse files
Show More
@@ -1,74 +1,74
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 ${_('Repositories groups administration')} - ${c.rhodecode_name}
5 ${_('Repositories groups administration')} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8
8
9 <%def name="breadcrumbs_links()">
9 <%def name="breadcrumbs_links()">
10 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Repositories')}
10 ${h.link_to(_('Admin'),h.url('admin_home'))} &raquo; ${_('Repositories')}
11 </%def>
11 </%def>
12 <%def name="page_nav()">
12 <%def name="page_nav()">
13 ${self.menu('admin')}
13 ${self.menu('admin')}
14 </%def>
14 </%def>
15 <%def name="main()">
15 <%def name="main()">
16 <div class="box">
16 <div class="box">
17 <!-- box / title -->
17 <!-- box / title -->
18 <div class="title">
18 <div class="title">
19 ${self.breadcrumbs()}
19 ${self.breadcrumbs()}
20 <ul class="links">
20 <ul class="links">
21 <li>
21 <li>
22 <span>${h.link_to(_(u'Add new group'),h.url('new_repos_group'))}</span>
22 <span>${h.link_to(_(u'Add new group'),h.url('new_repos_group'))}</span>
23 </li>
23 </li>
24 </ul>
24 </ul>
25 </div>
25 </div>
26 <!-- end box / title -->
26 <!-- end box / title -->
27 <div class="table">
27 <div class="table">
28 % if c.groups:
28 % if c.groups:
29 <table class="table_disp">
29 <table class="table_disp">
30
30
31 <thead>
31 <thead>
32 <tr>
32 <tr>
33 <th class="left"><a href="#">${_('Group name')}</a></th>
33 <th class="left"><a href="#">${_('Group name')}</a></th>
34 <th class="left"><a href="#">${_('Description')}</a></th>
34 <th class="left"><a href="#">${_('Description')}</a></th>
35 <th class="left"><a href="#">${_('Number of toplevel repositories')}</a></th>
35 <th class="left"><a href="#">${_('Number of toplevel repositories')}</a></th>
36 <th class="left" colspan="2">${_('action')}</th>
36 <th class="left" colspan="2">${_('action')}</th>
37 </tr>
37 </tr>
38 </thead>
38 </thead>
39
39
40 ## REPO GROUPS
40 ## REPO GROUPS
41
41
42 % for gr in c.groups:
42 % for gr in c.groups:
43 <% gr_cn = gr.repositories.count() %>
43 <% gr_cn = gr.repositories.count() %>
44 <tr>
44 <tr>
45 <td>
45 <td>
46 <div style="white-space: nowrap">
46 <div style="white-space: nowrap">
47 <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
47 <img class="icon" alt="${_('Repositories group')}" src="${h.url('/images/icons/database_link.png')}"/>
48 ${h.link_to(h.literal(' &raquo; '.join(map(h.safe_unicode,[g.name for g in gr.parents+[gr]]))), url('repos_group_home',group_name=gr.group_name))}
48 ${h.link_to(h.literal(' &raquo; '.join(map(h.safe_unicode,[g.name for g in gr.parents+[gr]]))), url('repos_group_home',group_name=gr.group_name))}
49 </div>
49 </div>
50 </td>
50 </td>
51 <td>${gr.group_description}</td>
51 <td>${gr.group_description}</td>
52 <td><b>${gr_cn}</b></td>
52 <td><b>${gr_cn}</b></td>
53 <td>
53 <td>
54 <a href="${h.url('edit_repos_group',id=gr.group_id)}" title="${_('edit')}">
54 <a href="${h.url('edit_repos_group',id=gr.group_id)}" title="${_('edit')}">
55 ${h.submit('edit_%s' % gr.group_name,_('edit'),class_="edit_icon action_button")}
55 ${h.submit('edit_%s' % gr.group_name,_('edit'),class_="edit_icon action_button")}
56 </a>
56 </a>
57 </td>
57 </td>
58 <td>
58 <td>
59 ${h.form(url('repos_group', id=gr.group_id),method='delete')}
59 ${h.form(url('repos_group', id=gr.group_id),method='delete')}
60 ${h.submit('remove_%s' % gr.name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_cn) % (gr.name,gr_cn)+"');")}
60 ${h.submit('remove_%s' % gr.name,_('delete'),class_="delete_icon action_button",onclick="return confirm('"+ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_cn) % (gr.name,gr_cn)+"');")}
61 ${h.end_form()}
61 ${h.end_form()}
62 </td>
62 </td>
63 </tr>
63 </tr>
64 % endfor
64 % endfor
65
65
66 </table>
66 </table>
67 % else:
67 % else:
68 ${_('There are no repositories groups yet')}
68 ${_('There are no repositories groups yet')}
69 % endif
69 % endif
70
70
71 </div>
71 </div>
72 </div>
72 </div>
73
73
74 </%def>
74 </%def>
@@ -1,359 +1,359
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="root.html"/>
2 <%inherit file="root.html"/>
3
3
4 <!-- HEADER -->
4 <!-- HEADER -->
5 <div id="header">
5 <div id="header">
6 <div id="header-inner" class="title hover">
6 <div id="header-inner" class="title hover">
7 <div id="logo">
7 <div id="logo">
8 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
8 <h1><a href="${h.url('home')}">${c.rhodecode_name}</a></h1>
9 </div>
9 </div>
10 <!-- MENU -->
10 <!-- MENU -->
11 ${self.page_nav()}
11 ${self.page_nav()}
12 <!-- END MENU -->
12 <!-- END MENU -->
13 ${self.body()}
13 ${self.body()}
14 </div>
14 </div>
15 </div>
15 </div>
16 <!-- END HEADER -->
16 <!-- END HEADER -->
17
17
18 <!-- CONTENT -->
18 <!-- CONTENT -->
19 <div id="content">
19 <div id="content">
20 <div class="flash_msg">
20 <div class="flash_msg">
21 <% messages = h.flash.pop_messages() %>
21 <% messages = h.flash.pop_messages() %>
22 % if messages:
22 % if messages:
23 <ul id="flash-messages">
23 <ul id="flash-messages">
24 % for message in messages:
24 % for message in messages:
25 <li class="${message.category}_msg">${message}</li>
25 <li class="${message.category}_msg">${message}</li>
26 % endfor
26 % endfor
27 </ul>
27 </ul>
28 % endif
28 % endif
29 </div>
29 </div>
30 <div id="main">
30 <div id="main">
31 ${next.main()}
31 ${next.main()}
32 </div>
32 </div>
33 </div>
33 </div>
34 <!-- END CONTENT -->
34 <!-- END CONTENT -->
35
35
36 <!-- FOOTER -->
36 <!-- FOOTER -->
37 <div id="footer">
37 <div id="footer">
38 <div id="footer-inner" class="title">
38 <div id="footer-inner" class="title">
39 <div>
39 <div>
40 <p class="footer-link">
40 <p class="footer-link">
41 <a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
41 <a href="${h.url('bugtracker')}">${_('Submit a bug')}</a>
42 </p>
42 </p>
43 <p class="footer-link-right">
43 <p class="footer-link-right">
44 <a href="${h.url('rhodecode_official')}">RhodeCode${'-%s' % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}</a>
44 <a href="${h.url('rhodecode_official')}">RhodeCode${'-%s' % c.rhodecode_instanceid if c.rhodecode_instanceid else ''}</a>
45 ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski
45 ${c.rhodecode_version} &copy; 2010-${h.datetime.today().year} by Marcin Kuzminski
46 </p>
46 </p>
47 </div>
47 </div>
48 </div>
48 </div>
49 </div>
49 </div>
50 <!-- END FOOTER -->
50 <!-- END FOOTER -->
51
51
52 ### MAKO DEFS ###
52 ### MAKO DEFS ###
53 <%def name="page_nav()">
53 <%def name="page_nav()">
54 ${self.menu()}
54 ${self.menu()}
55 </%def>
55 </%def>
56
56
57 <%def name="breadcrumbs()">
57 <%def name="breadcrumbs()">
58 <div class="breadcrumbs">
58 <div class="breadcrumbs">
59 ${self.breadcrumbs_links()}
59 ${self.breadcrumbs_links()}
60 </div>
60 </div>
61 </%def>
61 </%def>
62
62
63 <%def name="usermenu()">
63 <%def name="usermenu()">
64 ## USER MENU
64 ## USER MENU
65 <li>
65 <li>
66 <a class="menu_link" id="quick_login_link">
66 <a class="menu_link" id="quick_login_link">
67 <span class="icon" style="padding:5px 5px 0px 5px">
67 <span class="icon" style="padding:5px 5px 0px 5px">
68 <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
68 <img src="${h.gravatar_url(c.rhodecode_user.email,20)}" alt="avatar">
69 </span>
69 </span>
70 %if c.rhodecode_user.username != 'default':
70 %if c.rhodecode_user.username != 'default':
71 <span class="menu_link_user">${c.rhodecode_user.username}</span>
71 <span class="menu_link_user">${c.rhodecode_user.username}</span>
72 %if c.unread_notifications != 0:
72 %if c.unread_notifications != 0:
73 <span class="menu_link_notifications">${c.unread_notifications}</span>
73 <span class="menu_link_notifications">${c.unread_notifications}</span>
74 %endif
74 %endif
75 %else:
75 %else:
76 <span>${_('Not logged in')}</span>
76 <span>${_('Not logged in')}</span>
77 %endif
77 %endif
78 </a>
78 </a>
79
79
80 <div class="user-menu">
80 <div class="user-menu">
81 <div id="quick_login">
81 <div id="quick_login">
82 %if c.rhodecode_user.username == 'default':
82 %if c.rhodecode_user.username == 'default':
83 <h4>${_('Login to your account')}</h4>
83 <h4>${_('Login to your account')}</h4>
84 ${h.form(h.url('login_home',came_from=h.url.current()))}
84 ${h.form(h.url('login_home',came_from=h.url.current()))}
85 <div class="form">
85 <div class="form">
86 <div class="fields">
86 <div class="fields">
87 <div class="field">
87 <div class="field">
88 <div class="label">
88 <div class="label">
89 <label for="username">${_('Username')}:</label>
89 <label for="username">${_('Username')}:</label>
90 </div>
90 </div>
91 <div class="input">
91 <div class="input">
92 ${h.text('username',class_='focus',size=40)}
92 ${h.text('username',class_='focus',size=40)}
93 </div>
93 </div>
94
94
95 </div>
95 </div>
96 <div class="field">
96 <div class="field">
97 <div class="label">
97 <div class="label">
98 <label for="password">${_('Password')}:</label>
98 <label for="password">${_('Password')}:</label>
99 </div>
99 </div>
100 <div class="input">
100 <div class="input">
101 ${h.password('password',class_='focus',size=40)}
101 ${h.password('password',class_='focus',size=40)}
102 </div>
102 </div>
103
103
104 </div>
104 </div>
105 <div class="buttons">
105 <div class="buttons">
106 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
106 <div class="password_forgoten">${h.link_to(_('Forgot password ?'),h.url('reset_password'))}</div>
107 <div class="register">
107 <div class="register">
108 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
108 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
109 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
109 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
110 %endif
110 %endif
111 </div>
111 </div>
112 <div class="submit">
112 <div class="submit">
113 ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
113 ${h.submit('sign_in',_('Log In'),class_="ui-btn xsmall")}
114 </div>
114 </div>
115 </div>
115 </div>
116 </div>
116 </div>
117 </div>
117 </div>
118 ${h.end_form()}
118 ${h.end_form()}
119 %else:
119 %else:
120 <div class="links_left">
120 <div class="links_left">
121 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
121 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
122 <div class="email">${c.rhodecode_user.email}</div>
122 <div class="email">${c.rhodecode_user.email}</div>
123 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
123 <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
124 <div class="inbox"><a href="${h.url('notifications')}">${_('Inbox')}: ${c.unread_notifications}</a></div>
124 <div class="inbox"><a href="${h.url('notifications')}">${_('Inbox')}: ${c.unread_notifications}</a></div>
125 </div>
125 </div>
126 <div class="links_right">
126 <div class="links_right">
127 <ol class="links">
127 <ol class="links">
128 <li>${h.link_to(_(u'Home'),h.url('home'))}</li>
128 <li>${h.link_to(_(u'Home'),h.url('home'))}</li>
129 <li>${h.link_to(_(u'Journal'),h.url('journal'))}</li>
129 <li>${h.link_to(_(u'Journal'),h.url('journal'))}</li>
130 <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
130 <li>${h.link_to(_(u'My account'),h.url('admin_settings_my_account'))}</li>
131 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
131 <li class="logout">${h.link_to(_(u'Log Out'),h.url('logout_home'))}</li>
132 </ol>
132 </ol>
133 </div>
133 </div>
134 %endif
134 %endif
135 </div>
135 </div>
136 </div>
136 </div>
137
137
138 </li>
138 </li>
139 </%def>
139 </%def>
140
140
141 <%def name="menu(current=None)">
141 <%def name="menu(current=None)">
142 <%
142 <%
143 def is_current(selected):
143 def is_current(selected):
144 if selected == current:
144 if selected == current:
145 return h.literal('class="current"')
145 return h.literal('class="current"')
146 %>
146 %>
147 <ul id="quick">
147 <ul id="quick">
148 <!-- repo switcher -->
148 <!-- repo switcher -->
149 <li>
149 <li>
150 <a class="menu_link" id="repo_switcher" title="${_('Switch repository')}" href="#">
150 <a class="menu_link" id="repo_switcher" title="${_('Switch repository')}" href="#">
151 <span class="icon">
151 <span class="icon">
152 <img src="${h.url('/images/icons/database.png')}" alt="${_('Products')}" />
152 <img src="${h.url('/images/icons/database.png')}" alt="${_('Products')}" />
153 </span>
153 </span>
154 <span>${_('Repositories')}</span>
154 <span>${_('Repositories')}</span>
155 </a>
155 </a>
156 <ul id="repo_switcher_list" class="repo_switcher">
156 <ul id="repo_switcher_list" class="repo_switcher">
157 <li>
157 <li>
158 <a href="#">${_('loading...')}</a>
158 <a href="#">${_('loading...')}</a>
159 </li>
159 </li>
160 </ul>
160 </ul>
161 </li>
161 </li>
162 ## we render this menu only not for those pages
162 ## we render this menu only not for those pages
163 %if current not in ['home','admin', 'search', 'journal']:
163 %if current not in ['home','admin', 'search', 'journal']:
164 ##REGULAR MENU
164 ##REGULAR MENU
165 <li ${is_current('summary')}>
165 <li ${is_current('summary')}>
166 <a class="menu_link" title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
166 <a class="menu_link" title="${_('Summary')}" href="${h.url('summary_home',repo_name=c.repo_name)}">
167 <span class="icon">
167 <span class="icon">
168 <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
168 <img src="${h.url('/images/icons/clipboard_16.png')}" alt="${_('Summary')}" />
169 </span>
169 </span>
170 <span>${_('Summary')}</span>
170 <span>${_('Summary')}</span>
171 </a>
171 </a>
172 </li>
172 </li>
173 <li ${is_current('changelog')}>
173 <li ${is_current('changelog')}>
174 <a class="menu_link" title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
174 <a class="menu_link" title="${_('Changelog')}" href="${h.url('changelog_home',repo_name=c.repo_name)}">
175 <span class="icon">
175 <span class="icon">
176 <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
176 <img src="${h.url('/images/icons/time.png')}" alt="${_('Changelog')}" />
177 </span>
177 </span>
178 <span>${_('Changelog')}</span>
178 <span>${_('Changelog')}</span>
179 </a>
179 </a>
180 </li>
180 </li>
181 <li ${is_current('switch_to')}>
181 <li ${is_current('switch_to')}>
182 <a class="menu_link" id="branch_tag_switcher" title="${_('Switch to')}" href="#">
182 <a class="menu_link" id="branch_tag_switcher" title="${_('Switch to')}" href="#">
183 <span class="icon">
183 <span class="icon">
184 <img src="${h.url('/images/icons/arrow_switch.png')}" alt="${_('Switch to')}" />
184 <img src="${h.url('/images/icons/arrow_switch.png')}" alt="${_('Switch to')}" />
185 </span>
185 </span>
186 <span>${_('Switch to')}</span>
186 <span>${_('Switch to')}</span>
187 </a>
187 </a>
188 <ul id="switch_to_list" class="switch_to">
188 <ul id="switch_to_list" class="switch_to">
189 <li><a href="#">${_('loading...')}</a></li>
189 <li><a href="#">${_('loading...')}</a></li>
190 </ul>
190 </ul>
191 </li>
191 </li>
192 <li ${is_current('files')}>
192 <li ${is_current('files')}>
193 <a class="menu_link" title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
193 <a class="menu_link" title="${_('Files')}" href="${h.url('files_home',repo_name=c.repo_name)}">
194 <span class="icon">
194 <span class="icon">
195 <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
195 <img src="${h.url('/images/icons/file.png')}" alt="${_('Files')}" />
196 </span>
196 </span>
197 <span>${_('Files')}</span>
197 <span>${_('Files')}</span>
198 </a>
198 </a>
199 </li>
199 </li>
200 <li ${is_current('options')}>
200 <li ${is_current('options')}>
201 <a class="menu_link" title="${_('Options')}" href="#">
201 <a class="menu_link" title="${_('Options')}" href="#">
202 <span class="icon">
202 <span class="icon">
203 <img src="${h.url('/images/icons/table_gear.png')}" alt="${_('Admin')}" />
203 <img src="${h.url('/images/icons/table_gear.png')}" alt="${_('Admin')}" />
204 </span>
204 </span>
205 <span>${_('Options')}</span>
205 <span>${_('Options')}</span>
206 </a>
206 </a>
207 <ul>
207 <ul>
208 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
208 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
209 %if h.HasPermissionAll('hg.admin')('access settings on repository'):
209 %if h.HasPermissionAll('hg.admin')('access settings on repository'):
210 <li>${h.link_to(_('repository settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
210 <li>${h.link_to(_('repository settings'),h.url('edit_repo',repo_name=c.repo_name),class_='settings')}</li>
211 %else:
211 %else:
212 <li>${h.link_to(_('repository settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
212 <li>${h.link_to(_('repository settings'),h.url('repo_settings_home',repo_name=c.repo_name),class_='settings')}</li>
213 %endif
213 %endif
214 %endif
214 %endif
215
215
216 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
216 <li>${h.link_to(_('fork'),h.url('repo_fork_home',repo_name=c.repo_name),class_='fork')}</li>
217 %if h.is_hg(c.rhodecode_repo):
217 %if h.is_hg(c.rhodecode_repo):
218 <li>${h.link_to(_('open new pull request'),h.url('pullrequest_home',repo_name=c.repo_name),class_='pull_request')}</li>
218 <li>${h.link_to(_('open new pull request'),h.url('pullrequest_home',repo_name=c.repo_name),class_='pull_request')}</li>
219 %endif
219 %endif
220 %if c.rhodecode_db_repo.fork:
220 %if c.rhodecode_db_repo.fork:
221 <li>${h.link_to(_('compare fork'),h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref=request.GET.get('branch') or 'default',other_ref_type='branch',other_ref='default',repo=c.rhodecode_db_repo.fork.repo_name),class_='compare_request')}</li>
221 <li>${h.link_to(_('compare fork'),h.url('compare_url',repo_name=c.repo_name,org_ref_type='branch',org_ref=request.GET.get('branch') or 'default',other_ref_type='branch',other_ref='default',repo=c.rhodecode_db_repo.fork.repo_name),class_='compare_request')}</li>
222 %endif
222 %endif
223 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
223 <li>${h.link_to(_('search'),h.url('search_repo',search_repo=c.repo_name),class_='search')}</li>
224
224
225 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
225 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
226 %if c.rhodecode_db_repo.locked[0]:
226 %if c.rhodecode_db_repo.locked[0]:
227 <li>${h.link_to(_('unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
227 <li>${h.link_to(_('unlock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_del')}</li>
228 %else:
228 %else:
229 <li>${h.link_to(_('lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
229 <li>${h.link_to(_('lock'), h.url('toggle_locking',repo_name=c.repo_name),class_='locking_add')}</li>
230 %endif
230 %endif
231 %endif
231 %endif
232
232
233 % if h.HasPermissionAll('hg.admin')('access admin main page'):
233 % if h.HasPermissionAll('hg.admin')('access admin main page'):
234 <li>
234 <li>
235 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
235 ${h.link_to(_('admin'),h.url('admin_home'),class_='admin')}
236 <%def name="admin_menu()">
236 <%def name="admin_menu()">
237 <ul>
237 <ul>
238 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
238 <li>${h.link_to(_('journal'),h.url('admin_home'),class_='journal')}</li>
239 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
239 <li>${h.link_to(_('repositories'),h.url('repos'),class_='repos')}</li>
240 <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
240 <li>${h.link_to(_('repositories groups'),h.url('repos_groups'),class_='repos_groups')}</li>
241 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
241 <li>${h.link_to(_('users'),h.url('users'),class_='users')}</li>
242 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
242 <li>${h.link_to(_('users groups'),h.url('users_groups'),class_='groups')}</li>
243 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
243 <li>${h.link_to(_('permissions'),h.url('edit_permission',id='default'),class_='permissions')}</li>
244 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
244 <li>${h.link_to(_('ldap'),h.url('ldap_home'),class_='ldap')}</li>
245 <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
245 <li>${h.link_to(_('defaults'),h.url('defaults'),class_='defaults')}</li>
246 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
246 <li class="last">${h.link_to(_('settings'),h.url('admin_settings'),class_='settings')}</li>
247 </ul>
247 </ul>
248 </%def>
248 </%def>
249 ## ADMIN MENU
249 ## ADMIN MENU
250 ${admin_menu()}
250 ${admin_menu()}
251 </li>
251 </li>
252 % endif
252 % endif
253 </ul>
253 </ul>
254 </li>
254 </li>
255 <li>
255 <li>
256 <a class="menu_link" title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
256 <a class="menu_link" title="${_('Followers')}" href="${h.url('repo_followers_home',repo_name=c.repo_name)}">
257 <span class="icon_short">
257 <span class="icon_short">
258 <img src="${h.url('/images/icons/heart.png')}" alt="${_('Followers')}" />
258 <img src="${h.url('/images/icons/heart.png')}" alt="${_('Followers')}" />
259 </span>
259 </span>
260 <span id="current_followers_count" class="short">${c.repository_followers}</span>
260 <span id="current_followers_count" class="short">${c.repository_followers}</span>
261 </a>
261 </a>
262 </li>
262 </li>
263 <li>
263 <li>
264 <a class="menu_link" title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
264 <a class="menu_link" title="${_('Forks')}" href="${h.url('repo_forks_home',repo_name=c.repo_name)}">
265 <span class="icon_short">
265 <span class="icon_short">
266 <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Forks')}" />
266 <img src="${h.url('/images/icons/arrow_divide.png')}" alt="${_('Forks')}" />
267 </span>
267 </span>
268 <span class="short">${c.repository_forks}</span>
268 <span class="short">${c.repository_forks}</span>
269 </a>
269 </a>
270 </li>
270 </li>
271 <li>
271 <li>
272 <a class="menu_link" title="${_('Pull requests')}" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}">
272 <a class="menu_link" title="${_('Pull requests')}" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}">
273 <span class="icon_short">
273 <span class="icon_short">
274 <img src="${h.url('/images/icons/arrow_join.png')}" alt="${_('Pull requests')}" />
274 <img src="${h.url('/images/icons/arrow_join.png')}" alt="${_('Pull requests')}" />
275 </span>
275 </span>
276 <span class="short">${c.repository_pull_requests}</span>
276 <span class="short">${c.repository_pull_requests}</span>
277 </a>
277 </a>
278 </li>
278 </li>
279 ${usermenu()}
279 ${usermenu()}
280 <script type="text/javascript">
280 <script type="text/javascript">
281 YUE.on('branch_tag_switcher','mouseover',function(){
281 YUE.on('branch_tag_switcher','mouseover',function(){
282 var loaded = YUD.hasClass('branch_tag_switcher','loaded');
282 var loaded = YUD.hasClass('branch_tag_switcher','loaded');
283 if(!loaded){
283 if(!loaded){
284 YUD.addClass('branch_tag_switcher','loaded');
284 YUD.addClass('branch_tag_switcher','loaded');
285 ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list',
285 ypjax("${h.url('branch_tag_switcher',repo_name=c.repo_name)}",'switch_to_list',
286 function(o){},
286 function(o){},
287 function(o){YUD.removeClass('branch_tag_switcher','loaded');}
287 function(o){YUD.removeClass('branch_tag_switcher','loaded');}
288 ,null);
288 ,null);
289 }
289 }
290 return false;
290 return false;
291 });
291 });
292 </script>
292 </script>
293 %else:
293 %else:
294 ##ROOT MENU
294 ##ROOT MENU
295 %if c.rhodecode_user.username != 'default':
295 %if c.rhodecode_user.username != 'default':
296 <li ${is_current('journal')}>
296 <li ${is_current('journal')}>
297 <a class="menu_link" title="${_('Journal')}" href="${h.url('journal')}">
297 <a class="menu_link" title="${_('Journal')}" href="${h.url('journal')}">
298 <span class="icon">
298 <span class="icon">
299 <img src="${h.url('/images/icons/book.png')}" alt="${_('Journal')}" />
299 <img src="${h.url('/images/icons/book.png')}" alt="${_('Journal')}" />
300 </span>
300 </span>
301 <span>${_('Journal')}</span>
301 <span>${_('Journal')}</span>
302 </a>
302 </a>
303 </li>
303 </li>
304 %else:
304 %else:
305 <li ${is_current('journal')}>
305 <li ${is_current('journal')}>
306 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
306 <a class="menu_link" title="${_('Public journal')}" href="${h.url('public_journal')}">
307 <span class="icon">
307 <span class="icon">
308 <img src="${h.url('/images/icons/book.png')}" alt="${_('Public journal')}" />
308 <img src="${h.url('/images/icons/book.png')}" alt="${_('Public journal')}" />
309 </span>
309 </span>
310 <span>${_('Public journal')}</span>
310 <span>${_('Public journal')}</span>
311 </a>
311 </a>
312 </li>
312 </li>
313 %endif
313 %endif
314 <li ${is_current('search')}>
314 <li ${is_current('search')}>
315 <a class="menu_link" title="${_('Search')}" href="${h.url('search')}">
315 <a class="menu_link" title="${_('Search')}" href="${h.url('search')}">
316 <span class="icon">
316 <span class="icon">
317 <img src="${h.url('/images/icons/search_16.png')}" alt="${_('Search')}" />
317 <img src="${h.url('/images/icons/search_16.png')}" alt="${_('Search')}" />
318 </span>
318 </span>
319 <span>${_('Search')}</span>
319 <span>${_('Search')}</span>
320 </a>
320 </a>
321 </li>
321 </li>
322 %if h.HasPermissionAll('hg.admin')('access admin main page'):
322 %if h.HasPermissionAll('hg.admin')('access admin main page'):
323 <li ${is_current('admin')}>
323 <li ${is_current('admin')}>
324 <a class="menu_link" title="${_('Admin')}" href="${h.url('admin_home')}">
324 <a class="menu_link" title="${_('Admin')}" href="${h.url('admin_home')}">
325 <span class="icon">
325 <span class="icon">
326 <img src="${h.url('/images/icons/cog_edit.png')}" alt="${_('Admin')}" />
326 <img src="${h.url('/images/icons/cog_edit.png')}" alt="${_('Admin')}" />
327 </span>
327 </span>
328 <span>${_('Admin')}</span>
328 <span>${_('Admin')}</span>
329 </a>
329 </a>
330 ${admin_menu()}
330 ${admin_menu()}
331 </li>
331 </li>
332 %endif
332 %endif
333 ${usermenu()}
333 ${usermenu()}
334 %endif
334 %endif
335 <script type="text/javascript">
335 <script type="text/javascript">
336 YUE.on('repo_switcher','mouseover',function(){
336 YUE.on('repo_switcher','mouseover',function(){
337 var target = 'q_filter_rs';
337 var target = 'q_filter_rs';
338 var qfilter_activate = function(){
338 var qfilter_activate = function(){
339 var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
339 var nodes = YUQ('ul#repo_switcher_list li a.repo_name');
340 var func = function(node){
340 var func = function(node){
341 return node.parentNode;
341 return node.parentNode;
342 }
342 }
343 q_filter(target,nodes,func);
343 q_filter(target,nodes,func);
344 }
344 }
345
345
346 var loaded = YUD.hasClass('repo_switcher','loaded');
346 var loaded = YUD.hasClass('repo_switcher','loaded');
347 if(!loaded){
347 if(!loaded){
348 YUD.addClass('repo_switcher','loaded');
348 YUD.addClass('repo_switcher','loaded');
349 ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
349 ypjax("${h.url('repo_switcher')}",'repo_switcher_list',
350 function(o){qfilter_activate();YUD.get(target).focus()},
350 function(o){qfilter_activate();YUD.get(target).focus()},
351 function(o){YUD.removeClass('repo_switcher','loaded');}
351 function(o){YUD.removeClass('repo_switcher','loaded');}
352 ,null);
352 ,null);
353 }else{
353 }else{
354 YUD.get(target).focus();
354 YUD.get(target).focus();
355 }
355 }
356 return false;
356 return false;
357 });
357 });
358 </script>
358 </script>
359 </%def>
359 </%def>
@@ -1,195 +1,195
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 ## usage:
2 ## usage:
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
3 ## <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
4 ## ${comment.comment_block(co)}
4 ## ${comment.comment_block(co)}
5 ##
5 ##
6 <%def name="comment_block(co)">
6 <%def name="comment_block(co)">
7 <div class="comment" id="comment-${co.comment_id}" line="${co.line_no}">
7 <div class="comment" id="comment-${co.comment_id}" line="${co.line_no}">
8 <div class="comment-wrapp">
8 <div class="comment-wrapp">
9 <div class="meta">
9 <div class="meta">
10 <div style="float:left"> <img src="${h.gravatar_url(co.author.email, 20)}" /> </div>
10 <div style="float:left"> <img src="${h.gravatar_url(co.author.email, 20)}" /> </div>
11 <div class="user">
11 <div class="user">
12 ${co.author.username}
12 ${co.author.username}
13 </div>
13 </div>
14 <div class="date">
14 <div class="date">
15 ${h.age(co.modified_at)} <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
15 ${h.age(co.modified_at)} <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
16 </div>
16 </div>
17 %if co.status_change:
17 %if co.status_change:
18 <div style="float:left" class="changeset-status-container">
18 <div style="float:left" class="changeset-status-container">
19 <div style="float:left;padding:0px 2px 0px 2px"><span style="font-size: 18px;">&rsaquo;</span></div>
19 <div style="float:left;padding:0px 2px 0px 2px"><span style="font-size: 18px;">&rsaquo;</span></div>
20 <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change[0].status_lbl}</div>
20 <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change[0].status_lbl}</div>
21 <div class="changeset-status-ico"><img src="${h.url(str('/images/icons/flag_status_%s.png' % co.status_change[0].status))}" /></div>
21 <div class="changeset-status-ico"><img src="${h.url(str('/images/icons/flag_status_%s.png' % co.status_change[0].status))}" /></div>
22 </div>
22 </div>
23 %endif
23 %endif
24
24
25 <div style="float:left;padding:3px 0px 0px 5px">
25 <div style="float:left;padding:3px 0px 0px 5px">
26 <span class="">
26 <span class="">
27 %if co.pull_request:
27 %if co.pull_request:
28 <a href="${h.url('pullrequest_show',repo_name=co.pull_request.other_repo.repo_name,pull_request_id=co.pull_request.pull_request_id)}">
28 <a href="${h.url('pullrequest_show',repo_name=co.pull_request.other_repo.repo_name,pull_request_id=co.pull_request.pull_request_id)}">
29 %if co.status_change:
29 %if co.status_change:
30 ${_('Status from pull request %s') % co.pull_request.pull_request_id}
30 ${_('Status from pull request %s') % co.pull_request.pull_request_id}
31 %else:
31 %else:
32 ${_('Comment from pull request %s') % co.pull_request.pull_request_id}
32 ${_('Comment from pull request %s') % co.pull_request.pull_request_id}
33 %endif
33 %endif
34 </a>
34 </a>
35 %endif
35 %endif
36 </span>
36 </span>
37 </div>
37 </div>
38
38
39 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or co.author.user_id == c.rhodecode_user.user_id:
39 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or co.author.user_id == c.rhodecode_user.user_id:
40 <div class="buttons">
40 <div class="buttons">
41 <span onClick="deleteComment(${co.comment_id})" class="delete-comment ui-btn">${_('Delete')}</span>
41 <span onClick="deleteComment(${co.comment_id})" class="delete-comment ui-btn">${_('Delete')}</span>
42 </div>
42 </div>
43 %endif
43 %endif
44 </div>
44 </div>
45 <div class="text">
45 <div class="text">
46 ${h.rst_w_mentions(co.text)|n}
46 ${h.rst_w_mentions(co.text)|n}
47 </div>
47 </div>
48 </div>
48 </div>
49 </div>
49 </div>
50 </%def>
50 </%def>
51
51
52
52
53 <%def name="comment_inline_form()">
53 <%def name="comment_inline_form()">
54 <div id='comment-inline-form-template' style="display:none">
54 <div id='comment-inline-form-template' style="display:none">
55 <div class="comment-inline-form ac">
55 <div class="comment-inline-form ac">
56 %if c.rhodecode_user.username != 'default':
56 %if c.rhodecode_user.username != 'default':
57 <div class="overlay"><div class="overlay-text">${_('Submitting...')}</div></div>
57 <div class="overlay"><div class="overlay-text">${_('Submitting...')}</div></div>
58 ${h.form('#', class_='inline-form')}
58 ${h.form('#', class_='inline-form')}
59 <div class="clearfix">
59 <div class="clearfix">
60 <div class="comment-help">${_('Commenting on line {1}.')}
60 <div class="comment-help">${_('Commenting on line {1}.')}
61 ${(_('Comments parsed using %s syntax with %s support.') % (
61 ${(_('Comments parsed using %s syntax with %s support.') % (
62 ('<a href="%s">RST</a>' % h.url('rst_help')),
62 ('<a href="%s">RST</a>' % h.url('rst_help')),
63 ('<span style="color:#003367" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
63 ('<span style="color:#003367" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this RhodeCode user'))
64 )
64 )
65 )|n
65 )|n
66 }
66 }
67 </div>
67 </div>
68 <div class="mentions-container" id="mentions_container_{1}"></div>
68 <div class="mentions-container" id="mentions_container_{1}"></div>
69 <textarea id="text_{1}" name="text" class="yui-ac-input"></textarea>
69 <textarea id="text_{1}" name="text" class="yui-ac-input"></textarea>
70 </div>
70 </div>
71 <div class="comment-button">
71 <div class="comment-button">
72 <input type="hidden" name="f_path" value="{0}">
72 <input type="hidden" name="f_path" value="{0}">
73 <input type="hidden" name="line" value="{1}">
73 <input type="hidden" name="line" value="{1}">
74 ${h.submit('save', _('Comment'), class_='ui-btn save-inline-form')}
74 ${h.submit('save', _('Comment'), class_='ui-btn save-inline-form')}
75 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
75 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
76 </div>
76 </div>
77 ${h.end_form()}
77 ${h.end_form()}
78 %else:
78 %else:
79 ${h.form('')}
79 ${h.form('')}
80 <div class="clearfix">
80 <div class="clearfix">
81 <div class="comment-help">
81 <div class="comment-help">
82 ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
82 ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
83 </div>
83 </div>
84 </div>
84 </div>
85 <div class="comment-button">
85 <div class="comment-button">
86 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
86 ${h.reset('hide-inline-form', _('Hide'), class_='ui-btn hide-inline-form')}
87 </div>
87 </div>
88 ${h.end_form()}
88 ${h.end_form()}
89 %endif
89 %endif
90 </div>
90 </div>
91 </div>
91 </div>
92 </%def>
92 </%def>
93
93
94
94
95 ## generates inlines taken from c.comments var
95 ## generates inlines taken from c.comments var
96 <%def name="inlines()">
96 <%def name="inlines()">
97 <div class="comments-number">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
97 <div class="comments-number">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
98 %for path, lines in c.inline_comments:
98 %for path, lines in c.inline_comments:
99 % for line,comments in lines.iteritems():
99 % for line,comments in lines.iteritems():
100 <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
100 <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
101 %for co in comments:
101 %for co in comments:
102 ${comment_block(co)}
102 ${comment_block(co)}
103 %endfor
103 %endfor
104 </div>
104 </div>
105 %endfor
105 %endfor
106 %endfor
106 %endfor
107
107
108 </%def>
108 </%def>
109
109
110 ## generate inline comments and the main ones
110 ## generate inline comments and the main ones
111 <%def name="generate_comments()">
111 <%def name="generate_comments()">
112 <div class="comments">
112 <div class="comments">
113 <div id="inline-comments-container">
113 <div id="inline-comments-container">
114 ## generate inlines for this changeset
114 ## generate inlines for this changeset
115 ${inlines()}
115 ${inlines()}
116 </div>
116 </div>
117
117
118 %for co in c.comments:
118 %for co in c.comments:
119 <div id="comment-tr-${co.comment_id}">
119 <div id="comment-tr-${co.comment_id}">
120 ## only render comments that are not from pull request, or from
120 ## only render comments that are not from pull request, or from
121 ## pull request and a status change
121 ## pull request and a status change
122 %if not co.pull_request or co.pull_request and co.status_change:
122 %if not co.pull_request or co.pull_request and co.status_change:
123 ${comment_block(co)}
123 ${comment_block(co)}
124 %endif
124 %endif
125 </div>
125 </div>
126 %endfor
126 %endfor
127 </div>
127 </div>
128 </%def>
128 </%def>
129
129
130 ## MAIN COMMENT FORM
130 ## MAIN COMMENT FORM
131 <%def name="comments(post_url, cur_status, close_btn=False, change_status=True)">
131 <%def name="comments(post_url, cur_status, close_btn=False, change_status=True)">
132
132
133 <div class="comments">
133 <div class="comments">
134 %if c.rhodecode_user.username != 'default':
134 %if c.rhodecode_user.username != 'default':
135 <div class="comment-form ac">
135 <div class="comment-form ac">
136 ${h.form(post_url)}
136 ${h.form(post_url)}
137 <strong>${_('Leave a comment')}</strong>
137 <strong>${_('Leave a comment')}</strong>
138 <div class="clearfix">
138 <div class="clearfix">
139 <div class="comment-help">
139 <div class="comment-help">
140 ${(_('Comments parsed using %s syntax with %s support.') % (('<a href="%s">RST</a>' % h.url('rst_help')),
140 ${(_('Comments parsed using %s syntax with %s support.') % (('<a href="%s">RST</a>' % h.url('rst_help')),
141 '<span style="color:#003367" class="tooltip" title="%s">@mention</span>' %
141 '<span style="color:#003367" class="tooltip" title="%s">@mention</span>' %
142 _('Use @username inside this text to send notification to this RhodeCode user')))|n}
142 _('Use @username inside this text to send notification to this RhodeCode user')))|n}
143 %if change_status:
143 %if change_status:
144 | <label for="show_changeset_status_box" class="tooltip" title="${_('Check this to change current status of code-review for this changeset')}"> ${_('change status')}</label>
144 | <label for="show_changeset_status_box" class="tooltip" title="${_('Check this to change current status of code-review for this changeset')}"> ${_('change status')}</label>
145 <input style="vertical-align: bottom;margin-bottom:-2px" id="show_changeset_status_box" type="checkbox" name="change_changeset_status" />
145 <input style="vertical-align: bottom;margin-bottom:-2px" id="show_changeset_status_box" type="checkbox" name="change_changeset_status" />
146 %endif
146 %endif
147 </div>
147 </div>
148 %if change_status:
148 %if change_status:
149 <div id="status_block_container" class="status-block" style="display:none">
149 <div id="status_block_container" class="status-block" style="display:none">
150 %for status,lbl in c.changeset_statuses:
150 %for status,lbl in c.changeset_statuses:
151 <div class="">
151 <div class="">
152 <img src="${h.url('/images/icons/flag_status_%s.png' % status)}" /> <input ${'checked="checked"' if status == cur_status else ''}" type="radio" class="status_change_radio" name="changeset_status" id="${status}" value="${status}">
152 <img src="${h.url('/images/icons/flag_status_%s.png' % status)}" /> <input ${'checked="checked"' if status == cur_status else ''}" type="radio" class="status_change_radio" name="changeset_status" id="${status}" value="${status}">
153 <label for="${status}">${lbl}</label>
153 <label for="${status}">${lbl}</label>
154 </div>
154 </div>
155 %endfor
155 %endfor
156 </div>
156 </div>
157 %endif
157 %endif
158 <div class="mentions-container" id="mentions_container"></div>
158 <div class="mentions-container" id="mentions_container"></div>
159 ${h.textarea('text')}
159 ${h.textarea('text')}
160 </div>
160 </div>
161 <div class="comment-button">
161 <div class="comment-button">
162 ${h.submit('save', _('Comment'), class_="ui-btn large")}
162 ${h.submit('save', _('Comment'), class_="ui-btn large")}
163 %if close_btn and change_status:
163 %if close_btn and change_status:
164 ${h.submit('save_close', _('Comment and close'), class_='ui-btn blue large %s' % ('hidden' if cur_status in ['not_reviewed','under_review'] else ''))}
164 ${h.submit('save_close', _('Comment and close'), class_='ui-btn blue large %s' % ('hidden' if cur_status in ['not_reviewed','under_review'] else ''))}
165 %endif
165 %endif
166 </div>
166 </div>
167 ${h.end_form()}
167 ${h.end_form()}
168 </div>
168 </div>
169 %endif
169 %endif
170 </div>
170 </div>
171 <script>
171 <script>
172 YUE.onDOMReady(function () {
172 YUE.onDOMReady(function () {
173 MentionsAutoComplete('text', 'mentions_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
173 MentionsAutoComplete('text', 'mentions_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
174
174
175 // changeset status box listener
175 // changeset status box listener
176 YUE.on(YUD.get('show_changeset_status_box'),'change',function(e){
176 YUE.on(YUD.get('show_changeset_status_box'),'change',function(e){
177 if(e.currentTarget.checked){
177 if(e.currentTarget.checked){
178 YUD.setStyle('status_block_container','display','');
178 YUD.setStyle('status_block_container','display','');
179 }
179 }
180 else{
180 else{
181 YUD.setStyle('status_block_container','display','none');
181 YUD.setStyle('status_block_container','display','none');
182 }
182 }
183 })
183 })
184 YUE.on(YUQ('.status_change_radio'), 'change',function(e){
184 YUE.on(YUQ('.status_change_radio'), 'change',function(e){
185 var val = e.currentTarget.value;
185 var val = e.currentTarget.value;
186 if (val == 'approved' || val == 'rejected') {
186 if (val == 'approved' || val == 'rejected') {
187 YUD.removeClass('save_close', 'hidden');
187 YUD.removeClass('save_close', 'hidden');
188 }else{
188 }else{
189 YUD.addClass('save_close', 'hidden');
189 YUD.addClass('save_close', 'hidden');
190 }
190 }
191 })
191 })
192
192
193 });
193 });
194 </script>
194 </script>
195 </%def>
195 </%def>
@@ -1,228 +1,228
1 <%inherit file="/base/base.html"/>
1 <%inherit file="/base/base.html"/>
2
2
3 <%def name="title()">
3 <%def name="title()">
4 ${c.repo_name} ${_('Pull request #%s') % c.pull_request.pull_request_id}
4 ${c.repo_name} ${_('Pull request #%s') % c.pull_request.pull_request_id}
5 </%def>
5 </%def>
6
6
7 <%def name="breadcrumbs_links()">
7 <%def name="breadcrumbs_links()">
8 ${h.link_to(_(u'Home'),h.url('/'))}
8 ${h.link_to(_(u'Home'),h.url('/'))}
9 &raquo;
9 &raquo;
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
10 ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
11 &raquo;
11 &raquo;
12 ${_('Pull request #%s') % c.pull_request.pull_request_id}
12 ${_('Pull request #%s') % c.pull_request.pull_request_id}
13 </%def>
13 </%def>
14
14
15 <%def name="main()">
15 <%def name="main()">
16
16
17 <div class="box">
17 <div class="box">
18 <!-- box / title -->
18 <!-- box / title -->
19 <div class="title">
19 <div class="title">
20 ${self.breadcrumbs()}
20 ${self.breadcrumbs()}
21 </div>
21 </div>
22 %if c.pull_request.is_closed():
22 %if c.pull_request.is_closed():
23 <div style="padding:10px; font-size:22px;width:100%;text-align: center; color:#88D882">${_('Closed %s') % (h.age(c.pull_request.updated_on))} ${_('with status %s') % h.changeset_status_lbl(c.current_changeset_status)}</div>
23 <div style="padding:10px; font-size:22px;width:100%;text-align: center; color:#88D882">${_('Closed %s') % (h.age(c.pull_request.updated_on))} ${_('with status %s') % h.changeset_status_lbl(c.current_changeset_status)}</div>
24 %endif
24 %endif
25 <h3>${_('Title')}: ${c.pull_request.title}</h3>
25 <h3>${_('Title')}: ${c.pull_request.title}</h3>
26
26
27 <div class="form">
27 <div class="form">
28 <div id="summary" class="fields">
28 <div id="summary" class="fields">
29 <div class="field">
29 <div class="field">
30 <div class="label-summary">
30 <div class="label-summary">
31 <label>${_('Status')}:</label>
31 <label>${_('Status')}:</label>
32 </div>
32 </div>
33 <div class="input">
33 <div class="input">
34 <div class="changeset-status-container" style="float:none;clear:both">
34 <div class="changeset-status-container" style="float:none;clear:both">
35 %if c.current_changeset_status:
35 %if c.current_changeset_status:
36 <div title="${_('Pull request status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div>
36 <div title="${_('Pull request status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.current_changeset_status)}]</div>
37 <div class="changeset-status-ico" style="padding:1px 4px"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div>
37 <div class="changeset-status-ico" style="padding:1px 4px"><img src="${h.url('/images/icons/flag_status_%s.png' % c.current_changeset_status)}" /></div>
38 %endif
38 %endif
39 </div>
39 </div>
40 </div>
40 </div>
41 </div>
41 </div>
42 <div class="field">
42 <div class="field">
43 <div class="label-summary">
43 <div class="label-summary">
44 <label>${_('Still not reviewed by')}:</label>
44 <label>${_('Still not reviewed by')}:</label>
45 </div>
45 </div>
46 <div class="input">
46 <div class="input">
47 % if len(c.pull_request_pending_reviewers) > 0:
47 % if len(c.pull_request_pending_reviewers) > 0:
48 <div class="tooltip" title="${h.tooltip(','.join([x.username for x in c.pull_request_pending_reviewers]))}">${ungettext('%d reviewer', '%d reviewers',len(c.pull_request_pending_reviewers)) % len(c.pull_request_pending_reviewers)}</div>
48 <div class="tooltip" title="${h.tooltip(','.join([x.username for x in c.pull_request_pending_reviewers]))}">${ungettext('%d reviewer', '%d reviewers',len(c.pull_request_pending_reviewers)) % len(c.pull_request_pending_reviewers)}</div>
49 %else:
49 %else:
50 <div>${_('pull request was reviewed by all reviewers')}</div>
50 <div>${_('pull request was reviewed by all reviewers')}</div>
51 %endif
51 %endif
52 </div>
52 </div>
53 </div>
53 </div>
54 <div class="field">
54 <div class="field">
55 <div class="label-summary">
55 <div class="label-summary">
56 <label>${_('Origin repository')}:</label>
56 <label>${_('Origin repository')}:</label>
57 </div>
57 </div>
58 <div class="input">
58 <div class="input">
59 <div>
59 <div>
60 ##%if h.is_hg(c.pull_request.org_repo):
60 ##%if h.is_hg(c.pull_request.org_repo):
61 ## <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
61 ## <img class="icon" title="${_('Mercurial repository')}" alt="${_('Mercurial repository')}" src="${h.url('/images/icons/hgicon.png')}"/>
62 ##%elif h.is_git(c.pull_request.org_repo):
62 ##%elif h.is_git(c.pull_request.org_repo):
63 ## <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
63 ## <img class="icon" title="${_('Git repository')}" alt="${_('Git repository')}" src="${h.url('/images/icons/giticon.png')}"/>
64 ##%endif
64 ##%endif
65 <span class="spantag">${c.pull_request.org_ref_parts[0]}</span>
65 <span class="spantag">${c.pull_request.org_ref_parts[0]}</span>
66 :
66 :
67 <span class="spantag">${c.pull_request.org_ref_parts[1]}</span>
67 <span class="spantag">${c.pull_request.org_ref_parts[1]}</span>
68 <span><a href="${h.url('summary_home', repo_name=c.pull_request.org_repo.repo_name)}">${c.pull_request.org_repo.clone_url()}</a></span>
68 <span><a href="${h.url('summary_home', repo_name=c.pull_request.org_repo.repo_name)}">${c.pull_request.org_repo.clone_url()}</a></span>
69 </div>
69 </div>
70 </div>
70 </div>
71 </div>
71 </div>
72 </div>
72 </div>
73 </div>
73 </div>
74 <div style="white-space:pre-wrap;padding:3px 3px 5px 20px">${h.literal(c.pull_request.description)}</div>
74 <div style="white-space:pre-wrap;padding:3px 3px 5px 20px">${h.literal(c.pull_request.description)}</div>
75 <div style="padding:4px 4px 10px 20px">
75 <div style="padding:4px 4px 10px 20px">
76 <div>${_('Created on')}: ${h.fmt_date(c.pull_request.created_on)}</div>
76 <div>${_('Created on')}: ${h.fmt_date(c.pull_request.created_on)}</div>
77 </div>
77 </div>
78
78
79 <div style="overflow: auto;">
79 <div style="overflow: auto;">
80 ##DIFF
80 ##DIFF
81 <div class="table" style="float:left;clear:none">
81 <div class="table" style="float:left;clear:none">
82 <div id="body" class="diffblock">
82 <div id="body" class="diffblock">
83 <div style="white-space:pre-wrap;padding:5px">${_('Compare view')}</div>
83 <div style="white-space:pre-wrap;padding:5px">${_('Compare view')}</div>
84 </div>
84 </div>
85 <div id="changeset_compare_view_content">
85 <div id="changeset_compare_view_content">
86 ##CS
86 ##CS
87 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
87 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${ungettext('Showing %s commit','Showing %s commits', len(c.cs_ranges)) % len(c.cs_ranges)}</div>
88 <%include file="/compare/compare_cs.html" />
88 <%include file="/compare/compare_cs.html" />
89
89
90 ## FILES
90 ## FILES
91 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
91 <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">
92
92
93 % if c.limited_diff:
93 % if c.limited_diff:
94 ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
94 ${ungettext('%s file changed', '%s files changed', len(c.files)) % len(c.files)}
95 % else:
95 % else:
96 ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
96 ${ungettext('%s file changed with %s insertions and %s deletions','%s files changed with %s insertions and %s deletions', len(c.files)) % (len(c.files),c.lines_added,c.lines_deleted)}:
97 %endif
97 %endif
98
98
99 </div>
99 </div>
100 <div class="cs_files">
100 <div class="cs_files">
101 %if not c.files:
101 %if not c.files:
102 <span class="empty_data">${_('No files')}</span>
102 <span class="empty_data">${_('No files')}</span>
103 %endif
103 %endif
104 %for fid, change, f, stat in c.files:
104 %for fid, change, f, stat in c.files:
105 <div class="cs_${change}">
105 <div class="cs_${change}">
106 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
106 <div class="node">${h.link_to(h.safe_unicode(f),h.url.current(anchor=fid))}</div>
107 <div class="changes">${h.fancy_file_stats(stat)}</div>
107 <div class="changes">${h.fancy_file_stats(stat)}</div>
108 </div>
108 </div>
109 %endfor
109 %endfor
110 </div>
110 </div>
111 % if c.limited_diff:
111 % if c.limited_diff:
112 <h5>${_('Changeset was too big and was cut off...')}</h5>
112 <h5>${_('Changeset was too big and was cut off...')}</h5>
113 % endif
113 % endif
114 </div>
114 </div>
115 </div>
115 </div>
116 ## REVIEWERS
116 ## REVIEWERS
117 <div style="float:left; border-left:1px dashed #eee">
117 <div style="float:left; border-left:1px dashed #eee">
118 <h4>${_('Pull request reviewers')}</h4>
118 <h4>${_('Pull request reviewers')}</h4>
119 <div id="reviewers" style="padding:0px 0px 5px 10px">
119 <div id="reviewers" style="padding:0px 0px 5px 10px">
120 ## members goes here !
120 ## members goes here !
121 <div class="group_members_wrap" style="min-height:45px">
121 <div class="group_members_wrap" style="min-height:45px">
122 <ul id="review_members" class="group_members">
122 <ul id="review_members" class="group_members">
123 %for member,status in c.pull_request_reviewers:
123 %for member,status in c.pull_request_reviewers:
124 <li id="reviewer_${member.user_id}">
124 <li id="reviewer_${member.user_id}">
125 <div class="reviewers_member">
125 <div class="reviewers_member">
126 <div style="float:left;padding:0px 3px 0px 0px" class="tooltip" title="${h.tooltip(h.changeset_status_lbl(status[0][1].status if status else 'not_reviewed'))}">
126 <div style="float:left;padding:0px 3px 0px 0px" class="tooltip" title="${h.tooltip(h.changeset_status_lbl(status[0][1].status if status else 'not_reviewed'))}">
127 <img src="${h.url(str('/images/icons/flag_status_%s.png' % (status[0][1].status if status else 'not_reviewed')))}"/>
127 <img src="${h.url(str('/images/icons/flag_status_%s.png' % (status[0][1].status if status else 'not_reviewed')))}"/>
128 </div>
128 </div>
129 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
129 <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(member.email,14)}"/> </div>
130 <div style="float:left">${member.full_name} (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</div>
130 <div style="float:left">${member.full_name} (${_('owner') if c.pull_request.user_id == member.user_id else _('reviewer')})</div>
131 <input type="hidden" value="${member.user_id}" name="review_members" />
131 <input type="hidden" value="${member.user_id}" name="review_members" />
132 %if not c.pull_request.is_closed() and (h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.user_id == c.rhodecode_user.user_id):
132 %if not c.pull_request.is_closed() and (h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.user_id == c.rhodecode_user.user_id):
133 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
133 <span class="delete_icon action_button" onclick="removeReviewer(${member.user_id})"></span>
134 %endif
134 %endif
135 </div>
135 </div>
136 </li>
136 </li>
137 %endfor
137 %endfor
138 </ul>
138 </ul>
139 </div>
139 </div>
140 %if not c.pull_request.is_closed():
140 %if not c.pull_request.is_closed():
141 <div class='ac'>
141 <div class='ac'>
142 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.author.user_id == c.rhodecode_user.user_id:
142 %if h.HasPermissionAny('hg.admin', 'repository.admin')() or c.pull_request.author.user_id == c.rhodecode_user.user_id:
143 <div class="reviewer_ac">
143 <div class="reviewer_ac">
144 ${h.text('user', class_='yui-ac-input')}
144 ${h.text('user', class_='yui-ac-input')}
145 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
145 <span class="help-block">${_('Add reviewer to this pull request.')}</span>
146 <div id="reviewers_container"></div>
146 <div id="reviewers_container"></div>
147 </div>
147 </div>
148 <div style="padding:0px 10px">
148 <div style="padding:0px 10px">
149 <span id="update_pull_request" class="ui-btn xsmall">${_('save')}</span>
149 <span id="update_pull_request" class="ui-btn xsmall">${_('save')}</span>
150 </div>
150 </div>
151 %endif
151 %endif
152 </div>
152 </div>
153 %endif
153 %endif
154 </div>
154 </div>
155 </div>
155 </div>
156 </div>
156 </div>
157 <script>
157 <script>
158 var _USERS_AC_DATA = ${c.users_array|n};
158 var _USERS_AC_DATA = ${c.users_array|n};
159 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
159 var _GROUPS_AC_DATA = ${c.users_groups_array|n};
160 AJAX_COMMENT_URL = "${url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}";
160 AJAX_COMMENT_URL = "${url('pullrequest_comment',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}";
161 AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
161 AJAX_COMMENT_DELETE_URL = "${url('pullrequest_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}";
162 AJAX_UPDATE_PULLREQUEST = "${url('pullrequest_update',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}"
162 AJAX_UPDATE_PULLREQUEST = "${url('pullrequest_update',repo_name=c.repo_name,pull_request_id=c.pull_request.pull_request_id)}"
163 </script>
163 </script>
164
164
165 ## diff block
165 ## diff block
166 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
166 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
167 %for fid, change, f, stat in c.files:
167 %for fid, change, f, stat in c.files:
168 ${diff_block.diff_block_simple([c.changes[fid]])}
168 ${diff_block.diff_block_simple([c.changes[fid]])}
169 %endfor
169 %endfor
170 % if c.limited_diff:
170 % if c.limited_diff:
171 <h4>${_('Changeset was too big and was cut off...')}</h4>
171 <h4>${_('Changeset was too big and was cut off...')}</h4>
172 % endif
172 % endif
173
173
174
174
175 ## template for inline comment form
175 ## template for inline comment form
176 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
176 <%namespace name="comment" file="/changeset/changeset_file_comment.html"/>
177 ${comment.comment_inline_form()}
177 ${comment.comment_inline_form()}
178
178
179 ## render comments and inlines
179 ## render comments and inlines
180 ${comment.generate_comments()}
180 ${comment.generate_comments()}
181
181
182 % if not c.pull_request.is_closed():
182 % if not c.pull_request.is_closed():
183 ## main comment form and it status
183 ## main comment form and it status
184 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name,
184 ${comment.comments(h.url('pullrequest_comment', repo_name=c.repo_name,
185 pull_request_id=c.pull_request.pull_request_id),
185 pull_request_id=c.pull_request.pull_request_id),
186 c.current_changeset_status,
186 c.current_changeset_status,
187 close_btn=True, change_status=c.allowed_to_change_status)}
187 close_btn=True, change_status=c.allowed_to_change_status)}
188 %endif
188 %endif
189
189
190 <script type="text/javascript">
190 <script type="text/javascript">
191 YUE.onDOMReady(function(){
191 YUE.onDOMReady(function(){
192 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
192 PullRequestAutoComplete('user', 'reviewers_container', _USERS_AC_DATA, _GROUPS_AC_DATA);
193
193
194 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
194 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
195 var show = 'none';
195 var show = 'none';
196 var target = e.currentTarget;
196 var target = e.currentTarget;
197 if(target.checked){
197 if(target.checked){
198 var show = ''
198 var show = ''
199 }
199 }
200 var boxid = YUD.getAttribute(target,'id_for');
200 var boxid = YUD.getAttribute(target,'id_for');
201 var comments = YUQ('#{0} .inline-comments'.format(boxid));
201 var comments = YUQ('#{0} .inline-comments'.format(boxid));
202 for(c in comments){
202 for(c in comments){
203 YUD.setStyle(comments[c],'display',show);
203 YUD.setStyle(comments[c],'display',show);
204 }
204 }
205 var btns = YUQ('#{0} .inline-comments-button'.format(boxid));
205 var btns = YUQ('#{0} .inline-comments-button'.format(boxid));
206 for(c in btns){
206 for(c in btns){
207 YUD.setStyle(btns[c],'display',show);
207 YUD.setStyle(btns[c],'display',show);
208 }
208 }
209 })
209 })
210
210
211 YUE.on(YUQ('.line'),'click',function(e){
211 YUE.on(YUQ('.line'),'click',function(e){
212 var tr = e.currentTarget;
212 var tr = e.currentTarget;
213 injectInlineForm(tr);
213 injectInlineForm(tr);
214 });
214 });
215
215
216 // inject comments into they proper positions
216 // inject comments into they proper positions
217 var file_comments = YUQ('.inline-comment-placeholder');
217 var file_comments = YUQ('.inline-comment-placeholder');
218 renderInlineComments(file_comments);
218 renderInlineComments(file_comments);
219
219
220 YUE.on(YUD.get('update_pull_request'),'click',function(e){
220 YUE.on(YUD.get('update_pull_request'),'click',function(e){
221 updateReviewers();
221 updateReviewers();
222 })
222 })
223 })
223 })
224 </script>
224 </script>
225
225
226 </div>
226 </div>
227
227
228 </%def>
228 </%def>
@@ -1,1275 +1,1275
1 from __future__ import with_statement
1 from __future__ import with_statement
2 import random
2 import random
3 import mock
3 import mock
4
4
5 from rhodecode.tests import *
5 from rhodecode.tests import *
6 from rhodecode.lib.compat import json
6 from rhodecode.lib.compat import json
7 from rhodecode.lib.auth import AuthUser
7 from rhodecode.lib.auth import AuthUser
8 from rhodecode.model.user import UserModel
8 from rhodecode.model.user import UserModel
9 from rhodecode.model.users_group import UsersGroupModel
9 from rhodecode.model.users_group import UsersGroupModel
10 from rhodecode.model.repo import RepoModel
10 from rhodecode.model.repo import RepoModel
11 from rhodecode.model.meta import Session
11 from rhodecode.model.meta import Session
12 from rhodecode.model.scm import ScmModel
12 from rhodecode.model.scm import ScmModel
13 from rhodecode.model.db import Repository
13 from rhodecode.model.db import Repository
14
14
15 API_URL = '/_admin/api'
15 API_URL = '/_admin/api'
16
16
17
17
18 def _build_data(apikey, method, **kw):
18 def _build_data(apikey, method, **kw):
19 """
19 """
20 Builds API data with given random ID
20 Builds API data with given random ID
21
21
22 :param random_id:
22 :param random_id:
23 :type random_id:
23 :type random_id:
24 """
24 """
25 random_id = random.randrange(1, 9999)
25 random_id = random.randrange(1, 9999)
26 return random_id, json.dumps({
26 return random_id, json.dumps({
27 "id": random_id,
27 "id": random_id,
28 "api_key": apikey,
28 "api_key": apikey,
29 "method": method,
29 "method": method,
30 "args": kw
30 "args": kw
31 })
31 })
32
32
33 jsonify = lambda obj: json.loads(json.dumps(obj))
33 jsonify = lambda obj: json.loads(json.dumps(obj))
34
34
35
35
36 def crash(*args, **kwargs):
36 def crash(*args, **kwargs):
37 raise Exception('Total Crash !')
37 raise Exception('Total Crash !')
38
38
39
39
40 def api_call(test_obj, params):
40 def api_call(test_obj, params):
41 response = test_obj.app.post(API_URL, content_type='application/json',
41 response = test_obj.app.post(API_URL, content_type='application/json',
42 params=params)
42 params=params)
43 return response
43 return response
44
44
45
45
46 TEST_USERS_GROUP = 'test_users_group'
46 TEST_USERS_GROUP = 'test_users_group'
47
47
48
48
49 def make_users_group(name=TEST_USERS_GROUP):
49 def make_users_group(name=TEST_USERS_GROUP):
50 gr = UsersGroupModel().create(name=name)
50 gr = UsersGroupModel().create(name=name)
51 UsersGroupModel().add_user_to_group(users_group=gr,
51 UsersGroupModel().add_user_to_group(users_group=gr,
52 user=TEST_USER_ADMIN_LOGIN)
52 user=TEST_USER_ADMIN_LOGIN)
53 Session().commit()
53 Session().commit()
54 return gr
54 return gr
55
55
56
56
57 def destroy_users_group(name=TEST_USERS_GROUP):
57 def destroy_users_group(name=TEST_USERS_GROUP):
58 UsersGroupModel().delete(users_group=name, force=True)
58 UsersGroupModel().delete(users_group=name, force=True)
59 Session().commit()
59 Session().commit()
60
60
61
61
62 def create_repo(repo_name, repo_type, owner=None):
62 def create_repo(repo_name, repo_type, owner=None):
63 # create new repo
63 # create new repo
64 form_data = _get_repo_create_params(
64 form_data = _get_repo_create_params(
65 repo_name_full=repo_name,
65 repo_name_full=repo_name,
66 repo_description='description %s' % repo_name,
66 repo_description='description %s' % repo_name,
67 )
67 )
68 cur_user = UserModel().get_by_username(owner or TEST_USER_ADMIN_LOGIN)
68 cur_user = UserModel().get_by_username(owner or TEST_USER_ADMIN_LOGIN)
69 r = RepoModel().create(form_data, cur_user)
69 r = RepoModel().create(form_data, cur_user)
70 Session().commit()
70 Session().commit()
71 return r
71 return r
72
72
73
73
74 def create_fork(fork_name, fork_type, fork_of):
74 def create_fork(fork_name, fork_type, fork_of):
75 fork = RepoModel(Session())._get_repo(fork_of)
75 fork = RepoModel(Session())._get_repo(fork_of)
76 r = create_repo(fork_name, fork_type)
76 r = create_repo(fork_name, fork_type)
77 r.fork = fork
77 r.fork = fork
78 Session().add(r)
78 Session().add(r)
79 Session().commit()
79 Session().commit()
80 return r
80 return r
81
81
82
82
83 def destroy_repo(repo_name):
83 def destroy_repo(repo_name):
84 RepoModel().delete(repo_name)
84 RepoModel().delete(repo_name)
85 Session().commit()
85 Session().commit()
86
86
87
87
88 class BaseTestApi(object):
88 class BaseTestApi(object):
89 REPO = None
89 REPO = None
90 REPO_TYPE = None
90 REPO_TYPE = None
91
91
92 @classmethod
92 @classmethod
93 def setUpClass(self):
93 def setUpClass(self):
94 self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
94 self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
95 self.apikey = self.usr.api_key
95 self.apikey = self.usr.api_key
96 self.test_user = UserModel().create_or_update(
96 self.test_user = UserModel().create_or_update(
97 username='test-api',
97 username='test-api',
98 password='test',
98 password='test',
99 email='test@api.rhodecode.org',
99 email='test@api.rhodecode.org',
100 firstname='first',
100 firstname='first',
101 lastname='last'
101 lastname='last'
102 )
102 )
103 Session().commit()
103 Session().commit()
104 self.TEST_USER_LOGIN = self.test_user.username
104 self.TEST_USER_LOGIN = self.test_user.username
105 self.apikey_regular = self.test_user.api_key
105 self.apikey_regular = self.test_user.api_key
106
106
107 @classmethod
107 @classmethod
108 def teardownClass(self):
108 def teardownClass(self):
109 pass
109 pass
110
110
111 def setUp(self):
111 def setUp(self):
112 self.maxDiff = None
112 self.maxDiff = None
113 make_users_group()
113 make_users_group()
114
114
115 def tearDown(self):
115 def tearDown(self):
116 destroy_users_group()
116 destroy_users_group()
117
117
118 def _compare_ok(self, id_, expected, given):
118 def _compare_ok(self, id_, expected, given):
119 expected = jsonify({
119 expected = jsonify({
120 'id': id_,
120 'id': id_,
121 'error': None,
121 'error': None,
122 'result': expected
122 'result': expected
123 })
123 })
124 given = json.loads(given)
124 given = json.loads(given)
125 self.assertEqual(expected, given)
125 self.assertEqual(expected, given)
126
126
127 def _compare_error(self, id_, expected, given):
127 def _compare_error(self, id_, expected, given):
128 expected = jsonify({
128 expected = jsonify({
129 'id': id_,
129 'id': id_,
130 'error': expected,
130 'error': expected,
131 'result': None
131 'result': None
132 })
132 })
133 given = json.loads(given)
133 given = json.loads(given)
134 self.assertEqual(expected, given)
134 self.assertEqual(expected, given)
135
135
136 # def test_Optional(self):
136 # def test_Optional(self):
137 # from rhodecode.controllers.api.api import Optional
137 # from rhodecode.controllers.api.api import Optional
138 # option1 = Optional(None)
138 # option1 = Optional(None)
139 # self.assertEqual('<Optional:%s>' % None, repr(option1))
139 # self.assertEqual('<Optional:%s>' % None, repr(option1))
140 #
140 #
141 # self.assertEqual(1, Optional.extract(Optional(1)))
141 # self.assertEqual(1, Optional.extract(Optional(1)))
142 # self.assertEqual('trololo', Optional.extract('trololo'))
142 # self.assertEqual('trololo', Optional.extract('trololo'))
143
143
144 def test_api_wrong_key(self):
144 def test_api_wrong_key(self):
145 id_, params = _build_data('trololo', 'get_user')
145 id_, params = _build_data('trololo', 'get_user')
146 response = api_call(self, params)
146 response = api_call(self, params)
147
147
148 expected = 'Invalid API KEY'
148 expected = 'Invalid API KEY'
149 self._compare_error(id_, expected, given=response.body)
149 self._compare_error(id_, expected, given=response.body)
150
150
151 def test_api_missing_non_optional_param(self):
151 def test_api_missing_non_optional_param(self):
152 id_, params = _build_data(self.apikey, 'get_repo')
152 id_, params = _build_data(self.apikey, 'get_repo')
153 response = api_call(self, params)
153 response = api_call(self, params)
154
154
155 expected = 'Missing non optional `repoid` arg in JSON DATA'
155 expected = 'Missing non optional `repoid` arg in JSON DATA'
156 self._compare_error(id_, expected, given=response.body)
156 self._compare_error(id_, expected, given=response.body)
157
157
158 def test_api_missing_non_optional_param_args_null(self):
158 def test_api_missing_non_optional_param_args_null(self):
159 id_, params = _build_data(self.apikey, 'get_repo')
159 id_, params = _build_data(self.apikey, 'get_repo')
160 params = params.replace('"args": {}', '"args": null')
160 params = params.replace('"args": {}', '"args": null')
161 response = api_call(self, params)
161 response = api_call(self, params)
162
162
163 expected = 'Missing non optional `repoid` arg in JSON DATA'
163 expected = 'Missing non optional `repoid` arg in JSON DATA'
164 self._compare_error(id_, expected, given=response.body)
164 self._compare_error(id_, expected, given=response.body)
165
165
166 def test_api_missing_non_optional_param_args_bad(self):
166 def test_api_missing_non_optional_param_args_bad(self):
167 id_, params = _build_data(self.apikey, 'get_repo')
167 id_, params = _build_data(self.apikey, 'get_repo')
168 params = params.replace('"args": {}', '"args": 1')
168 params = params.replace('"args": {}', '"args": 1')
169 response = api_call(self, params)
169 response = api_call(self, params)
170
170
171 expected = 'Missing non optional `repoid` arg in JSON DATA'
171 expected = 'Missing non optional `repoid` arg in JSON DATA'
172 self._compare_error(id_, expected, given=response.body)
172 self._compare_error(id_, expected, given=response.body)
173
173
174 def test_api_args_is_null(self):
174 def test_api_args_is_null(self):
175 id_, params = _build_data(self.apikey, 'get_users',)
175 id_, params = _build_data(self.apikey, 'get_users',)
176 params = params.replace('"args": {}', '"args": null')
176 params = params.replace('"args": {}', '"args": null')
177 response = api_call(self, params)
177 response = api_call(self, params)
178 self.assertEqual(response.status, '200 OK')
178 self.assertEqual(response.status, '200 OK')
179
179
180 def test_api_args_is_bad(self):
180 def test_api_args_is_bad(self):
181 id_, params = _build_data(self.apikey, 'get_users',)
181 id_, params = _build_data(self.apikey, 'get_users',)
182 params = params.replace('"args": {}', '"args": 1')
182 params = params.replace('"args": {}', '"args": 1')
183 response = api_call(self, params)
183 response = api_call(self, params)
184 self.assertEqual(response.status, '200 OK')
184 self.assertEqual(response.status, '200 OK')
185
185
186 def test_api_get_users(self):
186 def test_api_get_users(self):
187 id_, params = _build_data(self.apikey, 'get_users',)
187 id_, params = _build_data(self.apikey, 'get_users',)
188 response = api_call(self, params)
188 response = api_call(self, params)
189 ret_all = []
189 ret_all = []
190 for usr in UserModel().get_all():
190 for usr in UserModel().get_all():
191 ret = usr.get_api_data()
191 ret = usr.get_api_data()
192 ret_all.append(jsonify(ret))
192 ret_all.append(jsonify(ret))
193 expected = ret_all
193 expected = ret_all
194 self._compare_ok(id_, expected, given=response.body)
194 self._compare_ok(id_, expected, given=response.body)
195
195
196 def test_api_get_user(self):
196 def test_api_get_user(self):
197 id_, params = _build_data(self.apikey, 'get_user',
197 id_, params = _build_data(self.apikey, 'get_user',
198 userid=TEST_USER_ADMIN_LOGIN)
198 userid=TEST_USER_ADMIN_LOGIN)
199 response = api_call(self, params)
199 response = api_call(self, params)
200
200
201 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
201 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
202 ret = usr.get_api_data()
202 ret = usr.get_api_data()
203 ret['permissions'] = AuthUser(usr.user_id).permissions
203 ret['permissions'] = AuthUser(usr.user_id).permissions
204
204
205 expected = ret
205 expected = ret
206 self._compare_ok(id_, expected, given=response.body)
206 self._compare_ok(id_, expected, given=response.body)
207
207
208 def test_api_get_user_that_does_not_exist(self):
208 def test_api_get_user_that_does_not_exist(self):
209 id_, params = _build_data(self.apikey, 'get_user',
209 id_, params = _build_data(self.apikey, 'get_user',
210 userid='trololo')
210 userid='trololo')
211 response = api_call(self, params)
211 response = api_call(self, params)
212
212
213 expected = "user `%s` does not exist" % 'trololo'
213 expected = "user `%s` does not exist" % 'trololo'
214 self._compare_error(id_, expected, given=response.body)
214 self._compare_error(id_, expected, given=response.body)
215
215
216 def test_api_get_user_without_giving_userid(self):
216 def test_api_get_user_without_giving_userid(self):
217 id_, params = _build_data(self.apikey, 'get_user')
217 id_, params = _build_data(self.apikey, 'get_user')
218 response = api_call(self, params)
218 response = api_call(self, params)
219
219
220 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
220 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
221 ret = usr.get_api_data()
221 ret = usr.get_api_data()
222 ret['permissions'] = AuthUser(usr.user_id).permissions
222 ret['permissions'] = AuthUser(usr.user_id).permissions
223
223
224 expected = ret
224 expected = ret
225 self._compare_ok(id_, expected, given=response.body)
225 self._compare_ok(id_, expected, given=response.body)
226
226
227 def test_api_get_user_without_giving_userid_non_admin(self):
227 def test_api_get_user_without_giving_userid_non_admin(self):
228 id_, params = _build_data(self.apikey_regular, 'get_user')
228 id_, params = _build_data(self.apikey_regular, 'get_user')
229 response = api_call(self, params)
229 response = api_call(self, params)
230
230
231 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
231 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
232 ret = usr.get_api_data()
232 ret = usr.get_api_data()
233 ret['permissions'] = AuthUser(usr.user_id).permissions
233 ret['permissions'] = AuthUser(usr.user_id).permissions
234
234
235 expected = ret
235 expected = ret
236 self._compare_ok(id_, expected, given=response.body)
236 self._compare_ok(id_, expected, given=response.body)
237
237
238 def test_api_get_user_with_giving_userid_non_admin(self):
238 def test_api_get_user_with_giving_userid_non_admin(self):
239 id_, params = _build_data(self.apikey_regular, 'get_user',
239 id_, params = _build_data(self.apikey_regular, 'get_user',
240 userid=self.TEST_USER_LOGIN)
240 userid=self.TEST_USER_LOGIN)
241 response = api_call(self, params)
241 response = api_call(self, params)
242
242
243 expected = 'userid is not the same as your user'
243 expected = 'userid is not the same as your user'
244 self._compare_error(id_, expected, given=response.body)
244 self._compare_error(id_, expected, given=response.body)
245
245
246 def test_api_pull(self):
246 def test_api_pull(self):
247 #TODO: issues with rhodecode_extras here.. not sure why !
247 #TODO: issues with rhodecode_extras here.. not sure why !
248 pass
248 pass
249
249
250 # repo_name = 'test_pull'
250 # repo_name = 'test_pull'
251 # r = create_repo(repo_name, self.REPO_TYPE)
251 # r = create_repo(repo_name, self.REPO_TYPE)
252 # r.clone_uri = TEST_self.REPO
252 # r.clone_uri = TEST_self.REPO
253 # Session.add(r)
253 # Session.add(r)
254 # Session.commit()
254 # Session.commit()
255 #
255 #
256 # id_, params = _build_data(self.apikey, 'pull',
256 # id_, params = _build_data(self.apikey, 'pull',
257 # repoid=repo_name,)
257 # repoid=repo_name,)
258 # response = self.app.post(API_URL, content_type='application/json',
258 # response = self.app.post(API_URL, content_type='application/json',
259 # params=params)
259 # params=params)
260 #
260 #
261 # expected = 'Pulled from `%s`' % repo_name
261 # expected = 'Pulled from `%s`' % repo_name
262 # self._compare_ok(id_, expected, given=response.body)
262 # self._compare_ok(id_, expected, given=response.body)
263 #
263 #
264 # destroy_repo(repo_name)
264 # destroy_repo(repo_name)
265
265
266 def test_api_pull_error(self):
266 def test_api_pull_error(self):
267 id_, params = _build_data(self.apikey, 'pull',
267 id_, params = _build_data(self.apikey, 'pull',
268 repoid=self.REPO,)
268 repoid=self.REPO,)
269 response = api_call(self, params)
269 response = api_call(self, params)
270
270
271 expected = 'Unable to pull changes from `%s`' % self.REPO
271 expected = 'Unable to pull changes from `%s`' % self.REPO
272 self._compare_error(id_, expected, given=response.body)
272 self._compare_error(id_, expected, given=response.body)
273
273
274 def test_api_rescan_repos(self):
274 def test_api_rescan_repos(self):
275 id_, params = _build_data(self.apikey, 'rescan_repos')
275 id_, params = _build_data(self.apikey, 'rescan_repos')
276 response = api_call(self, params)
276 response = api_call(self, params)
277
277
278 expected = {'added': [], 'removed': []}
278 expected = {'added': [], 'removed': []}
279 self._compare_ok(id_, expected, given=response.body)
279 self._compare_ok(id_, expected, given=response.body)
280
280
281 @mock.patch.object(ScmModel, 'repo_scan', crash)
281 @mock.patch.object(ScmModel, 'repo_scan', crash)
282 def test_api_rescann_error(self):
282 def test_api_rescann_error(self):
283 id_, params = _build_data(self.apikey, 'rescan_repos',)
283 id_, params = _build_data(self.apikey, 'rescan_repos',)
284 response = api_call(self, params)
284 response = api_call(self, params)
285
285
286 expected = 'Error occurred during rescan repositories action'
286 expected = 'Error occurred during rescan repositories action'
287 self._compare_error(id_, expected, given=response.body)
287 self._compare_error(id_, expected, given=response.body)
288
288
289 def test_api_lock_repo_lock_aquire(self):
289 def test_api_lock_repo_lock_aquire(self):
290 id_, params = _build_data(self.apikey, 'lock',
290 id_, params = _build_data(self.apikey, 'lock',
291 userid=TEST_USER_ADMIN_LOGIN,
291 userid=TEST_USER_ADMIN_LOGIN,
292 repoid=self.REPO,
292 repoid=self.REPO,
293 locked=True)
293 locked=True)
294 response = api_call(self, params)
294 response = api_call(self, params)
295 expected = ('User `%s` set lock state for repo `%s` to `%s`'
295 expected = ('User `%s` set lock state for repo `%s` to `%s`'
296 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
296 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
297 self._compare_ok(id_, expected, given=response.body)
297 self._compare_ok(id_, expected, given=response.body)
298
298
299 def test_api_lock_repo_lock_aquire_by_non_admin(self):
299 def test_api_lock_repo_lock_aquire_by_non_admin(self):
300 repo_name = 'api_delete_me'
300 repo_name = 'api_delete_me'
301 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
301 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
302 try:
302 try:
303 id_, params = _build_data(self.apikey_regular, 'lock',
303 id_, params = _build_data(self.apikey_regular, 'lock',
304 repoid=repo_name,
304 repoid=repo_name,
305 locked=True)
305 locked=True)
306 response = api_call(self, params)
306 response = api_call(self, params)
307 expected = ('User `%s` set lock state for repo `%s` to `%s`'
307 expected = ('User `%s` set lock state for repo `%s` to `%s`'
308 % (self.TEST_USER_LOGIN, repo_name, True))
308 % (self.TEST_USER_LOGIN, repo_name, True))
309 self._compare_ok(id_, expected, given=response.body)
309 self._compare_ok(id_, expected, given=response.body)
310 finally:
310 finally:
311 destroy_repo(repo_name)
311 destroy_repo(repo_name)
312
312
313 def test_api_lock_repo_lock_aquire_non_admin_with_userid(self):
313 def test_api_lock_repo_lock_aquire_non_admin_with_userid(self):
314 repo_name = 'api_delete_me'
314 repo_name = 'api_delete_me'
315 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
315 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
316 try:
316 try:
317 id_, params = _build_data(self.apikey_regular, 'lock',
317 id_, params = _build_data(self.apikey_regular, 'lock',
318 userid=TEST_USER_ADMIN_LOGIN,
318 userid=TEST_USER_ADMIN_LOGIN,
319 repoid=repo_name,
319 repoid=repo_name,
320 locked=True)
320 locked=True)
321 response = api_call(self, params)
321 response = api_call(self, params)
322 expected = 'userid is not the same as your user'
322 expected = 'userid is not the same as your user'
323 self._compare_error(id_, expected, given=response.body)
323 self._compare_error(id_, expected, given=response.body)
324 finally:
324 finally:
325 destroy_repo(repo_name)
325 destroy_repo(repo_name)
326
326
327 def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self):
327 def test_api_lock_repo_lock_aquire_non_admin_not_his_repo(self):
328 id_, params = _build_data(self.apikey_regular, 'lock',
328 id_, params = _build_data(self.apikey_regular, 'lock',
329 repoid=self.REPO,
329 repoid=self.REPO,
330 locked=True)
330 locked=True)
331 response = api_call(self, params)
331 response = api_call(self, params)
332 expected = 'repository `%s` does not exist' % (self.REPO)
332 expected = 'repository `%s` does not exist' % (self.REPO)
333 self._compare_error(id_, expected, given=response.body)
333 self._compare_error(id_, expected, given=response.body)
334
334
335 def test_api_lock_repo_lock_release(self):
335 def test_api_lock_repo_lock_release(self):
336 id_, params = _build_data(self.apikey, 'lock',
336 id_, params = _build_data(self.apikey, 'lock',
337 userid=TEST_USER_ADMIN_LOGIN,
337 userid=TEST_USER_ADMIN_LOGIN,
338 repoid=self.REPO,
338 repoid=self.REPO,
339 locked=False)
339 locked=False)
340 response = api_call(self, params)
340 response = api_call(self, params)
341 expected = ('User `%s` set lock state for repo `%s` to `%s`'
341 expected = ('User `%s` set lock state for repo `%s` to `%s`'
342 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
342 % (TEST_USER_ADMIN_LOGIN, self.REPO, False))
343 self._compare_ok(id_, expected, given=response.body)
343 self._compare_ok(id_, expected, given=response.body)
344
344
345 def test_api_lock_repo_lock_aquire_optional_userid(self):
345 def test_api_lock_repo_lock_aquire_optional_userid(self):
346 id_, params = _build_data(self.apikey, 'lock',
346 id_, params = _build_data(self.apikey, 'lock',
347 repoid=self.REPO,
347 repoid=self.REPO,
348 locked=True)
348 locked=True)
349 response = api_call(self, params)
349 response = api_call(self, params)
350 expected = ('User `%s` set lock state for repo `%s` to `%s`'
350 expected = ('User `%s` set lock state for repo `%s` to `%s`'
351 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
351 % (TEST_USER_ADMIN_LOGIN, self.REPO, True))
352 self._compare_ok(id_, expected, given=response.body)
352 self._compare_ok(id_, expected, given=response.body)
353
353
354 @mock.patch.object(Repository, 'lock', crash)
354 @mock.patch.object(Repository, 'lock', crash)
355 def test_api_lock_error(self):
355 def test_api_lock_error(self):
356 id_, params = _build_data(self.apikey, 'lock',
356 id_, params = _build_data(self.apikey, 'lock',
357 userid=TEST_USER_ADMIN_LOGIN,
357 userid=TEST_USER_ADMIN_LOGIN,
358 repoid=self.REPO,
358 repoid=self.REPO,
359 locked=True)
359 locked=True)
360 response = api_call(self, params)
360 response = api_call(self, params)
361
361
362 expected = 'Error occurred locking repository `%s`' % self.REPO
362 expected = 'Error occurred locking repository `%s`' % self.REPO
363 self._compare_error(id_, expected, given=response.body)
363 self._compare_error(id_, expected, given=response.body)
364
364
365 def test_api_create_existing_user(self):
365 def test_api_create_existing_user(self):
366 id_, params = _build_data(self.apikey, 'create_user',
366 id_, params = _build_data(self.apikey, 'create_user',
367 username=TEST_USER_ADMIN_LOGIN,
367 username=TEST_USER_ADMIN_LOGIN,
368 email='test@foo.com',
368 email='test@foo.com',
369 password='trololo')
369 password='trololo')
370 response = api_call(self, params)
370 response = api_call(self, params)
371
371
372 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
372 expected = "user `%s` already exist" % TEST_USER_ADMIN_LOGIN
373 self._compare_error(id_, expected, given=response.body)
373 self._compare_error(id_, expected, given=response.body)
374
374
375 def test_api_create_user_with_existing_email(self):
375 def test_api_create_user_with_existing_email(self):
376 id_, params = _build_data(self.apikey, 'create_user',
376 id_, params = _build_data(self.apikey, 'create_user',
377 username=TEST_USER_ADMIN_LOGIN + 'new',
377 username=TEST_USER_ADMIN_LOGIN + 'new',
378 email=TEST_USER_REGULAR_EMAIL,
378 email=TEST_USER_REGULAR_EMAIL,
379 password='trololo')
379 password='trololo')
380 response = api_call(self, params)
380 response = api_call(self, params)
381
381
382 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
382 expected = "email `%s` already exist" % TEST_USER_REGULAR_EMAIL
383 self._compare_error(id_, expected, given=response.body)
383 self._compare_error(id_, expected, given=response.body)
384
384
385 def test_api_create_user(self):
385 def test_api_create_user(self):
386 username = 'test_new_api_user'
386 username = 'test_new_api_user'
387 email = username + "@foo.com"
387 email = username + "@foo.com"
388
388
389 id_, params = _build_data(self.apikey, 'create_user',
389 id_, params = _build_data(self.apikey, 'create_user',
390 username=username,
390 username=username,
391 email=email,
391 email=email,
392 password='trololo')
392 password='trololo')
393 response = api_call(self, params)
393 response = api_call(self, params)
394
394
395 usr = UserModel().get_by_username(username)
395 usr = UserModel().get_by_username(username)
396 ret = dict(
396 ret = dict(
397 msg='created new user `%s`' % username,
397 msg='created new user `%s`' % username,
398 user=jsonify(usr.get_api_data())
398 user=jsonify(usr.get_api_data())
399 )
399 )
400
400
401 expected = ret
401 expected = ret
402 self._compare_ok(id_, expected, given=response.body)
402 self._compare_ok(id_, expected, given=response.body)
403
403
404 UserModel().delete(usr.user_id)
404 UserModel().delete(usr.user_id)
405 Session().commit()
405 Session().commit()
406
406
407 @mock.patch.object(UserModel, 'create_or_update', crash)
407 @mock.patch.object(UserModel, 'create_or_update', crash)
408 def test_api_create_user_when_exception_happened(self):
408 def test_api_create_user_when_exception_happened(self):
409
409
410 username = 'test_new_api_user'
410 username = 'test_new_api_user'
411 email = username + "@foo.com"
411 email = username + "@foo.com"
412
412
413 id_, params = _build_data(self.apikey, 'create_user',
413 id_, params = _build_data(self.apikey, 'create_user',
414 username=username,
414 username=username,
415 email=email,
415 email=email,
416 password='trololo')
416 password='trololo')
417 response = api_call(self, params)
417 response = api_call(self, params)
418 expected = 'failed to create user `%s`' % username
418 expected = 'failed to create user `%s`' % username
419 self._compare_error(id_, expected, given=response.body)
419 self._compare_error(id_, expected, given=response.body)
420
420
421 def test_api_delete_user(self):
421 def test_api_delete_user(self):
422 usr = UserModel().create_or_update(username=u'test_user',
422 usr = UserModel().create_or_update(username=u'test_user',
423 password=u'qweqwe',
423 password=u'qweqwe',
424 email=u'u232@rhodecode.org',
424 email=u'u232@rhodecode.org',
425 firstname=u'u1', lastname=u'u1')
425 firstname=u'u1', lastname=u'u1')
426 Session().commit()
426 Session().commit()
427 username = usr.username
427 username = usr.username
428 email = usr.email
428 email = usr.email
429 usr_id = usr.user_id
429 usr_id = usr.user_id
430 ## DELETE THIS USER NOW
430 ## DELETE THIS USER NOW
431
431
432 id_, params = _build_data(self.apikey, 'delete_user',
432 id_, params = _build_data(self.apikey, 'delete_user',
433 userid=username,)
433 userid=username,)
434 response = api_call(self, params)
434 response = api_call(self, params)
435
435
436 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
436 ret = {'msg': 'deleted user ID:%s %s' % (usr_id, username),
437 'user': None}
437 'user': None}
438 expected = ret
438 expected = ret
439 self._compare_ok(id_, expected, given=response.body)
439 self._compare_ok(id_, expected, given=response.body)
440
440
441 @mock.patch.object(UserModel, 'delete', crash)
441 @mock.patch.object(UserModel, 'delete', crash)
442 def test_api_delete_user_when_exception_happened(self):
442 def test_api_delete_user_when_exception_happened(self):
443 usr = UserModel().create_or_update(username=u'test_user',
443 usr = UserModel().create_or_update(username=u'test_user',
444 password=u'qweqwe',
444 password=u'qweqwe',
445 email=u'u232@rhodecode.org',
445 email=u'u232@rhodecode.org',
446 firstname=u'u1', lastname=u'u1')
446 firstname=u'u1', lastname=u'u1')
447 Session().commit()
447 Session().commit()
448 username = usr.username
448 username = usr.username
449
449
450 id_, params = _build_data(self.apikey, 'delete_user',
450 id_, params = _build_data(self.apikey, 'delete_user',
451 userid=username,)
451 userid=username,)
452 response = api_call(self, params)
452 response = api_call(self, params)
453 ret = 'failed to delete ID:%s %s' % (usr.user_id,
453 ret = 'failed to delete ID:%s %s' % (usr.user_id,
454 usr.username)
454 usr.username)
455 expected = ret
455 expected = ret
456 self._compare_error(id_, expected, given=response.body)
456 self._compare_error(id_, expected, given=response.body)
457
457
458 @parameterized.expand([('firstname', 'new_username'),
458 @parameterized.expand([('firstname', 'new_username'),
459 ('lastname', 'new_username'),
459 ('lastname', 'new_username'),
460 ('email', 'new_username'),
460 ('email', 'new_username'),
461 ('admin', True),
461 ('admin', True),
462 ('admin', False),
462 ('admin', False),
463 ('ldap_dn', 'test'),
463 ('ldap_dn', 'test'),
464 ('ldap_dn', None),
464 ('ldap_dn', None),
465 ('active', False),
465 ('active', False),
466 ('active', True),
466 ('active', True),
467 ('password', 'newpass')
467 ('password', 'newpass')
468 ])
468 ])
469 def test_api_update_user(self, name, expected):
469 def test_api_update_user(self, name, expected):
470 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
470 usr = UserModel().get_by_username(self.TEST_USER_LOGIN)
471 kw = {name: expected,
471 kw = {name: expected,
472 'userid': usr.user_id}
472 'userid': usr.user_id}
473 id_, params = _build_data(self.apikey, 'update_user', **kw)
473 id_, params = _build_data(self.apikey, 'update_user', **kw)
474 response = api_call(self, params)
474 response = api_call(self, params)
475
475
476 ret = {
476 ret = {
477 'msg': 'updated user ID:%s %s' % (usr.user_id, self.TEST_USER_LOGIN),
477 'msg': 'updated user ID:%s %s' % (usr.user_id, self.TEST_USER_LOGIN),
478 'user': jsonify(UserModel()\
478 'user': jsonify(UserModel()\
479 .get_by_username(self.TEST_USER_LOGIN)\
479 .get_by_username(self.TEST_USER_LOGIN)\
480 .get_api_data())
480 .get_api_data())
481 }
481 }
482
482
483 expected = ret
483 expected = ret
484 self._compare_ok(id_, expected, given=response.body)
484 self._compare_ok(id_, expected, given=response.body)
485
485
486 def test_api_update_user_no_changed_params(self):
486 def test_api_update_user_no_changed_params(self):
487 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
487 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
488 ret = jsonify(usr.get_api_data())
488 ret = jsonify(usr.get_api_data())
489 id_, params = _build_data(self.apikey, 'update_user',
489 id_, params = _build_data(self.apikey, 'update_user',
490 userid=TEST_USER_ADMIN_LOGIN)
490 userid=TEST_USER_ADMIN_LOGIN)
491
491
492 response = api_call(self, params)
492 response = api_call(self, params)
493 ret = {
493 ret = {
494 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
494 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
495 'user': ret
495 'user': ret
496 }
496 }
497 expected = ret
497 expected = ret
498 self._compare_ok(id_, expected, given=response.body)
498 self._compare_ok(id_, expected, given=response.body)
499
499
500 def test_api_update_user_by_user_id(self):
500 def test_api_update_user_by_user_id(self):
501 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
501 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
502 ret = jsonify(usr.get_api_data())
502 ret = jsonify(usr.get_api_data())
503 id_, params = _build_data(self.apikey, 'update_user',
503 id_, params = _build_data(self.apikey, 'update_user',
504 userid=usr.user_id)
504 userid=usr.user_id)
505
505
506 response = api_call(self, params)
506 response = api_call(self, params)
507 ret = {
507 ret = {
508 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
508 'msg': 'updated user ID:%s %s' % (usr.user_id, TEST_USER_ADMIN_LOGIN),
509 'user': ret
509 'user': ret
510 }
510 }
511 expected = ret
511 expected = ret
512 self._compare_ok(id_, expected, given=response.body)
512 self._compare_ok(id_, expected, given=response.body)
513
513
514 @mock.patch.object(UserModel, 'update_user', crash)
514 @mock.patch.object(UserModel, 'update_user', crash)
515 def test_api_update_user_when_exception_happens(self):
515 def test_api_update_user_when_exception_happens(self):
516 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
516 usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
517 ret = jsonify(usr.get_api_data())
517 ret = jsonify(usr.get_api_data())
518 id_, params = _build_data(self.apikey, 'update_user',
518 id_, params = _build_data(self.apikey, 'update_user',
519 userid=usr.user_id)
519 userid=usr.user_id)
520
520
521 response = api_call(self, params)
521 response = api_call(self, params)
522 ret = 'failed to update user `%s`' % usr.user_id
522 ret = 'failed to update user `%s`' % usr.user_id
523
523
524 expected = ret
524 expected = ret
525 self._compare_error(id_, expected, given=response.body)
525 self._compare_error(id_, expected, given=response.body)
526
526
527 def test_api_get_repo(self):
527 def test_api_get_repo(self):
528 new_group = 'some_new_group'
528 new_group = 'some_new_group'
529 make_users_group(new_group)
529 make_users_group(new_group)
530 RepoModel().grant_users_group_permission(repo=self.REPO,
530 RepoModel().grant_users_group_permission(repo=self.REPO,
531 group_name=new_group,
531 group_name=new_group,
532 perm='repository.read')
532 perm='repository.read')
533 Session().commit()
533 Session().commit()
534 id_, params = _build_data(self.apikey, 'get_repo',
534 id_, params = _build_data(self.apikey, 'get_repo',
535 repoid=self.REPO)
535 repoid=self.REPO)
536 response = api_call(self, params)
536 response = api_call(self, params)
537
537
538 repo = RepoModel().get_by_repo_name(self.REPO)
538 repo = RepoModel().get_by_repo_name(self.REPO)
539 ret = repo.get_api_data()
539 ret = repo.get_api_data()
540
540
541 members = []
541 members = []
542 followers = []
542 followers = []
543 for user in repo.repo_to_perm:
543 for user in repo.repo_to_perm:
544 perm = user.permission.permission_name
544 perm = user.permission.permission_name
545 user = user.user
545 user = user.user
546 user_data = user.get_api_data()
546 user_data = user.get_api_data()
547 user_data['type'] = "user"
547 user_data['type'] = "user"
548 user_data['permission'] = perm
548 user_data['permission'] = perm
549 members.append(user_data)
549 members.append(user_data)
550
550
551 for users_group in repo.users_group_to_perm:
551 for users_group in repo.users_group_to_perm:
552 perm = users_group.permission.permission_name
552 perm = users_group.permission.permission_name
553 users_group = users_group.users_group
553 users_group = users_group.users_group
554 users_group_data = users_group.get_api_data()
554 users_group_data = users_group.get_api_data()
555 users_group_data['type'] = "users_group"
555 users_group_data['type'] = "users_group"
556 users_group_data['permission'] = perm
556 users_group_data['permission'] = perm
557 members.append(users_group_data)
557 members.append(users_group_data)
558
558
559 for user in repo.followers:
559 for user in repo.followers:
560 followers.append(user.user.get_api_data())
560 followers.append(user.user.get_api_data())
561
561
562 ret['members'] = members
562 ret['members'] = members
563 ret['followers'] = followers
563 ret['followers'] = followers
564
564
565 expected = ret
565 expected = ret
566 self._compare_ok(id_, expected, given=response.body)
566 self._compare_ok(id_, expected, given=response.body)
567 destroy_users_group(new_group)
567 destroy_users_group(new_group)
568
568
569 def test_api_get_repo_by_non_admin(self):
569 def test_api_get_repo_by_non_admin(self):
570 id_, params = _build_data(self.apikey, 'get_repo',
570 id_, params = _build_data(self.apikey, 'get_repo',
571 repoid=self.REPO)
571 repoid=self.REPO)
572 response = api_call(self, params)
572 response = api_call(self, params)
573
573
574 repo = RepoModel().get_by_repo_name(self.REPO)
574 repo = RepoModel().get_by_repo_name(self.REPO)
575 ret = repo.get_api_data()
575 ret = repo.get_api_data()
576
576
577 members = []
577 members = []
578 followers = []
578 followers = []
579 for user in repo.repo_to_perm:
579 for user in repo.repo_to_perm:
580 perm = user.permission.permission_name
580 perm = user.permission.permission_name
581 user = user.user
581 user = user.user
582 user_data = user.get_api_data()
582 user_data = user.get_api_data()
583 user_data['type'] = "user"
583 user_data['type'] = "user"
584 user_data['permission'] = perm
584 user_data['permission'] = perm
585 members.append(user_data)
585 members.append(user_data)
586
586
587 for users_group in repo.users_group_to_perm:
587 for users_group in repo.users_group_to_perm:
588 perm = users_group.permission.permission_name
588 perm = users_group.permission.permission_name
589 users_group = users_group.users_group
589 users_group = users_group.users_group
590 users_group_data = users_group.get_api_data()
590 users_group_data = users_group.get_api_data()
591 users_group_data['type'] = "users_group"
591 users_group_data['type'] = "users_group"
592 users_group_data['permission'] = perm
592 users_group_data['permission'] = perm
593 members.append(users_group_data)
593 members.append(users_group_data)
594
594
595 for user in repo.followers:
595 for user in repo.followers:
596 followers.append(user.user.get_api_data())
596 followers.append(user.user.get_api_data())
597
597
598 ret['members'] = members
598 ret['members'] = members
599 ret['followers'] = followers
599 ret['followers'] = followers
600
600
601 expected = ret
601 expected = ret
602 self._compare_ok(id_, expected, given=response.body)
602 self._compare_ok(id_, expected, given=response.body)
603
603
604 def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
604 def test_api_get_repo_by_non_admin_no_permission_to_repo(self):
605 RepoModel().grant_user_permission(repo=self.REPO,
605 RepoModel().grant_user_permission(repo=self.REPO,
606 user=self.TEST_USER_LOGIN,
606 user=self.TEST_USER_LOGIN,
607 perm='repository.none')
607 perm='repository.none')
608
608
609 id_, params = _build_data(self.apikey_regular, 'get_repo',
609 id_, params = _build_data(self.apikey_regular, 'get_repo',
610 repoid=self.REPO)
610 repoid=self.REPO)
611 response = api_call(self, params)
611 response = api_call(self, params)
612
612
613 expected = 'repository `%s` does not exist' % (self.REPO)
613 expected = 'repository `%s` does not exist' % (self.REPO)
614 self._compare_error(id_, expected, given=response.body)
614 self._compare_error(id_, expected, given=response.body)
615
615
616 def test_api_get_repo_that_doesn_not_exist(self):
616 def test_api_get_repo_that_doesn_not_exist(self):
617 id_, params = _build_data(self.apikey, 'get_repo',
617 id_, params = _build_data(self.apikey, 'get_repo',
618 repoid='no-such-repo')
618 repoid='no-such-repo')
619 response = api_call(self, params)
619 response = api_call(self, params)
620
620
621 ret = 'repository `%s` does not exist' % 'no-such-repo'
621 ret = 'repository `%s` does not exist' % 'no-such-repo'
622 expected = ret
622 expected = ret
623 self._compare_error(id_, expected, given=response.body)
623 self._compare_error(id_, expected, given=response.body)
624
624
625 def test_api_get_repos(self):
625 def test_api_get_repos(self):
626 id_, params = _build_data(self.apikey, 'get_repos')
626 id_, params = _build_data(self.apikey, 'get_repos')
627 response = api_call(self, params)
627 response = api_call(self, params)
628
628
629 result = []
629 result = []
630 for repo in RepoModel().get_all():
630 for repo in RepoModel().get_all():
631 result.append(repo.get_api_data())
631 result.append(repo.get_api_data())
632 ret = jsonify(result)
632 ret = jsonify(result)
633
633
634 expected = ret
634 expected = ret
635 self._compare_ok(id_, expected, given=response.body)
635 self._compare_ok(id_, expected, given=response.body)
636
636
637 def test_api_get_repos_non_admin(self):
637 def test_api_get_repos_non_admin(self):
638 id_, params = _build_data(self.apikey_regular, 'get_repos')
638 id_, params = _build_data(self.apikey_regular, 'get_repos')
639 response = api_call(self, params)
639 response = api_call(self, params)
640
640
641 result = []
641 result = []
642 for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN):
642 for repo in RepoModel().get_all_user_repos(self.TEST_USER_LOGIN):
643 result.append(repo.get_api_data())
643 result.append(repo.get_api_data())
644 ret = jsonify(result)
644 ret = jsonify(result)
645
645
646 expected = ret
646 expected = ret
647 self._compare_ok(id_, expected, given=response.body)
647 self._compare_ok(id_, expected, given=response.body)
648
648
649 @parameterized.expand([('all', 'all'),
649 @parameterized.expand([('all', 'all'),
650 ('dirs', 'dirs'),
650 ('dirs', 'dirs'),
651 ('files', 'files'), ])
651 ('files', 'files'), ])
652 def test_api_get_repo_nodes(self, name, ret_type):
652 def test_api_get_repo_nodes(self, name, ret_type):
653 rev = 'tip'
653 rev = 'tip'
654 path = '/'
654 path = '/'
655 id_, params = _build_data(self.apikey, 'get_repo_nodes',
655 id_, params = _build_data(self.apikey, 'get_repo_nodes',
656 repoid=self.REPO, revision=rev,
656 repoid=self.REPO, revision=rev,
657 root_path=path,
657 root_path=path,
658 ret_type=ret_type)
658 ret_type=ret_type)
659 response = api_call(self, params)
659 response = api_call(self, params)
660
660
661 # we don't the actual return types here since it's tested somewhere
661 # we don't the actual return types here since it's tested somewhere
662 # else
662 # else
663 expected = json.loads(response.body)['result']
663 expected = json.loads(response.body)['result']
664 self._compare_ok(id_, expected, given=response.body)
664 self._compare_ok(id_, expected, given=response.body)
665
665
666 def test_api_get_repo_nodes_bad_revisions(self):
666 def test_api_get_repo_nodes_bad_revisions(self):
667 rev = 'i-dont-exist'
667 rev = 'i-dont-exist'
668 path = '/'
668 path = '/'
669 id_, params = _build_data(self.apikey, 'get_repo_nodes',
669 id_, params = _build_data(self.apikey, 'get_repo_nodes',
670 repoid=self.REPO, revision=rev,
670 repoid=self.REPO, revision=rev,
671 root_path=path,)
671 root_path=path,)
672 response = api_call(self, params)
672 response = api_call(self, params)
673
673
674 expected = 'failed to get repo: `%s` nodes' % self.REPO
674 expected = 'failed to get repo: `%s` nodes' % self.REPO
675 self._compare_error(id_, expected, given=response.body)
675 self._compare_error(id_, expected, given=response.body)
676
676
677 def test_api_get_repo_nodes_bad_path(self):
677 def test_api_get_repo_nodes_bad_path(self):
678 rev = 'tip'
678 rev = 'tip'
679 path = '/idontexits'
679 path = '/idontexits'
680 id_, params = _build_data(self.apikey, 'get_repo_nodes',
680 id_, params = _build_data(self.apikey, 'get_repo_nodes',
681 repoid=self.REPO, revision=rev,
681 repoid=self.REPO, revision=rev,
682 root_path=path,)
682 root_path=path,)
683 response = api_call(self, params)
683 response = api_call(self, params)
684
684
685 expected = 'failed to get repo: `%s` nodes' % self.REPO
685 expected = 'failed to get repo: `%s` nodes' % self.REPO
686 self._compare_error(id_, expected, given=response.body)
686 self._compare_error(id_, expected, given=response.body)
687
687
688 def test_api_get_repo_nodes_bad_ret_type(self):
688 def test_api_get_repo_nodes_bad_ret_type(self):
689 rev = 'tip'
689 rev = 'tip'
690 path = '/'
690 path = '/'
691 ret_type = 'error'
691 ret_type = 'error'
692 id_, params = _build_data(self.apikey, 'get_repo_nodes',
692 id_, params = _build_data(self.apikey, 'get_repo_nodes',
693 repoid=self.REPO, revision=rev,
693 repoid=self.REPO, revision=rev,
694 root_path=path,
694 root_path=path,
695 ret_type=ret_type)
695 ret_type=ret_type)
696 response = api_call(self, params)
696 response = api_call(self, params)
697
697
698 expected = 'ret_type must be one of %s' % (['files', 'dirs', 'all'])
698 expected = 'ret_type must be one of %s' % (['files', 'dirs', 'all'])
699 self._compare_error(id_, expected, given=response.body)
699 self._compare_error(id_, expected, given=response.body)
700
700
701 def test_api_create_repo(self):
701 def test_api_create_repo(self):
702 repo_name = 'api-repo'
702 repo_name = 'api-repo'
703 id_, params = _build_data(self.apikey, 'create_repo',
703 id_, params = _build_data(self.apikey, 'create_repo',
704 repo_name=repo_name,
704 repo_name=repo_name,
705 owner=TEST_USER_ADMIN_LOGIN,
705 owner=TEST_USER_ADMIN_LOGIN,
706 repo_type='hg',
706 repo_type='hg',
707 )
707 )
708 response = api_call(self, params)
708 response = api_call(self, params)
709
709
710 repo = RepoModel().get_by_repo_name(repo_name)
710 repo = RepoModel().get_by_repo_name(repo_name)
711 ret = {
711 ret = {
712 'msg': 'Created new repository `%s`' % repo_name,
712 'msg': 'Created new repository `%s`' % repo_name,
713 'repo': jsonify(repo.get_api_data())
713 'repo': jsonify(repo.get_api_data())
714 }
714 }
715 expected = ret
715 expected = ret
716 self._compare_ok(id_, expected, given=response.body)
716 self._compare_ok(id_, expected, given=response.body)
717 destroy_repo(repo_name)
717 destroy_repo(repo_name)
718
718
719 def test_api_create_repo_unknown_owner(self):
719 def test_api_create_repo_unknown_owner(self):
720 repo_name = 'api-repo'
720 repo_name = 'api-repo'
721 owner = 'i-dont-exist'
721 owner = 'i-dont-exist'
722 id_, params = _build_data(self.apikey, 'create_repo',
722 id_, params = _build_data(self.apikey, 'create_repo',
723 repo_name=repo_name,
723 repo_name=repo_name,
724 owner=owner,
724 owner=owner,
725 repo_type='hg',
725 repo_type='hg',
726 )
726 )
727 response = api_call(self, params)
727 response = api_call(self, params)
728 expected = 'user `%s` does not exist' % owner
728 expected = 'user `%s` does not exist' % owner
729 self._compare_error(id_, expected, given=response.body)
729 self._compare_error(id_, expected, given=response.body)
730
730
731 def test_api_create_repo_dont_specify_owner(self):
731 def test_api_create_repo_dont_specify_owner(self):
732 repo_name = 'api-repo'
732 repo_name = 'api-repo'
733 owner = 'i-dont-exist'
733 owner = 'i-dont-exist'
734 id_, params = _build_data(self.apikey, 'create_repo',
734 id_, params = _build_data(self.apikey, 'create_repo',
735 repo_name=repo_name,
735 repo_name=repo_name,
736 repo_type='hg',
736 repo_type='hg',
737 )
737 )
738 response = api_call(self, params)
738 response = api_call(self, params)
739
739
740 repo = RepoModel().get_by_repo_name(repo_name)
740 repo = RepoModel().get_by_repo_name(repo_name)
741 ret = {
741 ret = {
742 'msg': 'Created new repository `%s`' % repo_name,
742 'msg': 'Created new repository `%s`' % repo_name,
743 'repo': jsonify(repo.get_api_data())
743 'repo': jsonify(repo.get_api_data())
744 }
744 }
745 expected = ret
745 expected = ret
746 self._compare_ok(id_, expected, given=response.body)
746 self._compare_ok(id_, expected, given=response.body)
747 destroy_repo(repo_name)
747 destroy_repo(repo_name)
748
748
749 def test_api_create_repo_by_non_admin(self):
749 def test_api_create_repo_by_non_admin(self):
750 repo_name = 'api-repo'
750 repo_name = 'api-repo'
751 owner = 'i-dont-exist'
751 owner = 'i-dont-exist'
752 id_, params = _build_data(self.apikey_regular, 'create_repo',
752 id_, params = _build_data(self.apikey_regular, 'create_repo',
753 repo_name=repo_name,
753 repo_name=repo_name,
754 repo_type='hg',
754 repo_type='hg',
755 )
755 )
756 response = api_call(self, params)
756 response = api_call(self, params)
757
757
758 repo = RepoModel().get_by_repo_name(repo_name)
758 repo = RepoModel().get_by_repo_name(repo_name)
759 ret = {
759 ret = {
760 'msg': 'Created new repository `%s`' % repo_name,
760 'msg': 'Created new repository `%s`' % repo_name,
761 'repo': jsonify(repo.get_api_data())
761 'repo': jsonify(repo.get_api_data())
762 }
762 }
763 expected = ret
763 expected = ret
764 self._compare_ok(id_, expected, given=response.body)
764 self._compare_ok(id_, expected, given=response.body)
765 destroy_repo(repo_name)
765 destroy_repo(repo_name)
766
766
767 def test_api_create_repo_by_non_admin_specify_owner(self):
767 def test_api_create_repo_by_non_admin_specify_owner(self):
768 repo_name = 'api-repo'
768 repo_name = 'api-repo'
769 owner = 'i-dont-exist'
769 owner = 'i-dont-exist'
770 id_, params = _build_data(self.apikey_regular, 'create_repo',
770 id_, params = _build_data(self.apikey_regular, 'create_repo',
771 repo_name=repo_name,
771 repo_name=repo_name,
772 repo_type='hg',
772 repo_type='hg',
773 owner=owner
773 owner=owner
774 )
774 )
775 response = api_call(self, params)
775 response = api_call(self, params)
776
776
777 expected = 'Only RhodeCode admin can specify `owner` param'
777 expected = 'Only RhodeCode admin can specify `owner` param'
778 self._compare_error(id_, expected, given=response.body)
778 self._compare_error(id_, expected, given=response.body)
779 destroy_repo(repo_name)
779 destroy_repo(repo_name)
780
780
781 def test_api_create_repo_exists(self):
781 def test_api_create_repo_exists(self):
782 repo_name = self.REPO
782 repo_name = self.REPO
783 id_, params = _build_data(self.apikey, 'create_repo',
783 id_, params = _build_data(self.apikey, 'create_repo',
784 repo_name=repo_name,
784 repo_name=repo_name,
785 owner=TEST_USER_ADMIN_LOGIN,
785 owner=TEST_USER_ADMIN_LOGIN,
786 repo_type='hg',
786 repo_type='hg',
787 )
787 )
788 response = api_call(self, params)
788 response = api_call(self, params)
789 expected = "repo `%s` already exist" % repo_name
789 expected = "repo `%s` already exist" % repo_name
790 self._compare_error(id_, expected, given=response.body)
790 self._compare_error(id_, expected, given=response.body)
791
791
792 @mock.patch.object(RepoModel, 'create_repo', crash)
792 @mock.patch.object(RepoModel, 'create_repo', crash)
793 def test_api_create_repo_exception_occurred(self):
793 def test_api_create_repo_exception_occurred(self):
794 repo_name = 'api-repo'
794 repo_name = 'api-repo'
795 id_, params = _build_data(self.apikey, 'create_repo',
795 id_, params = _build_data(self.apikey, 'create_repo',
796 repo_name=repo_name,
796 repo_name=repo_name,
797 owner=TEST_USER_ADMIN_LOGIN,
797 owner=TEST_USER_ADMIN_LOGIN,
798 repo_type='hg',
798 repo_type='hg',
799 )
799 )
800 response = api_call(self, params)
800 response = api_call(self, params)
801 expected = 'failed to create repository `%s`' % repo_name
801 expected = 'failed to create repository `%s`' % repo_name
802 self._compare_error(id_, expected, given=response.body)
802 self._compare_error(id_, expected, given=response.body)
803
803
804 def test_api_delete_repo(self):
804 def test_api_delete_repo(self):
805 repo_name = 'api_delete_me'
805 repo_name = 'api_delete_me'
806 create_repo(repo_name, self.REPO_TYPE)
806 create_repo(repo_name, self.REPO_TYPE)
807
807
808 id_, params = _build_data(self.apikey, 'delete_repo',
808 id_, params = _build_data(self.apikey, 'delete_repo',
809 repoid=repo_name,)
809 repoid=repo_name,)
810 response = api_call(self, params)
810 response = api_call(self, params)
811
811
812 ret = {
812 ret = {
813 'msg': 'Deleted repository `%s`' % repo_name,
813 'msg': 'Deleted repository `%s`' % repo_name,
814 'success': True
814 'success': True
815 }
815 }
816 expected = ret
816 expected = ret
817 self._compare_ok(id_, expected, given=response.body)
817 self._compare_ok(id_, expected, given=response.body)
818
818
819 def test_api_delete_repo_by_non_admin(self):
819 def test_api_delete_repo_by_non_admin(self):
820 repo_name = 'api_delete_me'
820 repo_name = 'api_delete_me'
821 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
821 create_repo(repo_name, self.REPO_TYPE, owner=self.TEST_USER_LOGIN)
822 try:
822 try:
823 id_, params = _build_data(self.apikey_regular, 'delete_repo',
823 id_, params = _build_data(self.apikey_regular, 'delete_repo',
824 repoid=repo_name,)
824 repoid=repo_name,)
825 response = api_call(self, params)
825 response = api_call(self, params)
826
826
827 ret = {
827 ret = {
828 'msg': 'Deleted repository `%s`' % repo_name,
828 'msg': 'Deleted repository `%s`' % repo_name,
829 'success': True
829 'success': True
830 }
830 }
831 expected = ret
831 expected = ret
832 self._compare_ok(id_, expected, given=response.body)
832 self._compare_ok(id_, expected, given=response.body)
833 finally:
833 finally:
834 destroy_repo(repo_name)
834 destroy_repo(repo_name)
835
835
836 def test_api_delete_repo_by_non_admin_no_permission(self):
836 def test_api_delete_repo_by_non_admin_no_permission(self):
837 repo_name = 'api_delete_me'
837 repo_name = 'api_delete_me'
838 create_repo(repo_name, self.REPO_TYPE)
838 create_repo(repo_name, self.REPO_TYPE)
839 try:
839 try:
840 id_, params = _build_data(self.apikey_regular, 'delete_repo',
840 id_, params = _build_data(self.apikey_regular, 'delete_repo',
841 repoid=repo_name,)
841 repoid=repo_name,)
842 response = api_call(self, params)
842 response = api_call(self, params)
843 expected = 'repository `%s` does not exist' % (repo_name)
843 expected = 'repository `%s` does not exist' % (repo_name)
844 self._compare_error(id_, expected, given=response.body)
844 self._compare_error(id_, expected, given=response.body)
845 finally:
845 finally:
846 destroy_repo(repo_name)
846 destroy_repo(repo_name)
847
847
848 def test_api_delete_repo_exception_occurred(self):
848 def test_api_delete_repo_exception_occurred(self):
849 repo_name = 'api_delete_me'
849 repo_name = 'api_delete_me'
850 create_repo(repo_name, self.REPO_TYPE)
850 create_repo(repo_name, self.REPO_TYPE)
851 try:
851 try:
852 with mock.patch.object(RepoModel, 'delete', crash):
852 with mock.patch.object(RepoModel, 'delete', crash):
853 id_, params = _build_data(self.apikey, 'delete_repo',
853 id_, params = _build_data(self.apikey, 'delete_repo',
854 repoid=repo_name,)
854 repoid=repo_name,)
855 response = api_call(self, params)
855 response = api_call(self, params)
856
856
857 expected = 'failed to delete repository `%s`' % repo_name
857 expected = 'failed to delete repository `%s`' % repo_name
858 self._compare_error(id_, expected, given=response.body)
858 self._compare_error(id_, expected, given=response.body)
859 finally:
859 finally:
860 destroy_repo(repo_name)
860 destroy_repo(repo_name)
861
861
862 def test_api_fork_repo(self):
862 def test_api_fork_repo(self):
863 fork_name = 'api-repo-fork'
863 fork_name = 'api-repo-fork'
864 id_, params = _build_data(self.apikey, 'fork_repo',
864 id_, params = _build_data(self.apikey, 'fork_repo',
865 repoid=self.REPO,
865 repoid=self.REPO,
866 fork_name=fork_name,
866 fork_name=fork_name,
867 owner=TEST_USER_ADMIN_LOGIN,
867 owner=TEST_USER_ADMIN_LOGIN,
868 )
868 )
869 response = api_call(self, params)
869 response = api_call(self, params)
870
870
871 ret = {
871 ret = {
872 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
872 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
873 fork_name),
873 fork_name),
874 'success': True
874 'success': True
875 }
875 }
876 expected = ret
876 expected = ret
877 self._compare_ok(id_, expected, given=response.body)
877 self._compare_ok(id_, expected, given=response.body)
878 destroy_repo(fork_name)
878 destroy_repo(fork_name)
879
879
880 def test_api_fork_repo_non_admin(self):
880 def test_api_fork_repo_non_admin(self):
881 fork_name = 'api-repo-fork'
881 fork_name = 'api-repo-fork'
882 id_, params = _build_data(self.apikey_regular, 'fork_repo',
882 id_, params = _build_data(self.apikey_regular, 'fork_repo',
883 repoid=self.REPO,
883 repoid=self.REPO,
884 fork_name=fork_name,
884 fork_name=fork_name,
885 )
885 )
886 response = api_call(self, params)
886 response = api_call(self, params)
887
887
888 ret = {
888 ret = {
889 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
889 'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
890 fork_name),
890 fork_name),
891 'success': True
891 'success': True
892 }
892 }
893 expected = ret
893 expected = ret
894 self._compare_ok(id_, expected, given=response.body)
894 self._compare_ok(id_, expected, given=response.body)
895 destroy_repo(fork_name)
895 destroy_repo(fork_name)
896
896
897 def test_api_fork_repo_non_admin_specify_owner(self):
897 def test_api_fork_repo_non_admin_specify_owner(self):
898 fork_name = 'api-repo-fork'
898 fork_name = 'api-repo-fork'
899 id_, params = _build_data(self.apikey_regular, 'fork_repo',
899 id_, params = _build_data(self.apikey_regular, 'fork_repo',
900 repoid=self.REPO,
900 repoid=self.REPO,
901 fork_name=fork_name,
901 fork_name=fork_name,
902 owner=TEST_USER_ADMIN_LOGIN,
902 owner=TEST_USER_ADMIN_LOGIN,
903 )
903 )
904 response = api_call(self, params)
904 response = api_call(self, params)
905 expected = 'Only RhodeCode admin can specify `owner` param'
905 expected = 'Only RhodeCode admin can specify `owner` param'
906 self._compare_error(id_, expected, given=response.body)
906 self._compare_error(id_, expected, given=response.body)
907 destroy_repo(fork_name)
907 destroy_repo(fork_name)
908
908
909 def test_api_fork_repo_non_admin_no_permission_to_fork(self):
909 def test_api_fork_repo_non_admin_no_permission_to_fork(self):
910 RepoModel().grant_user_permission(repo=self.REPO,
910 RepoModel().grant_user_permission(repo=self.REPO,
911 user=self.TEST_USER_LOGIN,
911 user=self.TEST_USER_LOGIN,
912 perm='repository.none')
912 perm='repository.none')
913 fork_name = 'api-repo-fork'
913 fork_name = 'api-repo-fork'
914 id_, params = _build_data(self.apikey_regular, 'fork_repo',
914 id_, params = _build_data(self.apikey_regular, 'fork_repo',
915 repoid=self.REPO,
915 repoid=self.REPO,
916 fork_name=fork_name,
916 fork_name=fork_name,
917 )
917 )
918 response = api_call(self, params)
918 response = api_call(self, params)
919 expected = 'repository `%s` does not exist' % (self.REPO)
919 expected = 'repository `%s` does not exist' % (self.REPO)
920 self._compare_error(id_, expected, given=response.body)
920 self._compare_error(id_, expected, given=response.body)
921 destroy_repo(fork_name)
921 destroy_repo(fork_name)
922
922
923 def test_api_fork_repo_unknown_owner(self):
923 def test_api_fork_repo_unknown_owner(self):
924 fork_name = 'api-repo-fork'
924 fork_name = 'api-repo-fork'
925 owner = 'i-dont-exist'
925 owner = 'i-dont-exist'
926 id_, params = _build_data(self.apikey, 'fork_repo',
926 id_, params = _build_data(self.apikey, 'fork_repo',
927 repoid=self.REPO,
927 repoid=self.REPO,
928 fork_name=fork_name,
928 fork_name=fork_name,
929 owner=owner,
929 owner=owner,
930 )
930 )
931 response = api_call(self, params)
931 response = api_call(self, params)
932 expected = 'user `%s` does not exist' % owner
932 expected = 'user `%s` does not exist' % owner
933 self._compare_error(id_, expected, given=response.body)
933 self._compare_error(id_, expected, given=response.body)
934
934
935 def test_api_fork_repo_fork_exists(self):
935 def test_api_fork_repo_fork_exists(self):
936 fork_name = 'api-repo-fork'
936 fork_name = 'api-repo-fork'
937 create_fork(fork_name, self.REPO_TYPE, self.REPO)
937 create_fork(fork_name, self.REPO_TYPE, self.REPO)
938
938
939 try:
939 try:
940 fork_name = 'api-repo-fork'
940 fork_name = 'api-repo-fork'
941
941
942 id_, params = _build_data(self.apikey, 'fork_repo',
942 id_, params = _build_data(self.apikey, 'fork_repo',
943 repoid=self.REPO,
943 repoid=self.REPO,
944 fork_name=fork_name,
944 fork_name=fork_name,
945 owner=TEST_USER_ADMIN_LOGIN,
945 owner=TEST_USER_ADMIN_LOGIN,
946 )
946 )
947 response = api_call(self, params)
947 response = api_call(self, params)
948
948
949 expected = "fork `%s` already exist" % fork_name
949 expected = "fork `%s` already exist" % fork_name
950 self._compare_error(id_, expected, given=response.body)
950 self._compare_error(id_, expected, given=response.body)
951 finally:
951 finally:
952 destroy_repo(fork_name)
952 destroy_repo(fork_name)
953
953
954 def test_api_fork_repo_repo_exists(self):
954 def test_api_fork_repo_repo_exists(self):
955 fork_name = self.REPO
955 fork_name = self.REPO
956
956
957 id_, params = _build_data(self.apikey, 'fork_repo',
957 id_, params = _build_data(self.apikey, 'fork_repo',
958 repoid=self.REPO,
958 repoid=self.REPO,
959 fork_name=fork_name,
959 fork_name=fork_name,
960 owner=TEST_USER_ADMIN_LOGIN,
960 owner=TEST_USER_ADMIN_LOGIN,
961 )
961 )
962 response = api_call(self, params)
962 response = api_call(self, params)
963
963
964 expected = "repo `%s` already exist" % fork_name
964 expected = "repo `%s` already exist" % fork_name
965 self._compare_error(id_, expected, given=response.body)
965 self._compare_error(id_, expected, given=response.body)
966
966
967 @mock.patch.object(RepoModel, 'create_fork', crash)
967 @mock.patch.object(RepoModel, 'create_fork', crash)
968 def test_api_fork_repo_exception_occurred(self):
968 def test_api_fork_repo_exception_occurred(self):
969 fork_name = 'api-repo-fork'
969 fork_name = 'api-repo-fork'
970 id_, params = _build_data(self.apikey, 'fork_repo',
970 id_, params = _build_data(self.apikey, 'fork_repo',
971 repoid=self.REPO,
971 repoid=self.REPO,
972 fork_name=fork_name,
972 fork_name=fork_name,
973 owner=TEST_USER_ADMIN_LOGIN,
973 owner=TEST_USER_ADMIN_LOGIN,
974 )
974 )
975 response = api_call(self, params)
975 response = api_call(self, params)
976
976
977 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
977 expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
978 fork_name)
978 fork_name)
979 self._compare_error(id_, expected, given=response.body)
979 self._compare_error(id_, expected, given=response.body)
980
980
981 def test_api_get_users_group(self):
981 def test_api_get_users_group(self):
982 id_, params = _build_data(self.apikey, 'get_users_group',
982 id_, params = _build_data(self.apikey, 'get_users_group',
983 usersgroupid=TEST_USERS_GROUP)
983 usersgroupid=TEST_USERS_GROUP)
984 response = api_call(self, params)
984 response = api_call(self, params)
985
985
986 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
986 users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
987 members = []
987 members = []
988 for user in users_group.members:
988 for user in users_group.members:
989 user = user.user
989 user = user.user
990 members.append(user.get_api_data())
990 members.append(user.get_api_data())
991
991
992 ret = users_group.get_api_data()
992 ret = users_group.get_api_data()
993 ret['members'] = members
993 ret['members'] = members
994 expected = ret
994 expected = ret
995 self._compare_ok(id_, expected, given=response.body)
995 self._compare_ok(id_, expected, given=response.body)
996
996
997 def test_api_get_users_groups(self):
997 def test_api_get_users_groups(self):
998
998
999 make_users_group('test_users_group2')
999 make_users_group('test_users_group2')
1000
1000
1001 id_, params = _build_data(self.apikey, 'get_users_groups',)
1001 id_, params = _build_data(self.apikey, 'get_users_groups',)
1002 response = api_call(self, params)
1002 response = api_call(self, params)
1003
1003
1004 expected = []
1004 expected = []
1005 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
1005 for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
1006 users_group = UsersGroupModel().get_group(gr_name)
1006 users_group = UsersGroupModel().get_group(gr_name)
1007 ret = users_group.get_api_data()
1007 ret = users_group.get_api_data()
1008 expected.append(ret)
1008 expected.append(ret)
1009 self._compare_ok(id_, expected, given=response.body)
1009 self._compare_ok(id_, expected, given=response.body)
1010
1010
1011 UsersGroupModel().delete(users_group='test_users_group2')
1011 UsersGroupModel().delete(users_group='test_users_group2')
1012 Session().commit()
1012 Session().commit()
1013
1013
1014 def test_api_create_users_group(self):
1014 def test_api_create_users_group(self):
1015 group_name = 'some_new_group'
1015 group_name = 'some_new_group'
1016 id_, params = _build_data(self.apikey, 'create_users_group',
1016 id_, params = _build_data(self.apikey, 'create_users_group',
1017 group_name=group_name)
1017 group_name=group_name)
1018 response = api_call(self, params)
1018 response = api_call(self, params)
1019
1019
1020 ret = {
1020 ret = {
1021 'msg': 'created new users group `%s`' % group_name,
1021 'msg': 'created new users group `%s`' % group_name,
1022 'users_group': jsonify(UsersGroupModel()\
1022 'users_group': jsonify(UsersGroupModel()\
1023 .get_by_name(group_name)\
1023 .get_by_name(group_name)\
1024 .get_api_data())
1024 .get_api_data())
1025 }
1025 }
1026 expected = ret
1026 expected = ret
1027 self._compare_ok(id_, expected, given=response.body)
1027 self._compare_ok(id_, expected, given=response.body)
1028
1028
1029 destroy_users_group(group_name)
1029 destroy_users_group(group_name)
1030
1030
1031 def test_api_get_users_group_that_exist(self):
1031 def test_api_get_users_group_that_exist(self):
1032 id_, params = _build_data(self.apikey, 'create_users_group',
1032 id_, params = _build_data(self.apikey, 'create_users_group',
1033 group_name=TEST_USERS_GROUP)
1033 group_name=TEST_USERS_GROUP)
1034 response = api_call(self, params)
1034 response = api_call(self, params)
1035
1035
1036 expected = "users group `%s` already exist" % TEST_USERS_GROUP
1036 expected = "users group `%s` already exist" % TEST_USERS_GROUP
1037 self._compare_error(id_, expected, given=response.body)
1037 self._compare_error(id_, expected, given=response.body)
1038
1038
1039 @mock.patch.object(UsersGroupModel, 'create', crash)
1039 @mock.patch.object(UsersGroupModel, 'create', crash)
1040 def test_api_get_users_group_exception_occurred(self):
1040 def test_api_get_users_group_exception_occurred(self):
1041 group_name = 'exception_happens'
1041 group_name = 'exception_happens'
1042 id_, params = _build_data(self.apikey, 'create_users_group',
1042 id_, params = _build_data(self.apikey, 'create_users_group',
1043 group_name=group_name)
1043 group_name=group_name)
1044 response = api_call(self, params)
1044 response = api_call(self, params)
1045
1045
1046 expected = 'failed to create group `%s`' % group_name
1046 expected = 'failed to create group `%s`' % group_name
1047 self._compare_error(id_, expected, given=response.body)
1047 self._compare_error(id_, expected, given=response.body)
1048
1048
1049 def test_api_add_user_to_users_group(self):
1049 def test_api_add_user_to_users_group(self):
1050 gr_name = 'test_group'
1050 gr_name = 'test_group'
1051 UsersGroupModel().create(gr_name)
1051 UsersGroupModel().create(gr_name)
1052 Session().commit()
1052 Session().commit()
1053 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1053 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1054 usersgroupid=gr_name,
1054 usersgroupid=gr_name,
1055 userid=TEST_USER_ADMIN_LOGIN)
1055 userid=TEST_USER_ADMIN_LOGIN)
1056 response = api_call(self, params)
1056 response = api_call(self, params)
1057
1057
1058 expected = {
1058 expected = {
1059 'msg': 'added member `%s` to users group `%s`' % (
1059 'msg': 'added member `%s` to users group `%s`' % (
1060 TEST_USER_ADMIN_LOGIN, gr_name
1060 TEST_USER_ADMIN_LOGIN, gr_name
1061 ),
1061 ),
1062 'success': True}
1062 'success': True}
1063 self._compare_ok(id_, expected, given=response.body)
1063 self._compare_ok(id_, expected, given=response.body)
1064
1064
1065 UsersGroupModel().delete(users_group=gr_name)
1065 UsersGroupModel().delete(users_group=gr_name)
1066 Session().commit()
1066 Session().commit()
1067
1067
1068 def test_api_add_user_to_users_group_that_doesnt_exist(self):
1068 def test_api_add_user_to_users_group_that_doesnt_exist(self):
1069 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1069 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1070 usersgroupid='false-group',
1070 usersgroupid='false-group',
1071 userid=TEST_USER_ADMIN_LOGIN)
1071 userid=TEST_USER_ADMIN_LOGIN)
1072 response = api_call(self, params)
1072 response = api_call(self, params)
1073
1073
1074 expected = 'users group `%s` does not exist' % 'false-group'
1074 expected = 'users group `%s` does not exist' % 'false-group'
1075 self._compare_error(id_, expected, given=response.body)
1075 self._compare_error(id_, expected, given=response.body)
1076
1076
1077 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
1077 @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
1078 def test_api_add_user_to_users_group_exception_occurred(self):
1078 def test_api_add_user_to_users_group_exception_occurred(self):
1079 gr_name = 'test_group'
1079 gr_name = 'test_group'
1080 UsersGroupModel().create(gr_name)
1080 UsersGroupModel().create(gr_name)
1081 Session().commit()
1081 Session().commit()
1082 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1082 id_, params = _build_data(self.apikey, 'add_user_to_users_group',
1083 usersgroupid=gr_name,
1083 usersgroupid=gr_name,
1084 userid=TEST_USER_ADMIN_LOGIN)
1084 userid=TEST_USER_ADMIN_LOGIN)
1085 response = api_call(self, params)
1085 response = api_call(self, params)
1086
1086
1087 expected = 'failed to add member to users group `%s`' % gr_name
1087 expected = 'failed to add member to users group `%s`' % gr_name
1088 self._compare_error(id_, expected, given=response.body)
1088 self._compare_error(id_, expected, given=response.body)
1089
1089
1090 UsersGroupModel().delete(users_group=gr_name)
1090 UsersGroupModel().delete(users_group=gr_name)
1091 Session().commit()
1091 Session().commit()
1092
1092
1093 def test_api_remove_user_from_users_group(self):
1093 def test_api_remove_user_from_users_group(self):
1094 gr_name = 'test_group_3'
1094 gr_name = 'test_group_3'
1095 gr = UsersGroupModel().create(gr_name)
1095 gr = UsersGroupModel().create(gr_name)
1096 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1096 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1097 Session().commit()
1097 Session().commit()
1098 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1098 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1099 usersgroupid=gr_name,
1099 usersgroupid=gr_name,
1100 userid=TEST_USER_ADMIN_LOGIN)
1100 userid=TEST_USER_ADMIN_LOGIN)
1101 response = api_call(self, params)
1101 response = api_call(self, params)
1102
1102
1103 expected = {
1103 expected = {
1104 'msg': 'removed member `%s` from users group `%s`' % (
1104 'msg': 'removed member `%s` from users group `%s`' % (
1105 TEST_USER_ADMIN_LOGIN, gr_name
1105 TEST_USER_ADMIN_LOGIN, gr_name
1106 ),
1106 ),
1107 'success': True}
1107 'success': True}
1108 self._compare_ok(id_, expected, given=response.body)
1108 self._compare_ok(id_, expected, given=response.body)
1109
1109
1110 UsersGroupModel().delete(users_group=gr_name)
1110 UsersGroupModel().delete(users_group=gr_name)
1111 Session().commit()
1111 Session().commit()
1112
1112
1113 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
1113 @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
1114 def test_api_remove_user_from_users_group_exception_occurred(self):
1114 def test_api_remove_user_from_users_group_exception_occurred(self):
1115 gr_name = 'test_group_3'
1115 gr_name = 'test_group_3'
1116 gr = UsersGroupModel().create(gr_name)
1116 gr = UsersGroupModel().create(gr_name)
1117 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1117 UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
1118 Session().commit()
1118 Session().commit()
1119 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1119 id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
1120 usersgroupid=gr_name,
1120 usersgroupid=gr_name,
1121 userid=TEST_USER_ADMIN_LOGIN)
1121 userid=TEST_USER_ADMIN_LOGIN)
1122 response = api_call(self, params)
1122 response = api_call(self, params)
1123
1123
1124 expected = 'failed to remove member from users group `%s`' % gr_name
1124 expected = 'failed to remove member from users group `%s`' % gr_name
1125 self._compare_error(id_, expected, given=response.body)
1125 self._compare_error(id_, expected, given=response.body)
1126
1126
1127 UsersGroupModel().delete(users_group=gr_name)
1127 UsersGroupModel().delete(users_group=gr_name)
1128 Session().commit()
1128 Session().commit()
1129
1129
1130 @parameterized.expand([('none', 'repository.none'),
1130 @parameterized.expand([('none', 'repository.none'),
1131 ('read', 'repository.read'),
1131 ('read', 'repository.read'),
1132 ('write', 'repository.write'),
1132 ('write', 'repository.write'),
1133 ('admin', 'repository.admin')])
1133 ('admin', 'repository.admin')])
1134 def test_api_grant_user_permission(self, name, perm):
1134 def test_api_grant_user_permission(self, name, perm):
1135 id_, params = _build_data(self.apikey, 'grant_user_permission',
1135 id_, params = _build_data(self.apikey, 'grant_user_permission',
1136 repoid=self.REPO,
1136 repoid=self.REPO,
1137 userid=TEST_USER_ADMIN_LOGIN,
1137 userid=TEST_USER_ADMIN_LOGIN,
1138 perm=perm)
1138 perm=perm)
1139 response = api_call(self, params)
1139 response = api_call(self, params)
1140
1140
1141 ret = {
1141 ret = {
1142 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1142 'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
1143 perm, TEST_USER_ADMIN_LOGIN, self.REPO
1143 perm, TEST_USER_ADMIN_LOGIN, self.REPO
1144 ),
1144 ),
1145 'success': True
1145 'success': True
1146 }
1146 }
1147 expected = ret
1147 expected = ret
1148 self._compare_ok(id_, expected, given=response.body)
1148 self._compare_ok(id_, expected, given=response.body)
1149
1149
1150 def test_api_grant_user_permission_wrong_permission(self):
1150 def test_api_grant_user_permission_wrong_permission(self):
1151 perm = 'haha.no.permission'
1151 perm = 'haha.no.permission'
1152 id_, params = _build_data(self.apikey, 'grant_user_permission',
1152 id_, params = _build_data(self.apikey, 'grant_user_permission',
1153 repoid=self.REPO,
1153 repoid=self.REPO,
1154 userid=TEST_USER_ADMIN_LOGIN,
1154 userid=TEST_USER_ADMIN_LOGIN,
1155 perm=perm)
1155 perm=perm)
1156 response = api_call(self, params)
1156 response = api_call(self, params)
1157
1157
1158 expected = 'permission `%s` does not exist' % perm
1158 expected = 'permission `%s` does not exist' % perm
1159 self._compare_error(id_, expected, given=response.body)
1159 self._compare_error(id_, expected, given=response.body)
1160
1160
1161 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
1161 @mock.patch.object(RepoModel, 'grant_user_permission', crash)
1162 def test_api_grant_user_permission_exception_when_adding(self):
1162 def test_api_grant_user_permission_exception_when_adding(self):
1163 perm = 'repository.read'
1163 perm = 'repository.read'
1164 id_, params = _build_data(self.apikey, 'grant_user_permission',
1164 id_, params = _build_data(self.apikey, 'grant_user_permission',
1165 repoid=self.REPO,
1165 repoid=self.REPO,
1166 userid=TEST_USER_ADMIN_LOGIN,
1166 userid=TEST_USER_ADMIN_LOGIN,
1167 perm=perm)
1167 perm=perm)
1168 response = api_call(self, params)
1168 response = api_call(self, params)
1169
1169
1170 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1170 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1171 TEST_USER_ADMIN_LOGIN, self.REPO
1171 TEST_USER_ADMIN_LOGIN, self.REPO
1172 )
1172 )
1173 self._compare_error(id_, expected, given=response.body)
1173 self._compare_error(id_, expected, given=response.body)
1174
1174
1175 def test_api_revoke_user_permission(self):
1175 def test_api_revoke_user_permission(self):
1176 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1176 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1177 repoid=self.REPO,
1177 repoid=self.REPO,
1178 userid=TEST_USER_ADMIN_LOGIN,)
1178 userid=TEST_USER_ADMIN_LOGIN,)
1179 response = api_call(self, params)
1179 response = api_call(self, params)
1180
1180
1181 expected = {
1181 expected = {
1182 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1182 'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
1183 TEST_USER_ADMIN_LOGIN, self.REPO
1183 TEST_USER_ADMIN_LOGIN, self.REPO
1184 ),
1184 ),
1185 'success': True
1185 'success': True
1186 }
1186 }
1187 self._compare_ok(id_, expected, given=response.body)
1187 self._compare_ok(id_, expected, given=response.body)
1188
1188
1189 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
1189 @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
1190 def test_api_revoke_user_permission_exception_when_adding(self):
1190 def test_api_revoke_user_permission_exception_when_adding(self):
1191 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1191 id_, params = _build_data(self.apikey, 'revoke_user_permission',
1192 repoid=self.REPO,
1192 repoid=self.REPO,
1193 userid=TEST_USER_ADMIN_LOGIN,)
1193 userid=TEST_USER_ADMIN_LOGIN,)
1194 response = api_call(self, params)
1194 response = api_call(self, params)
1195
1195
1196 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1196 expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
1197 TEST_USER_ADMIN_LOGIN, self.REPO
1197 TEST_USER_ADMIN_LOGIN, self.REPO
1198 )
1198 )
1199 self._compare_error(id_, expected, given=response.body)
1199 self._compare_error(id_, expected, given=response.body)
1200
1200
1201 @parameterized.expand([('none', 'repository.none'),
1201 @parameterized.expand([('none', 'repository.none'),
1202 ('read', 'repository.read'),
1202 ('read', 'repository.read'),
1203 ('write', 'repository.write'),
1203 ('write', 'repository.write'),
1204 ('admin', 'repository.admin')])
1204 ('admin', 'repository.admin')])
1205 def test_api_grant_users_group_permission(self, name, perm):
1205 def test_api_grant_users_group_permission(self, name, perm):
1206 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1206 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1207 repoid=self.REPO,
1207 repoid=self.REPO,
1208 usersgroupid=TEST_USERS_GROUP,
1208 usersgroupid=TEST_USERS_GROUP,
1209 perm=perm)
1209 perm=perm)
1210 response = api_call(self, params)
1210 response = api_call(self, params)
1211
1211
1212 ret = {
1212 ret = {
1213 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
1213 'msg': 'Granted perm: `%s` for users group: `%s` in repo: `%s`' % (
1214 perm, TEST_USERS_GROUP, self.REPO
1214 perm, TEST_USERS_GROUP, self.REPO
1215 ),
1215 ),
1216 'success': True
1216 'success': True
1217 }
1217 }
1218 expected = ret
1218 expected = ret
1219 self._compare_ok(id_, expected, given=response.body)
1219 self._compare_ok(id_, expected, given=response.body)
1220
1220
1221 def test_api_grant_users_group_permission_wrong_permission(self):
1221 def test_api_grant_users_group_permission_wrong_permission(self):
1222 perm = 'haha.no.permission'
1222 perm = 'haha.no.permission'
1223 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1223 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1224 repoid=self.REPO,
1224 repoid=self.REPO,
1225 usersgroupid=TEST_USERS_GROUP,
1225 usersgroupid=TEST_USERS_GROUP,
1226 perm=perm)
1226 perm=perm)
1227 response = api_call(self, params)
1227 response = api_call(self, params)
1228
1228
1229 expected = 'permission `%s` does not exist' % perm
1229 expected = 'permission `%s` does not exist' % perm
1230 self._compare_error(id_, expected, given=response.body)
1230 self._compare_error(id_, expected, given=response.body)
1231
1231
1232 @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
1232 @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
1233 def test_api_grant_users_group_permission_exception_when_adding(self):
1233 def test_api_grant_users_group_permission_exception_when_adding(self):
1234 perm = 'repository.read'
1234 perm = 'repository.read'
1235 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1235 id_, params = _build_data(self.apikey, 'grant_users_group_permission',
1236 repoid=self.REPO,
1236 repoid=self.REPO,
1237 usersgroupid=TEST_USERS_GROUP,
1237 usersgroupid=TEST_USERS_GROUP,
1238 perm=perm)
1238 perm=perm)
1239 response = api_call(self, params)
1239 response = api_call(self, params)
1240
1240
1241 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1241 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1242 TEST_USERS_GROUP, self.REPO
1242 TEST_USERS_GROUP, self.REPO
1243 )
1243 )
1244 self._compare_error(id_, expected, given=response.body)
1244 self._compare_error(id_, expected, given=response.body)
1245
1245
1246 def test_api_revoke_users_group_permission(self):
1246 def test_api_revoke_users_group_permission(self):
1247 RepoModel().grant_users_group_permission(repo=self.REPO,
1247 RepoModel().grant_users_group_permission(repo=self.REPO,
1248 group_name=TEST_USERS_GROUP,
1248 group_name=TEST_USERS_GROUP,
1249 perm='repository.read')
1249 perm='repository.read')
1250 Session().commit()
1250 Session().commit()
1251 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1251 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1252 repoid=self.REPO,
1252 repoid=self.REPO,
1253 usersgroupid=TEST_USERS_GROUP,)
1253 usersgroupid=TEST_USERS_GROUP,)
1254 response = api_call(self, params)
1254 response = api_call(self, params)
1255
1255
1256 expected = {
1256 expected = {
1257 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
1257 'msg': 'Revoked perm for users group: `%s` in repo: `%s`' % (
1258 TEST_USERS_GROUP, self.REPO
1258 TEST_USERS_GROUP, self.REPO
1259 ),
1259 ),
1260 'success': True
1260 'success': True
1261 }
1261 }
1262 self._compare_ok(id_, expected, given=response.body)
1262 self._compare_ok(id_, expected, given=response.body)
1263
1263
1264 @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
1264 @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
1265 def test_api_revoke_users_group_permission_exception_when_adding(self):
1265 def test_api_revoke_users_group_permission_exception_when_adding(self):
1266
1266
1267 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1267 id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
1268 repoid=self.REPO,
1268 repoid=self.REPO,
1269 usersgroupid=TEST_USERS_GROUP,)
1269 usersgroupid=TEST_USERS_GROUP,)
1270 response = api_call(self, params)
1270 response = api_call(self, params)
1271
1271
1272 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1272 expected = 'failed to edit permission for users group: `%s` in repo: `%s`' % (
1273 TEST_USERS_GROUP, self.REPO
1273 TEST_USERS_GROUP, self.REPO
1274 )
1274 )
1275 self._compare_error(id_, expected, given=response.body)
1275 self._compare_error(id_, expected, given=response.body)
General Comments 0
You need to be logged in to leave comments. Login now