1 import flask
2 from . import query_params, get_copr, pagination, Paginator, GET, POST, PUT, DELETE
3 from .json2form import get_form_compatible_data, get_input_dict
4 from coprs import db, models, forms
5 from coprs.views.misc import api_login_required
6 from coprs.views.apiv3_ns import apiv3_ns
7 from coprs.logic.coprs_logic import CoprsLogic, CoprChrootsLogic, MockChrootsLogic
8 from coprs.logic.complex_logic import ComplexLogic
9 from coprs.logic.users_logic import UsersLogic
10 from coprs.exceptions import (DuplicateException, NonAdminCannotCreatePersistentProject,
11 NonAdminCannotDisableAutoPrunning, ActionInProgressException,
12 InsufficientRightsException, BadRequest, ObjectNotFound)
16 return {
17 "id": copr.id,
18 "name": copr.name,
19 "ownername": copr.owner_name,
20 "full_name": copr.full_name,
21 "homepage": copr.homepage,
22 "contact": copr.contact,
23 "description": copr.description,
24 "instructions": copr.instructions,
25 "devel_mode": copr.devel_mode,
26 "persistent": copr.persistent,
27 "unlisted_on_hp": copr.unlisted_on_hp,
28 "auto_prune": copr.auto_prune,
29 "chroot_repos": CoprsLogic.get_yum_repos(copr, empty=True),
30 "additional_repos": copr.repos_list,
31 "enable_net": copr.build_enable_net,
32 "bootstrap": copr.bootstrap,
33 "module_hotfixes": copr.module_hotfixes,
34 }
35
38 replace = {
39 "devel_mode": "disable_createrepo",
40 "additional_repos": "repos",
41 }
42 output = input.copy()
43 for from_name, to_name in replace.items():
44 if from_name not in output:
45 continue
46 output[to_name] = output.pop(from_name)
47 return output
48
51 inserted = set(input.get("chroots") or [])
52 allowed = {x.name for x in allowed_chroots}
53 unexpected = inserted - allowed
54 if unexpected:
55 raise BadRequest("Unexpected chroot: {}".format(", ".join(unexpected)))
56
76
77
78 @apiv3_ns.route("/project", methods=GET)
79 @query_params()
80 -def get_project(ownername, projectname):
83
84
85 @apiv3_ns.route("/project/list", methods=GET)
86 @pagination()
87 @query_params()
88 -def get_project_list(ownername=None, **kwargs):
102
103
104 @apiv3_ns.route("/project/search", methods=GET)
105 @pagination()
106 @query_params()
107
108 -def search_projects(query, **kwargs):
116
117
118 @apiv3_ns.route("/project/add/<ownername>", methods=POST)
119 @api_login_required
120 -def add_project(ownername):
121 user, group = owner2tuple(ownername)
122 data = rename_fields(get_form_compatible_data())
123 form = forms.CoprFormFactory.create_form_cls(user=user, group=group)(data, meta={'csrf': False})
124
125 if not form.validate_on_submit():
126 raise BadRequest(form.errors)
127 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple())
128
129 bootstrap = None
130
131 use_bootstrap_container = form.use_bootstrap_container.data
132 if use_bootstrap_container is not None:
133 bootstrap = "on" if use_bootstrap_container else "off"
134 if form.bootstrap.data is not None:
135 bootstrap = form.bootstrap.data
136
137 try:
138 copr = CoprsLogic.add(
139 name=form.name.data.strip(),
140 repos=" ".join(form.repos.data.split()),
141 user=user,
142 selected_chroots=form.selected_chroots,
143 description=form.description.data,
144 instructions=form.instructions.data,
145 check_for_duplicates=True,
146 unlisted_on_hp=form.unlisted_on_hp.data,
147 build_enable_net=form.enable_net.data,
148 group=group,
149 persistent=form.persistent.data,
150 auto_prune=form.auto_prune.data,
151 bootstrap=bootstrap,
152 homepage=form.homepage.data,
153 contact=form.contact.data,
154 disable_createrepo=form.disable_createrepo.data,
155 delete_after_days=form.delete_after_days.data,
156 multilib=form.multilib.data,
157 module_hotfixes=form.module_hotfixes.data,
158 )
159 db.session.commit()
160 except (DuplicateException,
161 NonAdminCannotCreatePersistentProject,
162 NonAdminCannotDisableAutoPrunning) as err:
163 db.session.rollback()
164 raise err
165 return flask.jsonify(to_dict(copr))
166
167
168 @apiv3_ns.route("/project/edit/<ownername>/<projectname>", methods=PUT)
169 @api_login_required
170 -def edit_project(ownername, projectname):
171 copr = get_copr(ownername, projectname)
172 data = rename_fields(get_form_compatible_data())
173 form = forms.CoprModifyForm(data, meta={'csrf': False})
174
175 if not form.validate_on_submit():
176 raise BadRequest(form.errors)
177 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple())
178
179 for field in form:
180 if field.data is None or field.name in ["csrf_token", "chroots"]:
181 continue
182 if field.name not in data.keys():
183 continue
184 setattr(copr, field.name, field.data)
185
186 if form.chroots.data:
187 CoprChrootsLogic.update_from_names(
188 flask.g.user, copr, form.chroots.data)
189
190 try:
191 CoprsLogic.update(flask.g.user, copr)
192 if copr.group:
193 _ = copr.group.id
194 db.session.commit()
195 except (ActionInProgressException,
196 InsufficientRightsException,
197 NonAdminCannotDisableAutoPrunning) as ex:
198 db.session.rollback()
199 raise ex
200
201 return flask.jsonify(to_dict(copr))
202
203
204 @apiv3_ns.route("/project/fork/<ownername>/<projectname>", methods=PUT)
205 @api_login_required
206 -def fork_project(ownername, projectname):
207 copr = get_copr(ownername, projectname)
208
209
210 data = get_form_compatible_data()
211 data["owner"] = data.get("ownername")
212
213 form = forms.CoprForkFormFactory \
214 .create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)(data, meta={'csrf': False})
215
216 if form.validate_on_submit() and copr:
217 try:
218 dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0]
219 if flask.g.user.name != form.owner.data and not dstgroup:
220 return ObjectNotFound("There is no such group: {}".format(form.owner.data))
221
222 dst_copr = CoprsLogic.get(flask.g.user.name, form.name.data).all()
223 if dst_copr and form.confirm.data != True:
224 raise BadRequest("You are about to fork into existing project: {}\n"
225 "Please use --confirm if you really want to do this".format(form.name.data))
226 fcopr, _ = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data,
227 dstgroup=dstgroup)
228 db.session.commit()
229
230 except (ActionInProgressException, InsufficientRightsException) as err:
231 db.session.rollback()
232 raise err
233 else:
234 raise BadRequest(form.errors)
235
236 return flask.jsonify(to_dict(fcopr))
237
238
239 @apiv3_ns.route("/project/delete/<ownername>/<projectname>", methods=DELETE)
240 @api_login_required
241 -def delete_project(ownername, projectname):
258