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 os 
  2  import flask 
  3  from . import query_params, get_copr, pagination, Paginator, GET, POST, PUT, DELETE 
  4  from .json2form import get_form_compatible_data, get_input_dict 
  5  from coprs import db, models, forms 
  6  from coprs.views.misc import api_login_required 
  7  from coprs.views.apiv3_ns import apiv3_ns 
  8  from coprs.logic.coprs_logic import CoprsLogic, CoprChrootsLogic, MockChrootsLogic 
  9  from coprs.logic.builds_logic import BuildsLogic 
 10  from coprs.logic.complex_logic import ComplexLogic 
 11  from coprs.exceptions import (ApiError, DuplicateException, NonAdminCannotCreatePersistentProject, 
 12                                NonAdminCannotDisableAutoPrunning, ActionInProgressException, 
 13                                InsufficientRightsException, BadRequest, ObjectNotFound) 
14 15 16 -def to_dict(copr):
17 return { 18 "id": copr.id, 19 "name": copr.name, 20 "ownername": copr.owner_name, 21 "full_name": copr.full_name, 22 "homepage": copr.homepage, 23 "contact": copr.contact, 24 "description": copr.description, 25 "instructions": copr.instructions, 26 "devel_mode": copr.devel_mode, 27 "persistent": copr.persistent, 28 "unlisted_on_hp": copr.unlisted_on_hp, 29 "auto_prune": copr.auto_prune, 30 "chroot_repos": CoprsLogic.get_yum_repos(copr, empty=True), 31 "additional_repos": copr.repos_list, 32 "enable_net": copr.build_enable_net, 33 "use_bootstrap_container": copr.use_bootstrap_container, 34 }
35
36 37 -def rename_fields(input):
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
49 50 -def validate_chroots(input, allowed_chroots):
51 inserted = set(input["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
57 58 @apiv3_ns.route("/project", methods=GET) 59 @query_params() 60 -def get_project(ownername, projectname):
61 copr = get_copr(ownername, projectname) 62 return flask.jsonify(to_dict(copr))
63
64 65 @apiv3_ns.route("/project/list", methods=GET) 66 @pagination() 67 @query_params() 68 -def get_project_list(ownername, **kwargs):
69 if 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, csrf_enabled=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 ) 128 db.session.commit() 129 except (DuplicateException, 130 NonAdminCannotCreatePersistentProject, 131 NonAdminCannotDisableAutoPrunning) as err: 132 db.session.rollback() 133 raise err 134 return flask.jsonify(to_dict(copr))
135
136 137 @apiv3_ns.route("/project/edit/<ownername>/<projectname>", methods=PUT) 138 @api_login_required 139 -def edit_project(ownername, projectname):
140 copr = get_copr(ownername, projectname) 141 data = rename_fields(get_form_compatible_data()) 142 form = forms.CoprModifyForm(data, csrf_enabled=False) 143 144 if not form.validate_on_submit(): 145 raise BadRequest(form.errors) 146 validate_chroots(get_input_dict(), MockChrootsLogic.get_multiple()) 147 148 for field in form: 149 if field.data is None or field.name in ["csrf_token", "chroots"]: 150 continue 151 if field.name not in data.keys(): 152 continue 153 setattr(copr, field.name, field.data) 154 155 if form.chroots.data: 156 CoprChrootsLogic.update_from_names( 157 flask.g.user, copr, form.chroots.data) 158 159 try: 160 CoprsLogic.update(flask.g.user, copr) 161 if copr.group: # load group.id 162 _ = copr.group.id 163 db.session.commit() 164 except (ActionInProgressException, 165 InsufficientRightsException, 166 NonAdminCannotDisableAutoPrunning) as ex: 167 db.session.rollback() 168 raise ex 169 170 return flask.jsonify(to_dict(copr))
171
172 173 @apiv3_ns.route("/project/fork/<ownername>/<projectname>", methods=PUT) 174 @api_login_required 175 -def fork_project(ownername, projectname):
176 copr = get_copr(ownername, projectname) 177 178 # @FIXME we want "ownername" from the outside, but our internal Form expects "owner" instead 179 data = get_form_compatible_data() 180 data["owner"] = data.get("ownername") 181 182 form = forms.CoprForkFormFactory \ 183 .create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)(data, csrf_enabled=False) 184 185 if form.validate_on_submit() and copr: 186 try: 187 dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0] 188 if flask.g.user.name != form.owner.data and not dstgroup: 189 return ObjectNotFound("There is no such group: {}".format(form.owner.data)) 190 191 fcopr, created = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup) 192 if not created and form.confirm.data != True: 193 raise BadRequest("You are about to fork into existing project: {}\n" 194 "Please use --confirm if you really want to do this".format(fcopr.full_name)) 195 db.session.commit() 196 197 except (ActionInProgressException, InsufficientRightsException) as err: 198 db.session.rollback() 199 raise err 200 else: 201 raise BadRequest(form.errors) 202 203 return flask.jsonify(to_dict(fcopr))
204
205 206 @apiv3_ns.route("/project/delete/<ownername>/<projectname>", methods=DELETE) 207 @api_login_required 208 -def delete_project(ownername, projectname):
209 copr = get_copr(ownername, projectname) 210 copr_dict = to_dict(copr) 211 form = forms.APICoprDeleteForm(csrf_enabled=False) 212 213 if form.validate_on_submit() and copr: 214 try: 215 ComplexLogic.delete_copr(copr) 216 except (ActionInProgressException, 217 InsufficientRightsException) as err: 218 db.session.rollback() 219 raise err 220 else: 221 db.session.commit() 222 else: 223 raise BadRequest(form.errors) 224 return flask.jsonify(copr_dict)
225