def delete_volume(volume_name_or_id, **attrs): """ Delete a volume, given its name or ID """ caller_user = _check_authenticated(attrs) volume = Volume.Read(volume_name_or_id) if volume is None or volume.deleted: return {"result": True} if volume.owner_id != caller_user.owner_id and not caller_user.is_admin: raise Exception("Caller cannot delete volume") ret = Volume.Delete(volume.volume_id) if ret: # delete succeeded. # Blow away cert bundle, in deferred task storagetypes.deferred.defer(VolumeCertBundle.Delete, volume.volume_id) # Blow away the MSEntries, in a deferred task storagetypes.deferred.defer(MSEntry.DeleteAll, volume) # Blow away the Gateways, in a deferred task storagetypes.deferred.defer(Gateway.DeleteAll, volume) return {'result': ret}
def create_volume(email, name, description, blocksize, **attrs): caller_user = _check_authenticated(attrs) # user must exist user = read_user(email) if user is None: raise Exception("No such user '%s'" % email) # a user can only create volumes for herself (admin can for anyone) if caller_user.owner_id != user.owner_id and not caller_user.is_admin: raise Exception("Caller cannot create Volumes for other users") # check quota for this user user_volume_ids = list_accessible_volumes(email, caller_user=caller_user, projection=['volume_id']) if len(user_volume_ids) > user.get_volume_quota(): raise Exception("User '%s' has exceeded Volume quota %s" % (email, user.get_volume_quota())) new_volume_key = Volume.Create(user, blocksize=blocksize, name=name, description=description, **attrs) if new_volume_key != None: # create succeed. Make a root directory volume = new_volume_key.get() MSEntry.MakeRoot(user.owner_id, volume) return new_volume_key.get() else: raise Exception("Failed to create Volume")
def delete_volume(volume_name_or_id): volume = Volume.Read(volume_name_or_id) if volume is None: return True ret = Volume.Delete(volume.volume_id) if ret: # delete succeeded. # Blow away the MSEntries, in a deferred task storagetypes.deferred.defer(MSEntry.DeleteAll, volume) # Blow away the Gateways, in a deferred task storagetypes.deferred.defer(Gateway.DeleteAll, volume) return ret
def deactivatevolume(request, volume_id): session = request.session username = session['login_email'] vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) if request.method == "POST": form = libforms.Password(request.POST) if not form.is_valid(): session['message'] = "Password required." return redirect('django_volume.views.volumesettings', vol.volume_id) # Check password hash hash_check = Volume.generate_password_hash( form.cleaned_data['password'], vol.volume_secret_salt) if hash_check != vol.volume_secret_salted_hash: session['message'] = "Incorrect password." return redirect('django_volume.views.volumesettings', vol.volume_id) fields = {'active': False} db.update_volume(vol.volume_id, **fields) session['new_change'] = "We've deactivated your volume." session['next_url'] = '/syn/volume/' + str(vol.volume_id) session['next_message'] = "Click here to go back to your volume." return redirect('/syn/thanks') return redirect("/syn/volume/" + str(vol.volume_id))
def _get_volume_id(volume_name_or_id): try: volume_id = int(volume_name_or_id) return volume_id except: volume = Volume.Read(volume_name_or_id) if volume == None: raise Exception("No such Volume '%s'" % volume_name_or_id) else: return volume.volume_id
def changevolumepassword(request, volume_id): session = request.session username = session['login_email'] vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) if request.method != "POST": return redirect('/syn/volume/' + str(volume_id) + '/settings') form = libforms.ChangePassword(request.POST) if not form.is_valid(): session['message'] = "You must fill out all password fields." return redirect('django_volume.views.volumesettings', volume_id) else: # Check password hash hash_check = Volume.generate_password_hash( form.cleaned_data['oldpassword'], vol.volume_secret_salt) if hash_check != vol.volume_secret_salted_hash: session['message'] = "Incorrect password." return redirect('django_volume.views.volumesettings', volume_id) elif form.cleaned_data['newpassword_1'] != form.cleaned_data[ 'newpassword_2']: session['message'] = "Your new passwords did not match each other." return redirect('django_volume.views.volumesettings', volume_id) # Ok change password kwargs = {} new_volume_secret_salt, new_volume_secret_salted_hash = Volume.generate_volume_secret( form.cleaned_data['newpassword_1']) kwargs['volume_secret_salted_hash'] = new_volume_secret_salted_hash kwargs['volume_secret_salt'] = new_volume_secret_salt db.update_volume(vol.volume_id, **kwargs) session['new_change'] = "We've changed your volume's password." session['next_url'] = '/syn/volume/' + str(vol.volume_id) session['next_message'] = "Click here to go back to your volume." return redirect('/syn/thanks')
def changedesc(request, volume_id): session = request.session username = session['login_email'] vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) if request.method != "POST": return redirect('/syn/volume/' + str(vol.volume_id) + '/settings') form = libforms.Password(request.POST) desc_form = forms.ChangeVolumeD(request.POST) old_data = {} if not form.is_valid(): session['message'] = "Password required." desc_form.is_valid() if desc_form.errors: session['old_data' + str(volume_id)] = "" else: session['old_data' + str(volume_id)] = desc_form.cleaned_data['description'] return redirect('django_volume.views.volumesettings', volume_id) # Check password hash hash_check = Volume.generate_password_hash(form.cleaned_data['password'], vol.volume_secret_salt) if hash_check != vol.volume_secret_salted_hash: session['message'] = "Incorrect password." desc_form.is_valid() if desc_form.errors: session['old_data' + str(volume_id)] = "" else: session['old_data' + str(volume_id)] = desc_form.cleaned_data['description'] return redirect('django_volume.views.volumesettings', volume_id) if not desc_form.is_valid(): session['message'] = "Invalid description field entries." return redirect('django_volume.views.volumesettings', volume_id) kwargs = {} if desc_form.cleaned_data['description']: kwargs['description'] = desc_form.cleaned_data['description'] db.update_volume(vol.volume_id, **kwargs) session.pop('old_data' + str(volume_id), None) session['new_change'] = "We've changed your volume description." session['next_url'] = '/syn/volume/' + str(vol.volume_id) session['next_message'] = "Click here to go back to your volume." return redirect('/syn/thanks')
def changepermissions(request, volume_id): ''' This view handles modification or removal of rights to the volume for users who already had some rights. ''' session = request.session username = session['login_email'] vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) PermissionFormSet = formset_factory(forms.Permissions, extra=0) if request.method != "POST": return redirect('/syn/volume/' + str(vol.volume_id) + '/permissions') else: passwordform = libforms.Password(request.POST) formset = PermissionFormSet(request.POST) if not passwordform.is_valid(): session['message'] = "Password required." return redirect('django_volume.views.volumepermissions', vol.volume_id) else: # Check password hash if vol.volume_secret_salted_hash != Volume.generate_password_hash( passwordform.cleaned_data['password'], vol.volume_secret_salt): session['message'] = "Incorrect password" return redirect('django_volume.views.volumepermissions', vol.volume_id) if not formset.is_valid(): session['message'] = "Invalid field entries." return redirect('django_volume.views.volumepermissions', vol.volume_id) else: initial_and_forms = zip(session['initial_perms' + str(volume_id)], formset.forms) for data, form in initial_and_forms: check_username = data['user'] check_read = form.cleaned_data['read'] check_write = form.cleaned_data['write'] check_user = db.read_user(check_username) if check_write and not check_read: session[ 'message'] = "Write permissions require read permissions as well." return redirect('django_volume.views.volumepermissions', vol.volume_id) if data['write']: if check_write: continue elif check_read: # Give read, take away write new_volumes_r = check_user.volumes_r + [vol.volume_id] new_volumes_rw = check_user.volumes_rw.remove( vol.volume_id) if not new_volumes_rw: new_volumes_rw = [] fields = { 'volumes_r': new_volumes_r, 'volumes_rw': new_volumes_rw } db.update_user(check_username, **fields) else: # change to no permissions new_volumes_rw = check_user.volumes_rw.remove( vol.volume_id) if not new_volumes_rw: new_volumes_rw = [] fields = {'volumes_rw': new_volumes_rw} db.update_user(check_username, **fields) elif data['read']: if check_write: # Give write, take away read new_volumes_r = check_user.volumes_r.remove( vol.volume_id) new_volumes_rw = check_user.volumes_rw + [ vol.volume_id ] if not new_volumes_r: new_volumes_r = [] fields = { 'volumes_r': new_volumes_r, 'volumes_rw': new_volumes_rw } db.update_user(check_username, **fields) elif check_read: continue else: # change to no permissions new_volumes_r = check_user.volumes_r.remove( vol.volume_id) if not new_volumes_r: new_volumes_r = [] fields = {'volumes_r': new_volumes_r} db.update_user(check_username, **fields) # Clear out stale data. session.pop("initial_perms" + str(volume_id), None) session['new_change'] = "We've saved your new permissions." session['next_url'] = '/syn/volume/' + str( vol.volume_id) + '/permissions' session[ 'next_message'] = "Click here to see your volumes permissions." return redirect('/syn/thanks')
def list_volumes(attrs=None, **q_opts): return Volume.ListAll(attrs, **q_opts)
def deletevolume(request, volume_id): ''' View for deleting volumes. Since so many other entites have properties related to volume ID's, numerous db updates need to be checked. CQ, they are all grouped together into the transactional helper method multi_update(). ''' # Clear out volume_id in properties for users, UG's, AG's, and RG's. @transactional(xg=True) def multi_update(vol, users, usergateways, acquisitiongateways, replicagateways): v_id = vol.volume_id db.delete_volume(v_id) logging.info(users) for user in users: fields = {} if v_id in user.volumes_o: new_volumes_o = user.volumes_o new_volumes_o.remove(v_id) fields['volumes_o'] = new_volumes_o if v_id in user.volumes_rw: new_volumes_rw = user.volumes_rw new_volumes_rw.remove(v_id) fields['volumes_rw'] = new_volumes_rw if v_id in user.volumes_r: new_volumes_r = user.volumes_r new_volumes_r.remove(v_id) fields['volumes_r'] = new_volumes_r if fields: db.update_user(user.email, **fields) for ug in usergateways: fields = {} fields['volume_id'] = 0 db.update_user_gateway(ug.g_id, **fields) for ag in acquisitiongateways: logging.info(ag) fields = {} new_ids = ag.volume_ids.remove(v_id) if not new_ids: fields['volume_ids'] = [] else: fields['volume_ids'] = new_ids db.update_acquisition_gateway(ag.g_id, **fields) for rg in replicagateways: fields = {} new_ids = rg.volume_ids.remove(v_id) if not new_ids: fields['volume_ids'] = [] else: fields['volume_ids'] = new_ids db.update_replica_gateway(rg.g_id, **fields) # Clear initial data session variable to prevent stale tables in ag.views.viewgateway and rg.views.viewgateway session.pop("rg_initial_data" + str(v_id), None) session.pop("ag_initial_data" + str(v_id), None) # Clear initial data session variable to prevent stale data in volume settings, change rgs, and change ags. session.pop("volume_initial_ags" + str(v_id), None) session.pop("volume_initial_rgs" + str(v_id), None) session = request.session message = session.pop('message', "") username = session['login_email'] vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) if request.method == "POST": form = forms.DeleteVolume(request.POST) if form.is_valid(): # Check password hash hash_check = Volume.generate_password_hash( form.cleaned_data['password'], vol.volume_secret_salt) if hash_check == vol.volume_secret_salted_hash: # Ok to delete attrs = {} users = db.list_users( {'SyndicateUser.volumes_rw ==': vol.volume_id}) users.extend( db.list_users( {'SyndicateUser.volumes_r ==': vol.volume_id})) ags = db.list_acquisition_gateways_by_volume(vol.volume_id) rgs = db.list_replica_gateways_by_volume(vol.volume_id) ugs = db.list_user_gateways_by_volume(vol.volume_id) try: multi_update(vol, users, ugs, ags, rgs) except Exception as e: logging.error("Unable to delete volume %s" % e) session['message'] = "Unable to delete volume." return redirect('django_volume.views.deletevolume', volume_id=vol.volume_id) session['new_change'] = "We've deleted your volume." session['next_url'] = '/syn/volume/myvolumes/' session[ 'next_message'] = "Click here to go back to your volumes." return redirect('/syn/thanks') else: session['message'] = "Invalid password" return redirect('django_volume.views.deletevolume', volume_id=vol.volume_id) else: session['message'] = "Please fill out all entries" return redirect('django_volume.views.deletevolume', vol.volume_id) else: form = forms.DeleteVolume() t = loader.get_template('deletevolume.html') c = RequestContext(request, { 'username': username, 'form': form, 'message': message, 'volume': vol }) return HttpResponse(t.render(c))
def update_volume(volume_name_or_id, **fields): Volume.Update(volume_name_or_id, **fields) return True
def volume_update_shard_count(volume_id, num_shards): return Volume.update_shard_count(volume_id, num_shards)
def read_volume(volume_name_or_id): return Volume.Read(volume_name_or_id)
def changegateways_rg(request, volume_id): session = request.session username = session['login_email'] vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) @transactional(xg=True) def update(v_id, gnames, vfields, gfields): db.update_volume(v_id, **vfields) for g, gfield in zip(gnames, gfields): db.update_replica_gateway(g, **gfield) session.pop('volume_initial_rgs' + str(volume_id), None) # make sure this variable exists, i.e. they came from the settings page. if not 'volume_initial_rgs' + str(volume_id) in session: return redirect("django_volume.views.volumesettings", volume_id) if request.POST: passwordform = libforms.Password(request.POST) if not passwordform.is_valid(): session['message'] = "Password required." return redirect('django_volume.views.volumesettings', volume_id) else: hash_check = Volume.generate_password_hash( passwordform.cleaned_data['password'], vol.volume_secret_salt) if hash_check != vol.volume_secret_salted_hash: session['message'] = "Incorrect password." return redirect('django_volume.views.volumesettings', volume_id) GatewayFormset = formset_factory(forms.Gateway, extra=0) formset = GatewayFormset(request.POST) formset.is_valid() remove_gateways = [] remove_gateway_names = [] remove_gateway_ids = [] for data, form in zip(session['volume_initial_rgs' + str(volume_id)], formset.forms): if form.cleaned_data['remove']: g = db.read_replica_gateway(data['g_name']) remove_gateways.append(g) remove_gateway_names.append(data['g_name']) remove_gateway_ids.append(g.rg_id) if not remove_gateways: return redirect('django_volume.views.volumesettings', volume_id) new_rgs = list(set(vol.rg_ids) - set(remove_gateway_ids)) vfields = {'rg_ids': new_rgs} gfields = [] for g in remove_gateways: new_vol_ids = g.volume_ids new_vol_ids.remove(vol.volume_id) gfields.append({"volume_ids": new_vol_ids}) try: update(vol.volume_id, remove_gateway_names, vfields, gfields) except Exception as e: session['message'] = "Unable to update volume or RG's." return redirect('django_volume.views.volumesettings', volume_id) session['new_change'] = "We've updated your volume." session['next_url'] = '/syn/volume/' + str(vol.volume_id) + '/settings' session['next_message'] = "Click here to go back to your volume." return redirect('/syn/thanks') else: return redirect('django_volume.views.volumesettings', volume_id=vol.volume_id)
def volume_update_shard_count( volume_id, num_shards ): return Volume.update_shard_count( volume_id, num_shards )
raise Exception("Volume '%s' exists" % volume_cert.name) # "fake" volume version, since the volume version doesn't exist yet... rc = validate_cert_bundle(cert_bundle, user, volume_cert.volume_id, 0) if not rc: raise Exception("Invalid volume cert bundle") # a user can only create volumes for herself (admin can for anyone) if caller_user.owner_id != user.owner_id and not caller_user.is_admin: raise Exception("Caller cannot create Volumes for other users") # check quota for this user if user.get_volume_quota() >= 0: user_volume_ids_qry = Volume.ListAll( {"Volume.owner_id ==": user.owner_id}, keys_only=True, query_only=True) num_volumes = user_volume_ids_qry.count() if num_volumes > user.get_volume_quota(): raise Exception("User '%s' has exceeded Volume quota of %s" % (user.email, user.get_volume_quota())) # verify the root inode root_inode = volume_cert.root root_inode_sigb64 = root_inode.signature root_inode_sig = base64.b64decode(root_inode_sigb64) root_inode.signature = "" root_inode_nosig = root_inode.SerializeToString()
def addpermissions(request, volume_id): ''' This handler allows adding users to volumes so they can have either read access or read and write access. ''' session = request.session username = session['login_email'] if request.method != "POST": return redirect('syn/volume/' + str(vol.volume_id) + '/permissions') else: vol = db.read_volume(volume_id) if not vol: return redirect('django_volume.views.viewvolume', volume_id) addform = forms.AddPermissions(request.POST) passwordform = libforms.Password(request.POST) if not passwordform.is_valid(): session['message'] = "Password required." return redirect('django_volume.views.volumepermissions', vol.volume_id) else: # Check password hash if vol.volume_secret_salted_hash != Volume.generate_password_hash( passwordform.cleaned_data['password'], vol.volume_secret_salt): session['message'] = "Incorrect password" return redirect('django_volume.views.volumepermissions', vol.volume_id) if not addform.is_valid(): session[ 'message'] = "Incorrect entry fields: likely invalid email address." return redirect('django_volume.views.volumepermissions', vol.volume_id) # Ok to update else: new_username = addform.cleaned_data['user'] read = addform.cleaned_data['read'] write = addform.cleaned_data['write'] for data in session['initial_perms' + str(volume_id)]: if data['user'] == new_username: session['message'] = "User already has rights for volume." return redirect('django_volume.views.volumepermissions', vol.volume_id) new_user = db.read_user(new_username) if not new_user: session[ 'message'] = "No Syndicate user with the email {} exists.".format( new_username) return redirect('django_volume.views.volumepermissions', vol.volume_id) if vol.owner_id == new_user.owner_id: session['message'] = "You already own this volume." return redirect('django_volume.views.volumepermissions', vol.volume_id) if write: if read: new_volumes_rw = new_user.volumes_rw + [vol.volume_id] fields = {'volumes_rw': new_volumes_rw} db.update_user(new_username, **fields) else: session[ 'message'] = "Write permissions require read permissions as well." return redirect('django_volume.views.volumepermissions', vol.volume_id) elif read: new_volumes_r = new_user.volumes_r + [vol.volume_id] fields = {'volumes_r': new_volumes_r} db.update_user(new_username, **fields) # Clear out old permissions data. session.pop('initial_perms' + str(volume_id), None) session['new_change'] = "We've saved a new user to your volume." session['next_url'] = '/syn/volume/' + str( vol.volume_id) + '/permissions' session[ 'next_message'] = "Click here to see your volumes permissions." return redirect('/syn/thanks')