Package coprs :: Package views :: Package apiv3_ns :: Module apiv3_projects
[hide private]
[frames] | no frames]

Source Code for Module coprs.views.apiv3_ns.apiv3_projects

  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.exceptions import (DuplicateException, NonAdminCannotCreatePersistentProject, 
 10                                NonAdminCannotDisableAutoPrunning, ActionInProgressException, 
 11                                InsufficientRightsException, BadRequest, ObjectNotFound) 
12 13 14 -def to_dict(copr):
15 return { 16 "id": copr.id, 17 "name": copr.name, 18 "ownername": copr.owner_name, 19 "full_name": copr.full_name, 20 "homepage": copr.homepage, 21 "contact": copr.contact, 22 "description": copr.description, 23 "instructions": copr.instructions, 24 "devel_mode": copr.devel_mode, 25 "persistent": copr.persistent, 26 "unlisted_on_hp": copr.unlisted_on_hp, 27 "auto_prune": copr.auto_prune, 28 "chroot_repos": CoprsLogic.get_yum_repos(copr, empty=True), 29 "additional_repos": copr.repos_list, 30 "enable_net": copr.build_enable_net, 31 "use_bootstrap_container": copr.use_bootstrap_container, 32 }
33
34 35 -def rename_fields(input):
36 replace = { 37 "devel_mode": "disable_createrepo", 38 "additional_repos": "repos", 39 } 40 output = input.copy() 41 for from_name, to_name in replace.items(): 42 if from_name not in output: 43 continue 44 output[to_name] = output.pop(from_name) 45 return output
46
47 48 -def validate_chroots(input, allowed_chroots):
49 inserted = set(input["chroots"] or []) 50 allowed = {x.name for x in allowed_chroots} 51 unexpected = inserted - allowed 52 if unexpected: 53 raise BadRequest("Unexpected chroot: {}".format(", ".join(unexpected)))
54
55 56 @apiv3_ns.route("/project", methods=GET) 57 @query_params() 58 -def get_project(ownername, projectname):
59 copr = get_copr(ownername, projectname) 60 return flask.jsonify(to_dict(copr))
61
62 63 @apiv3_ns.route("/project/list", methods=GET) 64 @pagination() 65 @query_params() 66 -def get_project_list(ownername=None, **kwargs):
67 if not ownername: 68 query = CoprsLogic.get_multiple() 69 elif ownername.startswith("@"): 70 group_name = ownername[1:] 71 query = CoprsLogic.get_multiple() 72 query = CoprsLogic.filter_by_group_name(query, group_name) 73 else: 74 query = CoprsLogic.get_multiple_owned_by_username(ownername) 75 76 # @TODO ordering doesn't work correctly - try order by models.Copr.name DESC 77 paginator = Paginator(query, models.Copr, **kwargs) 78 projects = paginator.map(to_dict) 79 return flask.jsonify(items=projects, meta=paginator.meta)
80
81 82 @apiv3_ns.route("/project/search", methods=GET) 83 @pagination() 84 @query_params() 85 # @TODO should the param be query or projectname? 86 -def search_projects(query, **kwargs):
87 try: 88 search_query = CoprsLogic.get_multiple_fulltext(query) 89 paginator = Paginator(search_query, models.Copr, **kwargs) 90 projects = paginator.map(to_dict) 91 except ValueError as ex: 92 raise BadRequest(str(ex)) 93 return flask.jsonify(items=projects, meta=paginator.meta)
94
95 96 @apiv3_ns.route("/project/add/<ownername>", methods=POST) 97 @api_login_required 98 -def add_project(ownername):
99 data = rename_fields(get_form_compatible_data()) 100 form = forms.CoprFormFactory.create_form_cls()(data, meta={'csrf': False}) 101 102 if not form.validate_on_submit(): 103 raise BadRequest(form.errors) 104 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple()) 105 106 group = None 107 if ownername[0] == "@": 108 group = ComplexLogic.get_group_by_name_safe(ownername[1:]) 109 110 try: 111 copr = CoprsLogic.add( 112 name=form.name.data.strip(), 113 repos=" ".join(form.repos.data.split()), 114 user=flask.g.user, 115 selected_chroots=form.selected_chroots, 116 description=form.description.data, 117 instructions=form.instructions.data, 118 check_for_duplicates=True, 119 unlisted_on_hp=form.unlisted_on_hp.data, 120 build_enable_net=form.enable_net.data, 121 group=group, 122 persistent=form.persistent.data, 123 auto_prune=form.auto_prune.data, 124 use_bootstrap_container=form.use_bootstrap_container.data, 125 homepage=form.homepage.data, 126 contact=form.contact.data, 127 disable_createrepo=form.disable_createrepo.data, 128 delete_after_days=form.delete_after_days.data, 129 ) 130 db.session.commit() 131 except (DuplicateException, 132 NonAdminCannotCreatePersistentProject, 133 NonAdminCannotDisableAutoPrunning) as err: 134 db.session.rollback() 135 raise err 136 return flask.jsonify(to_dict(copr))
137
138 139 @apiv3_ns.route("/project/edit/<ownername>/<projectname>", methods=PUT) 140 @api_login_required 141 -def edit_project(ownername, projectname):
142 copr = get_copr(ownername, projectname) 143 data = rename_fields(get_form_compatible_data()) 144 form = forms.CoprModifyForm(data, meta={'csrf': False}) 145 146 if not form.validate_on_submit(): 147 raise BadRequest(form.errors) 148 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple()) 149 150 for field in form: 151 if field.data is None or field.name in ["csrf_token", "chroots"]: 152 continue 153 if field.name not in data.keys(): 154 continue 155 setattr(copr, field.name, field.data) 156 157 if form.chroots.data: 158 CoprChrootsLogic.update_from_names( 159 flask.g.user, copr, form.chroots.data) 160 161 try: 162 CoprsLogic.update(flask.g.user, copr) 163 if copr.group: # load group.id 164 _ = copr.group.id 165 db.session.commit() 166 except (ActionInProgressException, 167 InsufficientRightsException, 168 NonAdminCannotDisableAutoPrunning) as ex: 169 db.session.rollback() 170 raise ex 171 172 return flask.jsonify(to_dict(copr))
173
174 175 @apiv3_ns.route("/project/fork/<ownername>/<projectname>", methods=PUT) 176 @api_login_required 177 -def fork_project(ownername, projectname):
178 copr = get_copr(ownername, projectname) 179 180 # @FIXME we want "ownername" from the outside, but our internal Form expects "owner" instead 181 data = get_form_compatible_data() 182 data["owner"] = data.get("ownername") 183 184 form = forms.CoprForkFormFactory \ 185 .create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)(data, meta={'csrf': False}) 186 187 if form.validate_on_submit() and copr: 188 try: 189 dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0] 190 if flask.g.user.name != form.owner.data and not dstgroup: 191 return ObjectNotFound("There is no such group: {}".format(form.owner.data)) 192 193 fcopr, created = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup) 194 if not created and form.confirm.data != True: 195 raise BadRequest("You are about to fork into existing project: {}\n" 196 "Please use --confirm if you really want to do this".format(fcopr.full_name)) 197 db.session.commit() 198 199 except (ActionInProgressException, InsufficientRightsException) as err: 200 db.session.rollback() 201 raise err 202 else: 203 raise BadRequest(form.errors) 204 205 return flask.jsonify(to_dict(fcopr))
206
207 208 @apiv3_ns.route("/project/delete/<ownername>/<projectname>", methods=DELETE) 209 @api_login_required 210 -def delete_project(ownername, projectname):
211 copr = get_copr(ownername, projectname) 212 copr_dict = to_dict(copr) 213 form = forms.APICoprDeleteForm(meta={'csrf': False}) 214 215 if form.validate_on_submit() and copr: 216 try: 217 ComplexLogic.delete_copr(copr) 218 except (ActionInProgressException, 219 InsufficientRightsException) as err: 220 db.session.rollback() 221 raise err 222 else: 223 db.session.commit() 224 else: 225 raise BadRequest(form.errors) 226 return flask.jsonify(copr_dict)
227