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 query = CoprsLogic.filter_without_group_projects(query) 76 77 # @TODO ordering doesn't work correctly - try order by models.Copr.name DESC 78 paginator = Paginator(query, models.Copr, **kwargs) 79 projects = paginator.map(to_dict) 80 return flask.jsonify(items=projects, meta=paginator.meta)
81
82 83 @apiv3_ns.route("/project/search", methods=GET) 84 @pagination() 85 @query_params() 86 # @TODO should the param be query or projectname? 87 -def search_projects(query, **kwargs):
88 try: 89 search_query = CoprsLogic.get_multiple_fulltext(query) 90 paginator = Paginator(search_query, models.Copr, **kwargs) 91 projects = paginator.map(to_dict) 92 except ValueError as ex: 93 raise BadRequest(str(ex)) 94 return flask.jsonify(items=projects, meta=paginator.meta)
95
96 97 @apiv3_ns.route("/project/add/<ownername>", methods=POST) 98 @api_login_required 99 -def add_project(ownername):
100 data = rename_fields(get_form_compatible_data()) 101 form = forms.CoprFormFactory.create_form_cls()(data, meta={'csrf': False}) 102 103 if not form.validate_on_submit(): 104 raise BadRequest(form.errors) 105 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple()) 106 107 group = None 108 if ownername[0] == "@": 109 group = ComplexLogic.get_group_by_name_safe(ownername[1:]) 110 111 try: 112 copr = CoprsLogic.add( 113 name=form.name.data.strip(), 114 repos=" ".join(form.repos.data.split()), 115 user=flask.g.user, 116 selected_chroots=form.selected_chroots, 117 description=form.description.data, 118 instructions=form.instructions.data, 119 check_for_duplicates=True, 120 unlisted_on_hp=form.unlisted_on_hp.data, 121 build_enable_net=form.enable_net.data, 122 group=group, 123 persistent=form.persistent.data, 124 auto_prune=form.auto_prune.data, 125 use_bootstrap_container=form.use_bootstrap_container.data, 126 homepage=form.homepage.data, 127 contact=form.contact.data, 128 disable_createrepo=form.disable_createrepo.data, 129 delete_after_days=form.delete_after_days.data, 130 ) 131 db.session.commit() 132 except (DuplicateException, 133 NonAdminCannotCreatePersistentProject, 134 NonAdminCannotDisableAutoPrunning) as err: 135 db.session.rollback() 136 raise err 137 return flask.jsonify(to_dict(copr))
138
139 140 @apiv3_ns.route("/project/edit/<ownername>/<projectname>", methods=PUT) 141 @api_login_required 142 -def edit_project(ownername, projectname):
143 copr = get_copr(ownername, projectname) 144 data = rename_fields(get_form_compatible_data()) 145 form = forms.CoprModifyForm(data, meta={'csrf': False}) 146 147 if not form.validate_on_submit(): 148 raise BadRequest(form.errors) 149 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple()) 150 151 for field in form: 152 if field.data is None or field.name in ["csrf_token", "chroots"]: 153 continue 154 if field.name not in data.keys(): 155 continue 156 setattr(copr, field.name, field.data) 157 158 if form.chroots.data: 159 CoprChrootsLogic.update_from_names( 160 flask.g.user, copr, form.chroots.data) 161 162 try: 163 CoprsLogic.update(flask.g.user, copr) 164 if copr.group: # load group.id 165 _ = copr.group.id 166 db.session.commit() 167 except (ActionInProgressException, 168 InsufficientRightsException, 169 NonAdminCannotDisableAutoPrunning) as ex: 170 db.session.rollback() 171 raise ex 172 173 return flask.jsonify(to_dict(copr))
174
175 176 @apiv3_ns.route("/project/fork/<ownername>/<projectname>", methods=PUT) 177 @api_login_required 178 -def fork_project(ownername, projectname):
179 copr = get_copr(ownername, projectname) 180 181 # @FIXME we want "ownername" from the outside, but our internal Form expects "owner" instead 182 data = get_form_compatible_data() 183 data["owner"] = data.get("ownername") 184 185 form = forms.CoprForkFormFactory \ 186 .create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)(data, meta={'csrf': False}) 187 188 if form.validate_on_submit() and copr: 189 try: 190 dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0] 191 if flask.g.user.name != form.owner.data and not dstgroup: 192 return ObjectNotFound("There is no such group: {}".format(form.owner.data)) 193 194 fcopr, created = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup) 195 if not created and form.confirm.data != True: 196 raise BadRequest("You are about to fork into existing project: {}\n" 197 "Please use --confirm if you really want to do this".format(fcopr.full_name)) 198 db.session.commit() 199 200 except (ActionInProgressException, InsufficientRightsException) as err: 201 db.session.rollback() 202 raise err 203 else: 204 raise BadRequest(form.errors) 205 206 return flask.jsonify(to_dict(fcopr))
207
208 209 @apiv3_ns.route("/project/delete/<ownername>/<projectname>", methods=DELETE) 210 @api_login_required 211 -def delete_project(ownername, projectname):
212 copr = get_copr(ownername, projectname) 213 copr_dict = to_dict(copr) 214 form = forms.APICoprDeleteForm(meta={'csrf': False}) 215 216 if form.validate_on_submit() and copr: 217 try: 218 ComplexLogic.delete_copr(copr) 219 except (ActionInProgressException, 220 InsufficientRightsException) as err: 221 db.session.rollback() 222 raise err 223 else: 224 db.session.commit() 225 else: 226 raise BadRequest(form.errors) 227 return flask.jsonify(copr_dict)
228