def update_app_data(composed_app, data): """ update_app_data(composed_app, data) Updates the App's composer-specific data. @param composed_app: Either the App object itself, or a string containing the app-id. @param data: Data to update the app with. Either a JSON-able dictionary, or a JSON string. @note: This function can only be used by logged-on users, and they must be the owners of the app being saved. """ # Convert ID to App if not done already (otherwise it's NOP). composed_app = _get_app_obj(composed_app) # TODO: Remove this # As a preliminary step towards db migration, we remove bundles information which may be present in the data. if type(data) is str or type(data) is unicode: data = json.loads(data) if type(data) is not str and type(data) is not unicode: if "bundles" in data: del data["bundles"] data = json.dumps(data) if composed_app.owner != current_user(): raise NotAuthorizedException() composed_app.data = data composed_app.modification_date = composed_app.last_access_date = datetime.datetime.utcnow() db.session.add(composed_app) db.session.commit()
def update_app_data(composed_app, data): """ update_app_data(composed_app, data) Updates the App's composer-specific data. @param composed_app: Either the App object itself, or a string containing the app-id. @param data: Data to update the app with. Either a JSON-able dictionary, or a JSON string. @note: This function can only be used by logged-on users, and they must be the owners of the app being saved. """ # Convert ID to App if not done already (otherwise it's NOP). composed_app = _get_app_obj(composed_app) # TODO: Remove this # As a preliminary step towards db migration, we remove bundles information which may be present in the data. if type(data) is str or type(data) is unicode: data = json.loads(data) if type(data) is not str and type(data) is not unicode: if "bundles" in data: del data["bundles"] data = json.dumps(data) if composed_app.owner != current_user(): raise NotAuthorizedException() composed_app.data = data composed_app.modification_date = composed_app.last_access_date = datetime.datetime.utcnow( ) db.session.add(composed_app) db.session.commit()
def transfer_ownership(): # No matter if we are handling a GET or POST, we require these parameters. appid = request.values.get("appid") # Retrieve the application we want to view or edit. app = get_app(appid) if app is None: return render_template("composers/errors.html", message=gettext("App not found")), 404 # Make sure the logged in user owns the app. user = current_user() if app.owner != user: return render_template("composers/errors.html", message=gettext("Not Authorized: User does not own app")), 403 # Get the XMLSPEC bm = BundleManager.create_from_existing_app(app.data) spec = bm.get_gadget_spec() # Get the language lang = request.values.get("lang") if lang is None: return render_template("composers/errors.html", message=gettext("Lang not specified")), 400 # Verify that we are the owners of the language we are trying to transfer. owner_app = _db_get_lang_owner_app(spec, lang) if owner_app != app: return render_template("composers/errors.html", message=gettext("Not Authorized: App does not own language")), 403 # Get the possible apps to which we can concede ownership. apps = _db_get_spec_apps(spec) apps = [a for a in apps if a != app] # We received a POST request. We need to transfer the ownership. if request.method == "POST": # Protect against CSRF attacks. if not verify_csrf(request): return render_template("composers/errors.html", message=gettext("Request does not seem to come from the right source (csrf check)")), 400 # Verify that we were passed the target app. targetapp = get_app(request.values.get("transfer")) if targetapp is None: return render_template("composers/errors.html", message=gettext("Target app not specified")), 400 # Verify that the target app is of the same spec. targetappdata = json.loads(targetapp.data) targetspec = targetappdata["spec"] if targetspec != spec: return render_template("composers/errors.html", message=gettext("Target app does not have the same spec")), 400 # Carry out the transfer. _db_transfer_ownership(lang, app, targetapp) # Redirect to selectlang. return redirect(url_for("translate.translate_selectlang", appid=app.unique_id)) # For GET return render_template("composers/translate/transfer_ownership.html", app=app, apps=apps, xmlspec=spec, lang=lang)
def update_app_data(composed_app, data): """ update_app_data(composed_app, data) Updates the App's composer-specific data. @param composed_app: Either the App object itself, or a string containing the app-id. @param data: Data to update the app with. Either a JSON-able dictionary, or a JSON string. @note: This function can only be used by logged-on users, and they must be the owners of the app being saved. """ # Convert ID to App if not done already (otherwise it's NOP). composed_app = _get_app_obj(composed_app) if type(data) is not str and type(data) is not unicode: data = json.dumps(data) if composed_app.owner != current_user(): raise NotAuthorizedException() composed_app.data = data composed_app.modification_date = composed_app.last_access_date = datetime.datetime.utcnow() db.session.add(composed_app) db.session.commit()
def new(): next_url = request.args.get('next', '') or request.form.get('next', '') name = request.args.get("name") if name is None: return "Missing parameter: name", 400 owner = current_user() app = create_app(name, owner, "dummy", "{'message':'Hello world'}") return "Application created"
def adapt_type_selection(): """ adapt_type_selection() Loads the page that lets the user choose the adaptation type, and that lets the user view or duplicate an existing adaptation instead. This method DOES NOT REQUIRE LOGIN but will display a different view when not logged in. """ # Check if we are logged in. logged_in = current_user() is not None # If we are not logged in disallow POST. if not logged_in and request.method == "POST": return render_template("composers/errors.html", message=gettext("Cannot POST to this URL if not logged in")), 403 # We require the appurl parameter. appurl = request.values.get("appurl") if appurl is None: return render_template("composers/errors.html", message=gettext("appurl parameter not specified")) # Obtain a list of every adaptation that exists in the database for the specified appurl. # TODO: Move db_helpers somewhere else. Makes no sense to use translator files in the adaptor. apps_list = _db_get_spec_apps(appurl) apps = [] for app in apps_list: if app.composer != "adapt": continue apps.append({ "name": app.name, "desc": app.description, "owner": app.owner.name, "type": "adapt", # TO-DO: Specify the specific adaptor sub-type. "app_id": app.unique_id }) # We will only get here if we are logged in if request.method == "POST": # Protect against CSRF attacks. if not verify_csrf(request): return render_template("composers/errors.html", message="Request does not seem to come from the right source (csrf check)"), 400 adaptor_type = request.form["adaptor_type"] if adaptor_type and adaptor_type in ADAPTORS: # In order to show the list of apps we redirect to other url return redirect(url_for("adapt.adapt_create", adaptor_type=adaptor_type)) else: # An adaptor_type is required. flash("Invalid adaptor type", "error") if logged_in: return render_template("composers/adapt/type.html", adaptors=ADAPTORS, apps=apps) # Version for the public else: return render_template("composers/adapt/public_type.html", adaptors=ADAPTORS, apps=apps)
def test_create_app(self): app = api.create_app("UTApp", "dummy", None, "{}") assert app is not None assert app.name == "UTApp" id = app.unique_id # TODO: Probably no point for App to have two different unique ids. app = None app = api.get_app(id) assert app is not None assert app.name == "UTApp" assert app.owner == current_user()
def index(self): """ index(self) This method will be invoked for the Profile Edit view. This view is used for both viewing and updating the user profile. It exposes both GET and POST, for viewing and updating respectively. """ # This will be passed as a template parameter to let us change the password. # (And display the appropriate form field). change_password = True user = current_user() if user is None: return redirect("login") # If it is a POST request to edit the form, then request.form will not be None # Otherwise we will simply load the form data from the DB if len(request.form): form = ProfileEditForm(request.form, csrf_enabled=True) else: # It was a GET request (just viewing). form = ProfileEditForm(csrf_enabled=True) form.name.data = user.name form.login.data = user.login form.email.data = user.email form.organization.data = user.organization form.role.data = user.role form.creation_date.data = user.creation_date form.last_access_date.data = user.last_access_date form.auth_system.data = user.auth_system form.password.data = user.auth_data # If the method is POST we assume that we want to update and not just view if request.method == "POST" and form.validate_on_submit(): # It was a POST request, the data (which has been modified) will be contained in # the request. For security reasons, we manually modify the user for these # settings which should actually be modifiable. user.email = form.email.data user.organization = form.organization.data user.role = form.role.data user.auth_type = form.auth_system.data # Probably in the release we shouldn't let users modify the auth this way if len(form.password.data) > 0: new_password_data = create_salted_password(form.password.data) user.auth_data = new_password_data db.session.add(user) db.session.commit() flash("Changes saved", "success") return self.render("user/profile-edit.html", user=user, form=form, change_password=change_password)
def test_create_app(self): app = api.create_app("UTApp", "dummy", "{}") assert app is not None assert app.name == "UTApp" id = app.unique_id # TODO: Probably no point for App to have two different unique ids. app = None app = api.get_app(id) assert app is not None assert app.name == "UTApp" assert app.owner == current_user()
def get_my_apps(**filters): """ get_my_apps(**filters) Retrieves the current user's app with a specified set of filters for the AppVars. For example: get_my_apps(adaptor_type = 'composer') will only return those apps of the user which match that. @note: This function can only be used by logged-on users. """ user = current_user() if filters: app_vars_query_obj = db.session.query(AppVar.app_id) for filter_name, filter_value in filters.iteritems(): app_vars_query_obj = app_vars_query_obj.filter_by(name=filter_name, value=filter_value) subquery = app_vars_query_obj.subquery() return App.query.filter(App.id.in_(subquery), App.owner == current_user()).all() else: return App.query.filter(App.owner == current_user()).all()
def create_app(name, composer, data, find_new_name=False, description = None): """ create_app(name, data) @param name: Unique name to give to the application. @param composer: Composer identifier. @param data: JSON-able dictionary with the composer-specific data, or the JSON string itself. @return: The app that has been created. @note: This function can be used by any logged-on user. There are no restrictions other than unique (name, owner) combination. """ # Get the current user, who will be the owner of our app. owner = current_user() # To try to create an app we need to be logged in. if owner is None: raise NotAuthorizedException("User is not logged in") # If the composer-specific data is already a string, we assume # it is JSON'ed already. if type(data) is not str and type(data) is not unicode: data = json.dumps(data) # Check if an app with that name and owner exists already. existing_app = App.query.filter_by(owner=owner, name=name).first() if existing_app is not None: if find_new_name: MAX = 10000 counter = 2 while counter < MAX: new_name = '%s (%s)' % (name, counter) existing_app = App.query.filter_by(owner=owner, name=new_name).first() if existing_app is None: name = new_name break counter += 1 if counter == MAX: raise AppExistsException() else: raise AppExistsException() # Create it new_app = App(name, owner, composer, description = description) new_app.data = data # Insert the new app into the database db.session.add(new_app) db.session.commit() return new_app
def get_app_by_name(app_name): """ get_app_by_name(app_name) Retrieves the current user's app with the specified name. @param app_name: Name of the application. Will be unique within the list of user's apps. @return: The app if found, None otherwise. @note: This function can only be used by logged-on users. """ user = current_user() retrieved_app = App.query.filter_by(owner=user, name=app_name).first() return retrieved_app
def get_my_apps(**filters): """ get_my_apps(**filters) Retrieves the current user's app with a specified set of filters for the AppVars. For example: get_my_apps(adaptor_type = 'composer') will only return those apps of the user which match that. @note: This function can only be used by logged-on users. """ user = current_user() if filters: app_vars_query_obj = db.session.query(AppVar.app_id) for filter_name, filter_value in filters.iteritems(): app_vars_query_obj = app_vars_query_obj.filter_by( name=filter_name, value=filter_value) subquery = app_vars_query_obj.subquery() return App.query.filter(App.id.in_(subquery), App.owner == current_user()).all() else: return App.query.filter(App.owner == current_user()).all()
def save_app(composed_app): """ save_app(app) Saves the App object to the database. Useful when the object has been modified. @param app: App object @return: None. @note: This function can only be used by logged on users, and they must be the owners of the app being saved. """ if composed_app.owner != current_user(): raise NotAuthorizedException() composed_app.modification_date = composed_app.last_access_date = datetime.datetime.utcnow() db.session.add(composed_app) db.session.commit()
def adapt_preview(appid): """ adapt_preview(appid) Previews an application. You can preview the app of any user. # TODO: Eventually the preview feature should probably be merged into view_edit, through a read-only mode. LOGIN IS OPTIONAL FOR THIS METHOD. @param appid: Appid of the app to preview. """ if not appid: return render_template("composers/errors.html", message=gettext("appid not provided")), 400 # Check whether we are logged in. logged_in = current_user() is not None # TODO: Improve this: do not load the whole thing. We just need the variables. app = appstorage.get_app(appid) if app is None: return render_template("composers/errors.html", message=gettext("app not found")), 500 adaptor_types = [var for var in app.appvars if var.name == 'adaptor_type'] if not adaptor_types: return render_template("composers/errors.html", message=gettext("Error: no attached adaptor_type variable")), 500 adaptor_type = adaptor_types[0].value if adaptor_type not in ADAPTORS: return render_template("composers/errors.html", message=gettext("Error: adaptor %s not currently supported") % adaptor_type), 500 adaptor_plugin = ADAPTORS[adaptor_type]['adaptor'] # TODO: URLs seem to be dependent on adaptor type. This is meant to work with jsconfig at least. # Calculate the URL for the Preview iframe. app_url = url_for('%s.app_xml' % adaptor_type, app_id=appid, _external=True) preview_url = shindig_url("/gadgets/ifr?nocache=1&url=%s" % app_url) # Retrieve the URL from the appdata. appdata = json.loads(app.data) spec_url = appdata["url"] return render_template("composers/adapt/preview.html", logged_in=logged_in, app_id=appid, app_url=app_url, spec_url=spec_url, name=app.name, preview_url=preview_url)
def save_app(composed_app): """ save_app(app) Saves the App object to the database. Useful when the object has been modified. @param app: App object @return: None. @note: This function can only be used by logged on users, and they must be the owners of the app being saved. """ if composed_app.owner != current_user(): raise NotAuthorizedException() composed_app.modification_date = composed_app.last_access_date = datetime.datetime.utcnow( ) db.session.add(composed_app) db.session.commit()
def delete_app(composed_app): """ delete_app(composed_app) @param composed_app: The app that we want to delete. It can either be the app object itself or an app-id. @return: nothing. @note: This function can only be used by logged-on users, and they must be the owners of the app being saved. """ composed_app = _get_app_obj(composed_app) if composed_app.owner != current_user(): raise NotAuthorizedException() # Delete every AppVar for that App. Otherwise, as of now, deletion doesn't work because # the delete cascade on the relationship has some problem. # TODO: Fix me. AppVar.query.filter_by(app=composed_app).delete() db.session.delete(composed_app) db.session.commit()
def adapt_type_selection(): """ adapt_type_selection() Loads the page that lets the user choose the adaptation type, and that lets the user view or duplicate an existing adaptation instead. This method DOES NOT REQUIRE LOGIN but will display a different view when not logged in. """ # Check if we are logged in. logged_in = current_user() is not None # If we are not logged in disallow POST. if not logged_in and request.method == "POST": return render_template( "composers/errors.html", message=gettext("Cannot POST to this URL if not logged in")), 403 # We require the appurl parameter. appurl = request.values.get("appurl") if appurl is None: return render_template( "composers/errors.html", message=gettext("appurl parameter not specified")) # Obtain a list of every adaptation that exists in the database for the specified appurl. # TODO: Move db_helpers somewhere else. Makes no sense to use translator files in the adaptor. apps_list = _db_get_spec_apps(appurl) apps = [] for app in apps_list: if app.composer != "adapt": continue apps.append({ "name": app.name, "desc": app.description, "owner": app.owner.name, "type": "adapt", # TO-DO: Specify the specific adaptor sub-type. "app_id": app.unique_id }) # We will only get here if we are logged in if request.method == "POST": # Protect against CSRF attacks. if not verify_csrf(request): return render_template( "composers/errors.html", message= "Request does not seem to come from the right source (csrf check)" ), 400 adaptor_type = request.form["adaptor_type"] if adaptor_type and adaptor_type in ADAPTORS: # In order to show the list of apps we redirect to other url return redirect( url_for("adapt.adapt_create", adaptor_type=adaptor_type)) else: # An adaptor_type is required. flash("Invalid adaptor type", "error") if logged_in: return render_template("composers/adapt/type.html", adaptors=ADAPTORS, apps=apps) # Version for the public else: return render_template("composers/adapt/public_type.html", adaptors=ADAPTORS, apps=apps)
def create_app(name, composer, spec_url, data, find_new_name=False, description=None): """ @param {str} name: Unique name to give to the application. @param {str} composer: Composer identifier. @param {str} spec_url: Spec URL that the app is linked to. It can be None. @param {dict} data: JSON-able dictionary with the composer-specific data, or the JSON string itself. @param {bool} find_new_name: Whether the name should be auto-modified with a number to make it unique or throw an exception. @param {str} description: Description of the app. @return {App}: The app that has been created. @note: This function can be used by any logged-on user. There are no restrictions other than unique (name, owner) combination. """ # Get the current user, who will be the owner of our app. owner = current_user() # To try to create an app we need to be logged in. if owner is None: raise NotAuthorizedException("User is not logged in") # If the composer-specific data is already a string, we assume # it is JSON'ed already. if type(data) is not str and type(data) is not unicode: data = json.dumps(data) # Check if an app with that name and owner exists already. existing_app = App.query.filter_by(owner=owner, name=name).first() if existing_app is not None: if find_new_name: MAX = 10000 counter = 2 while counter < MAX: new_name = '%s (%s)' % (name, counter) existing_app = App.query.filter_by(owner=owner, name=new_name).first() if existing_app is None: name = new_name break counter += 1 if counter == MAX: raise AppExistsException() else: raise AppExistsException() # Create the Spec object. if spec_url is not None: spec = getcreate_spec(spec_url) else: spec = None # Create it new_app = App(name, owner, composer, description=description) new_app.data = data new_app.spec = spec # Insert the new app into the database db.session.add(new_app) db.session.commit() return new_app
def is_accessible(self): return current_user() is not None
def _is_admin(): _current_user = current_user() return _current_user and _current_user.role == Role.admin
def create_app(name, composer, spec_url, data, find_new_name=False, description=None): """ @param {str} name: Unique name to give to the application. @param {str} composer: Composer identifier. @param {str} spec_url: Spec URL that the app is linked to. It can be None. @param {dict} data: JSON-able dictionary with the composer-specific data, or the JSON string itself. @param {bool} find_new_name: Whether the name should be auto-modified with a number to make it unique or throw an exception. @param {str} description: Description of the app. @return {App}: The app that has been created. @note: This function can be used by any logged-on user. There are no restrictions other than unique (name, owner) combination. """ # Get the current user, who will be the owner of our app. owner = current_user() # To try to create an app we need to be logged in. if owner is None: raise NotAuthorizedException("User is not logged in") # If the composer-specific data is already a string, we assume # it is JSON'ed already. if type(data) is not str and type(data) is not unicode: data = json.dumps(data) # Check if an app with that name and owner exists already. existing_app = App.query.filter_by(owner=owner, name=name).first() if existing_app is not None: if find_new_name: MAX = 10000 counter = 2 while counter < MAX: new_name = "%s (%s)" % (name, counter) existing_app = App.query.filter_by(owner=owner, name=new_name).first() if existing_app is None: name = new_name break counter += 1 if counter == MAX: raise AppExistsException() else: raise AppExistsException() # Create the Spec object. if spec_url is not None: spec = getcreate_spec(spec_url) else: spec = None # Create it new_app = App(name, owner, composer, description=description) new_app.data = data new_app.spec = spec # Insert the new app into the database db.session.add(new_app) db.session.commit() return new_app
def test_current_user(self): cu = current_user() assert cu.login == "testuser"