{dataType: 'json',
type: $(this).attr('data-remote-method'),
data: {
- 'link[head_kind]': 'arvados#collection',
'link[head_uuid]': tag_head_uuid,
'link[link_class]': 'tag',
'link[name]': new_tag
});
}
}
-
+
var fixer = new HeaderRowFixer('.table-fixed-header-row');
fixer.duplicateTheadTr();
fixer.fixThead();
chash.each do |k,v|
l = Link.new({
- tail_kind: "arvados#collection",
tail_uuid: k,
- head_kind: "arvados#collection",
head_uuid: newuuid,
link_class: "provenance",
name: "provided"
Link.where(tail_uuid: @sourcedata.keys).each do |link|
if link.link_class == 'data_origin'
@sourcedata[link.tail_uuid][:data_origins] ||= []
- @sourcedata[link.tail_uuid][:data_origins] << [link.name, link.head_kind, link.head_uuid]
+ @sourcedata[link.tail_uuid][:data_origins] << [link.name, link.head_uuid]
end
end
Collection.where(uuid: @sourcedata.keys).each do |collection|
@sourcedata[collection.uuid][:collection] = collection
end
end
-
+
Collection.where(uuid: @object.uuid).each do |u|
puts request
- @prov_svg = ProvenanceHelper::create_provenance_graph(u.provenance, "provenance_svg",
+ @prov_svg = ProvenanceHelper::create_provenance_graph(u.provenance, "provenance_svg",
{:request => request,
- :direction => :bottom_up,
+ :direction => :bottom_up,
:combine_jobs => :script_only}) rescue nil
- @used_by_svg = ProvenanceHelper::create_provenance_graph(u.used_by, "used_by_svg",
+ @used_by_svg = ProvenanceHelper::create_provenance_graph(u.used_by, "used_by_svg",
{:request => request,
- :direction => :top_down,
- :combine_jobs => :script_only,
+ :direction => :top_down,
+ :combine_jobs => :script_only,
:pdata_only => true}) rescue nil
end
end
def home
@showallalerts = false
@my_ssh_keys = AuthorizedKey.where(authorized_user_uuid: current_user.uuid)
- # @my_vm_perms = Link.where(tail_uuid: current_user.uuid, head_kind: 'arvados#virtual_machine', link_class: 'permission', name: 'can_login')
- # @my_repo_perms = Link.where(tail_uuid: current_user.uuid, head_kind: 'arvados#repository', link_class: 'permission', name: 'can_write')
-
@my_tag_links = {}
@my_jobs = Job.
'modified_by_user_uuid' => '004',
'modified_by_client_uuid' => '005',
'name' => '050',
- 'tail_kind' => '100',
'tail_uuid' => '100',
- 'head_kind' => '101',
'head_uuid' => '101',
'info' => 'zzz-000',
'updated_at' => 'zzz-999'
true
end
end
-
+
def links(*args)
o = {}
o.merge!(args.pop) if args[-1].is_a? Hash
o[:link_class] ||= args.shift
o[:name] ||= args.shift
- o[:head_kind] ||= args.shift
- o[:tail_kind] = self.kind
o[:tail_uuid] = self.uuid
if all_links
return all_links.select do |m|
attr_accessor :head
attr_accessor :tail
def self.by_tail(t, opts={})
- where(opts.merge :tail_kind => t.kind, :tail_uuid => t.uuid)
+ where(opts.merge :tail_uuid => t.uuid)
end
end
read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
{
-"tail_kind":"arvados#user",
"tail_uuid":"$user_uuid",
-"head_kind":"arvados#virtualMachine",
"head_uuid":"$vm_uuid",
"link_class":"permission",
"name":"can_login",
read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
{
-"tail_kind":"arvados#user",
"tail_uuid":"$user_uuid",
-"head_kind":"arvados#repository",
"head_uuid":"$repo_uuid",
"link_class":"permission",
"name":"can_write",
table(table table-bordered table-condensed).
|_. Attribute|_. Type|_. Description|
|tail_uuid|string|Object UUID at the tail (start, source, origin) of this link|
-|tail_kind|string|Object kind at the tail (start, source, origin) of this link|
|link_class|string|Class (see below)|
|name|string|Link type (see below)|
|head_uuid|string|Object UUID at the head (end, destination, target) of this link|
-|head_kind|string|Object kind at the head (end, destination, target) of this link|
|properties{}|list|Additional information, expressed as a key→value hash. Key: string. Value: string, number, array, or hash.|
h2. Link classes
table(table table-bordered table-condensed).
|_. Attribute|_. Type|_. Description|_. Example|
-|object_kind|string|||
|object_uuid|string|||
|event_at|datetime|||
|event_type|string|A user-defined category or type for this event.|@LOGIN@|
read -rd $'\000' newlink <<EOF; arv link create --link "$newlink"
{
- "tail_kind":"arvados#group",
"tail_uuid":"$all_users_group_uuid",
- "head_kind":"arvados#repository",
"head_uuid":"$repo_uuid",
"link_class":"permission",
"name":"can_read"
We query the "links" resource to find humans that report the selected trait. Links are directional connections between Arvados data items, for example, from a human to their reported traits.
<notextile>
-<pre><code>>>> <span class="userinput">trait_query = {
- 'link_class': 'human_trait',
- 'tail_kind': 'arvados#human',
- 'head_uuid': non_melanoma_cancer
- }
+<pre><code>>>> <span class="userinput">trait_filter = [
+ ['link_class', '=', 'human_trait'],
+ ['tail_uuid', 'is_a', 'arvados#human'],
+ ['head_uuid', '=', non_melanoma_cancer],
+ ]
</code></pre>
</notextile>
-* @'link_class'@ queries for links that describe the traits of a particular human.
-* @'tail_kind'@ queries for links where the tail of the link is a human.
-* @'head_uuit'@ queries for links where the head of the link is a specific data item.
+* @['link_class', '=', 'human_trait']@ filters on links that connect phenotype traits to individuals in the database.
+* @['tail_uuid', 'is_a', 'arvados#human']@ filters that the "tail" must be a "human" database object.
+* @['head_uuid', '=', non_melanoma_cancer]@ filters that the "head" of the link must connect to the "trait" database object non_melanoma_cancer .
The query will return links that match all three conditions.
<notextile>
-<pre><code>>>> <span class="userinput">trait_links = arvados.api().links().list(limit=1000, where=trait_query).execute()</span>
+<pre><code>>>> <span class="userinput">trait_links = arvados.api().links().list(limit=1000, filters=trait_filter).execute()</span>
</code></pre>
</notextile>
def create
@object = model_class.new resource_attrs
- if @object.save
- show
- else
- raise "Save failed"
- end
+ @object.save!
+ show
end
def update
attrs_to_update = resource_attrs.reject { |k,v|
[:kind, :etag, :href].index k
}
- if @object.update_attributes attrs_to_update
- show
- else
- raise "Update failed"
- end
+ @object.update_attributes! attrs_to_update
+ show
end
def destroy
cond_out << "#{table_name}.#{attr} IN (?)"
param_out << operand
end
+ when 'is_a'
+ operand = [operand] unless operand.is_a? Array
+ cond = []
+ operand.each do |op|
+ cl = ArvadosModel::kind_class op
+ if cl
+ cond << "#{table_name}.#{attr} like ?"
+ param_out << cl.uuid_like_pattern
+ else
+ cond << "1=0"
+ end
+ end
+ cond_out << cond.join(' OR ')
end
end
if cond_out.any?
# exist) giving the current user (or specified owner_uuid)
# permission to read it.
owner_uuid = resource_attrs.delete(:owner_uuid) || current_user.uuid
- owner_kind = if owner_uuid.match(/-(\w+)-/)[1] == User.uuid_prefix
- 'arvados#user'
- else
- 'arvados#group'
- end
unless current_user.can? write: owner_uuid
logger.warn "User #{current_user.andand.uuid} tried to set collection owner_uuid to #{owner_uuid}"
raise ArvadosModel::PermissionDeniedError
owner_uuid: owner_uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#collection',
head_uuid: @object.uuid,
- tail_kind: owner_kind,
tail_uuid: owner_uuid
}
ActiveRecord::Base.transaction do
def cancel
reload_object_before_update
- @object.update_attributes cancelled_at: Time.now
+ @object.update_attributes! cancelled_at: Time.now
show
end
service_ssl_flag: true
}
end
+
def ping
params[:service_host] ||= request.env['REMOTE_ADDR']
- if not @object.ping params
- return render_not_found "object not found"
+ act_as_system_user do
+ if not @object.ping params
+ return render_not_found "object not found"
+ end
+ # Render the :superuser view (i.e., include the ping_secret) even
+ # if !current_user.is_admin. This is safe because @object.ping's
+ # success implies the ping_secret was already known by the client.
+ render json: @object.as_api_response(:superuser)
end
- # Render the :superuser view (i.e., include the ping_secret) even
- # if !current_user.is_admin. This is safe because @object.ping's
- # success implies the ping_secret was already known by the client.
- render json: @object.as_api_response(:superuser)
end
def find_objects_for_index
def self._ping_requires_parameters
{ ping_secret: true }
end
+
def ping
- @object = Node.where(uuid: (params[:id] || params[:uuid])).first
- if !@object
- return render_not_found
- end
- @object.ping({ ip: params[:local_ipv4] || request.env['REMOTE_ADDR'],
- ping_secret: params[:ping_secret],
- ec2_instance_id: params[:instance_id] })
- if @object.info[:ping_secret] == params[:ping_secret]
- render json: @object.as_api_response(:superuser)
- else
- raise "Invalid ping_secret after ping"
+ act_as_system_user do
+ @object = Node.where(uuid: (params[:id] || params[:uuid])).first
+ if !@object
+ return render_not_found
+ end
+ @object.ping({ ip: params[:local_ipv4] || request.env['REMOTE_ADDR'],
+ ping_secret: params[:ping_secret],
+ ec2_instance_id: params[:instance_id] })
+ if @object.info[:ping_secret] == params[:ping_secret]
+ render json: @object.as_api_response(:superuser)
+ else
+ raise "Invalid ping_secret after ping"
+ end
end
end
gitolite_permissions = ''
perms = []
repo.permissions.each do |perm|
- if perm.tail_kind == 'arvados#group'
+ if ArvadosModel::resource_class_for_uuid(perm.tail_uuid) == Group
@users.each do |user_uuid, user|
user.group_permissions.each do |group_uuid, perm_mask|
if perm_mask[:write]
else
current_user_uuid = current_user.uuid
act_as_system_user do
- uuids = Link.where(owner_uuid: system_user_uuid,
- link_class: 'signature',
- name: 'require',
- tail_kind: 'arvados#user',
- tail_uuid: system_user_uuid,
- head_kind: 'arvados#collection').
+ uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+ system_user_uuid,
+ 'signature',
+ 'require',
+ system_user_uuid,
+ Collection.uuid_like_pattern).
collect &:head_uuid
@objects = Collection.where('uuid in (?)', uuids)
end
current_user_uuid = (current_user.andand.is_admin && params[:uuid]) ||
current_user.uuid
act_as_system_user do
- @objects = Link.where(owner_uuid: system_user_uuid,
- link_class: 'signature',
- name: 'click',
- tail_kind: 'arvados#user',
- tail_uuid: current_user_uuid,
- head_kind: 'arvados#collection')
+ @objects = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+ system_user_uuid,
+ 'signature',
+ 'click',
+ current_user_uuid,
+ Collection.uuid_like_pattern)
end
@response_resource_name = 'link'
render_list
act_as_system_user do
@object = Link.create(link_class: 'signature',
name: 'click',
- tail_kind: 'arvados#user',
tail_uuid: current_user_uuid,
- head_kind: 'arvados#collection',
head_uuid: params[:uuid])
end
show
"but is not invited"
raise ArgumentError.new "Cannot activate without being invited."
end
- act_as_system_user do
- required_uuids = Link.where(owner_uuid: system_user_uuid,
- link_class: 'signature',
- name: 'require',
- tail_uuid: system_user_uuid,
- head_kind: 'arvados#collection').
+ act_as_system_user do
+ required_uuids = Link.where("owner_uuid = ? and link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+ system_user_uuid,
+ 'signature',
+ 'require',
+ system_user_uuid,
+ Collection.uuid_like_pattern).
collect(&:head_uuid)
signed_uuids = Link.where(owner_uuid: system_user_uuid,
link_class: 'signature',
name: 'click',
- tail_kind: 'arvados#user',
tail_uuid: @object.uuid,
- head_kind: 'arvados#collection',
head_uuid: required_uuids).
collect(&:head_uuid)
todo_uuids = required_uuids - signed_uuids
if not user
# Check for permission to log in to an existing User record with
# a different identity_url
- Link.where(link_class: 'permission',
- name: 'can_login',
- tail_kind: 'email',
- tail_uuid: omniauth['info']['email'],
- head_kind: 'arvados#user').each do |link|
+ Link.where("link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
+ 'permission',
+ 'can_login',
+ omniauth['info']['email'],
+ User.uuid_like_pattern).each do |link|
if prefix = link.properties['identity_url_prefix']
if prefix == omniauth['info']['identity_url'][0..prefix.size-1]
user = User.find_by_uuid(link.head_uuid)
before_create :ensure_permission_to_create
before_update :ensure_permission_to_update
before_destroy :ensure_permission_to_destroy
- before_create :update_modified_by_fields
- before_update :maybe_update_modified_by_fields
+
+ before_validation :maybe_update_modified_by_fields
validate :ensure_serialized_attribute_type
validate :normalize_collection_uuids
+ validate :ensure_valid_uuids
has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'"
end
def self.kind_class(kind)
- kind.match(/^arvados\#(.+?)(_list|List)?$/)[1].pluralize.classify.constantize rescue nil
+ kind.match(/^arvados\#(.+)$/)[1].classify.safe_constantize rescue nil
end
def href
self.columns.select { |col| col.name == attr.to_s }.first
end
- def eager_load_associations
- self.class.columns.each do |col|
- re = col.name.match /^(.*)_kind$/
- if (re and
- self.respond_to? re[1].to_sym and
- (auuid = self.send((re[1] + '_uuid').to_sym)) and
- (aclass = self.class.kind_class(self.send(col.name.to_sym))) and
- (aobject = aclass.where('uuid=?', auuid).first))
- self.instance_variable_set('@'+re[1], aobject)
- end
- end
- end
+ # def eager_load_associations
+ # self.class.columns.each do |col|
+ # re = col.name.match /^(.*)_kind$/
+ # if (re and
+ # self.respond_to? re[1].to_sym and
+ # (auuid = self.send((re[1] + '_uuid').to_sym)) and
+ # (aclass = self.class.kind_class(self.send(col.name.to_sym))) and
+ # (aobject = aclass.where('uuid=?', auuid).first))
+ # self.instance_variable_set('@'+re[1], aobject)
+ # end
+ # end
+ # end
def self.readable_by user
uuid_list = [user.uuid, *user.groups_i_can(:read)]
end
def maybe_update_modified_by_fields
- update_modified_by_fields if self.changed?
+ update_modified_by_fields if self.changed? or self.new_record?
end
def update_modified_by_fields
attributes.keys.select { |a| a.match /_uuid$/ }
end
+ def skip_uuid_read_permission_check
+ %w(modified_by_client_uuid)
+ end
+
def normalize_collection_uuids
foreign_key_attributes.each do |attr|
attr_value = send attr
end
end
+ @@UUID_REGEX = /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/
+
+ @@prefixes_hash = nil
+ def self.uuid_prefixes
+ unless @@prefixes_hash
+ @@prefixes_hash = {}
+ ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
+ if k.respond_to?(:uuid_prefix)
+ @@prefixes_hash[k.uuid_prefix] = k
+ end
+ end
+ end
+ @@prefixes_hash
+ end
+
+ def self.uuid_like_pattern
+ "_____-#{uuid_prefix}-_______________"
+ end
+
+ def ensure_valid_uuids
+ specials = [system_user_uuid, 'd41d8cd98f00b204e9800998ecf8427e+0']
+
+ foreign_key_attributes.each do |attr|
+ begin
+ if new_record? or send (attr + "_changed?")
+ attr_value = send attr
+ r = ArvadosModel::resource_class_for_uuid attr_value if attr_value
+ r = r.readable_by(current_user) if r and not skip_uuid_read_permission_check.include? attr
+ if r and r.where(uuid: attr_value).count == 0 and not specials.include? attr_value
+ errors.add(attr, "'#{attr_value}' not found")
+ end
+ end
+ rescue Exception => e
+ bt = e.backtrace.join("\n")
+ errors.add(attr, "'#{attr_value}' error '#{e}'\n#{bt}\n")
+ end
+ end
+ end
+
def self.resource_class_for_uuid(uuid)
if uuid.is_a? ArvadosModel
return uuid.class
resource_class = nil
Rails.application.eager_load!
- uuid.match /^[0-9a-z]{5}-([0-9a-z]{5})-[0-9a-z]{15}$/ do |re|
- ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
- if k.respond_to?(:uuid_prefix)
- if k.uuid_prefix == re[1]
- return k
- end
- end
- end
+ uuid.match @@UUID_REGEX do |re|
+ return uuid_prefixes[re[1]] if uuid_prefixes[re[1]]
end
nil
end
end
end
+ def self.uuid_like_pattern
+ "________________________________+%"
+ end
+
def self.normalize_uuid uuid
hash_part = nil
size_part = nil
super + %w(output log)
end
+ def skip_uuid_read_permission_check
+ super + %w(cancelled_by_client_uuid)
+ end
+
def ensure_script_version_is_commit
if self.is_locked_by_uuid and self.started_at
# Apparently client has already decided to go for it. This is
t.add :ping_secret
end
+ def foreign_key_attributes
+ super.reject { |a| a == "filesystem_uuid" }
+ end
+
def ping(o)
raise "must have :service_host and :ping_secret" unless o[:service_host] and o[:ping_secret]
end
@bypass_arvados_authorization = true
- self.update_attributes(o.select { |k,v|
+ self.update_attributes!(o.select { |k,v|
[:service_host,
:service_port,
:service_ssl_flag,
attr_accessor :tail
api_accessible :user, extend: :common do |t|
- t.add :tail_kind
t.add :tail_uuid
t.add :link_class
t.add :name
- t.add :head_kind
t.add :head_uuid
t.add :head, :if => :head
t.add :tail, :if => :tail
# All users can grant permissions on objects they own
head_obj = self.class.
- kind_class(self.head_kind).
+ kind_class(self.head_uuid).
where('uuid=?',head_uuid).
first
if head_obj
attr_accessor :object
api_accessible :user, extend: :common do |t|
- t.add :object_kind
t.add :object_uuid
t.add :object, :if => :object
t.add :event_at
Group.where('owner_uuid in (?)', lookup_uuids).each do |group|
newgroups << [group.owner_uuid, group.uuid, 'can_manage']
end
- Link.where('tail_uuid in (?) and link_class = ? and head_kind in (?)',
+ Link.where('tail_uuid in (?) and link_class = ? and (head_uuid like ? or head_uuid like ?)',
lookup_uuids,
'permission',
- ['arvados#group', 'arvados#user']).each do |link|
+ Group.uuid_like_pattern,
+ User.uuid_like_pattern).each do |link|
newgroups << [link.tail_uuid, link.head_uuid, link.name]
end
newgroups.each do |tail_uuid, head_uuid, perm_name|
--- /dev/null
+class RemoveKindColumns < ActiveRecord::Migration
+ def up
+ remove_column :links, :head_kind
+ remove_column :links, :tail_kind
+ remove_column :logs, :object_kind
+ end
+
+ def down
+ add_column :links, :head_kind, :string
+ add_column :links, :tail_kind, :string
+ add_column :logs, :object_kind, :string
+ end
+end
t.string "modified_by_user_uuid"
t.datetime "modified_at"
t.string "tail_uuid"
- t.string "tail_kind"
t.string "link_class"
t.string "name"
t.string "head_uuid"
t.text "properties"
t.datetime "updated_at"
- t.string "head_kind"
end
add_index "links", ["created_at"], :name => "index_links_on_created_at"
- add_index "links", ["head_kind"], :name => "index_links_on_head_kind"
add_index "links", ["head_uuid"], :name => "index_links_on_head_uuid"
add_index "links", ["modified_at"], :name => "index_links_on_modified_at"
- add_index "links", ["tail_kind"], :name => "index_links_on_tail_kind"
add_index "links", ["tail_uuid"], :name => "index_links_on_tail_uuid"
add_index "links", ["uuid"], :name => "index_links_on_uuid", :unique => true
t.string "owner_uuid"
t.string "modified_by_client_uuid"
t.string "modified_by_user_uuid"
- t.string "object_kind"
t.string "object_uuid"
t.datetime "event_at"
t.string "event_type"
add_index "logs", ["event_at"], :name => "index_logs_on_event_at"
add_index "logs", ["event_type"], :name => "index_logs_on_event_type"
add_index "logs", ["modified_at"], :name => "index_logs_on_modified_at"
- add_index "logs", ["object_kind"], :name => "index_logs_on_object_kind"
add_index "logs", ["object_uuid"], :name => "index_logs_on_object_uuid"
add_index "logs", ["summary"], :name => "index_logs_on_summary"
add_index "logs", ["uuid"], :name => "index_logs_on_uuid", :unique => true
modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
modified_at: 2013-12-26T19:52:21Z
updated_at: 2013-12-26T19:52:21Z
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-000000000000000
link_class: signature
name: require
- head_kind: arvados#collection
head_uuid: b519d9cb706a29fc7ea24dbea2f05851+249025
properties: {}
modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#group
tail_uuid: zzzzz-j7d0g-fffffffffffffff
link_class: permission
name: can_read
- head_kind: arvados#collection
head_uuid: b519d9cb706a29fc7ea24dbea2f05851+249025
properties: {}
modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
link_class: permission
name: can_read
- head_kind: arvados#group
head_uuid: zzzzz-j7d0g-fffffffffffffff
properties: {}
modified_by_user_uuid: zzzzz-tpzed-000000000000000
modified_at: 2014-02-03 15:42:26 -0800
updated_at: 2014-02-03 15:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
link_class: permission
name: can_manage
- head_kind: arvados#group
head_uuid: zzzzz-j7d0g-8ulrifv67tve5sx
properties: {}
modified_by_user_uuid: zzzzz-tpzed-xurymjxw79nv3jz
modified_at: 2013-12-26T20:52:21Z
updated_at: 2013-12-26T20:52:21Z
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
link_class: signature
name: click
- head_kind: arvados#collection
head_uuid: b519d9cb706a29fc7ea24dbea2f05851+249025
properties: {}
modified_by_user_uuid: zzzzz-tpzed-7sg468ezxwnodxs
modified_at: 2013-12-26T20:52:21Z
updated_at: 2013-12-26T20:52:21Z
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-7sg468ezxwnodxs
link_class: signature
name: click
- head_kind: arvados#collection
head_uuid: b519d9cb706a29fc7ea24dbea2f05851+249025
properties: {}
modified_by_user_uuid: zzzzz-tpzed-d9tiejq69daie8f
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
link_class: permission
name: can_read
- head_kind: arvados#group
head_uuid: zzzzz-j7d0g-fffffffffffffff
properties: {}
modified_by_user_uuid: zzzzz-tpzed-7sg468ezxwnodxs
modified_at: 2013-12-26T20:52:21Z
updated_at: 2013-12-26T20:52:21Z
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-x9kqpd79egh49c7
link_class: permission
name: can_read
- head_kind: arvados#group
head_uuid: zzzzz-j7d0g-fffffffffffffff
properties: {}
modified_by_user_uuid: zzzzz-tpzed-7sg468ezxwnodxs
modified_at: 2013-12-26T20:52:21Z
updated_at: 2013-12-26T20:52:21Z
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-7sg468ezxwnodxs
link_class: permission
name: can_read
- head_kind: arvados#group
head_uuid: zzzzz-j7d0g-fffffffffffffff
properties: {}
modified_by_user_uuid: zzzzz-tpzed-000000000000000
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
link_class: permission
name: can_read
- head_kind: arvados#collection
head_uuid: 1f4b0bc7583c2a7f9102c395f4ffc5e3+45
properties: {}
modified_by_user_uuid: zzzzz-tpzed-000000000000000
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-xurymjxw79nv3jz
link_class: permission
name: can_read
- head_kind: arvados#collection
head_uuid: fa7aeb5140e2848d39b416daeef4ffc5+45
properties: {}
modified_by_user_uuid: zzzzz-tpzed-000000000000000
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
link_class: permission
name: can_read
- head_kind: arvados#collection
head_uuid: fa7aeb5140e2848d39b416daeef4ffc5+45
properties: {}
modified_by_user_uuid: zzzzz-tpzed-000000000000000
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#group
tail_uuid: zzzzz-j7d0g-fffffffffffffff
link_class: permission
name: can_read
- head_kind: arvados#collection
head_uuid: ea10d51bcf88862dbcc36eb292017dfd+45
properties: {}
modified_by_user_uuid: zzzzz-tpzed-000000000000000
modified_at: 2014-01-24 20:42:26 -0800
updated_at: 2014-01-24 20:42:26 -0800
- tail_kind: arvados#user
tail_uuid: zzzzz-tpzed-l1s2piq4t4mps8r
link_class: permission
name: can_read
- head_kind: arvados#job
head_uuid: zzzzz-8i9sb-cjs4pklxxjykyuq
properties: {}
uuid: zzzzz-2x53u-382brsig8rp3064
owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
hostname: testvm.shell
+
+testvm2:
+ uuid: zzzzz-2x53u-382brsig8rp3065
+ owner_uuid: zzzzz-tpzed-d9tiejq69daie8f
+ hostname: testvm2.shell
properties: {username: 'testusername'},
link_class: 'test',
name: 'encoding',
- tail_kind: 'arvados#user',
tail_uuid: users(:admin).uuid,
- head_kind: 'arvados#virtualMachine',
head_uuid: virtual_machines(:testvm).uuid
}
authorize_with :admin
end
end
+ test "head must exist" do
+ link = {
+ link_class: 'test',
+ name: 'stuff',
+ tail_uuid: users(:active).uuid,
+ head_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+ }
+ authorize_with :admin
+ post :create, link: link
+ assert_response 422
+ end
+
+ test "tail must exist" do
+ link = {
+ link_class: 'test',
+ name: 'stuff',
+ head_uuid: users(:active).uuid,
+ tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+ }
+ authorize_with :admin
+ post :create, link: link
+ assert_response 422
+ end
+
+ test "tail must be visible by user" do
+ link = {
+ link_class: 'test',
+ name: 'stuff',
+ head_uuid: users(:active).uuid,
+ tail_uuid: virtual_machines(:testvm).uuid
+ }
+ authorize_with :active
+ post :create, link: link
+ assert_response 422
+ end
+
+ test "filter links with 'is_a' operator" do
+ authorize_with :admin
+ get :index, {
+ filters: [ ['tail_uuid', 'is_a', 'arvados#user'] ]
+ }
+ assert_response :success
+ found = assigns(:objects)
+ assert_not_equal 0, found.count
+ assert_equal found.count, (found.select { |f| f.tail_uuid.match /[a-z0-9]{5}-tpzed-[a-z0-9]{15}/}).count
+ end
+
+ test "filter links with 'is_a' operator with more than one" do
+ authorize_with :admin
+ get :index, {
+ filters: [ ['tail_uuid', 'is_a', ['arvados#user', 'arvados#group'] ] ],
+ }
+ assert_response :success
+ found = assigns(:objects)
+ assert_not_equal 0, found.count
+ assert_equal found.count, (found.select { |f| f.tail_uuid.match /[a-z0-9]{5}-(tpzed|j7d0g)-[a-z0-9]{15}/}).count
+ end
+
+ test "filter links with 'is_a' operator with bogus type" do
+ authorize_with :admin
+ get :index, {
+ filters: [ ['tail_uuid', 'is_a', ['arvados#bogus'] ] ],
+ }
+ assert_response :success
+ found = assigns(:objects)
+ assert_equal 0, found.count
+ end
+
+ test "filter links with 'is_a' operator with collection" do
+ authorize_with :admin
+ get :index, {
+ filters: [ ['head_uuid', 'is_a', ['arvados#collection'] ] ],
+ }
+ assert_response :success
+ found = assigns(:objects)
+ assert_response :success
+ found = assigns(:objects)
+ assert_not_equal 0, found.count
+ assert_equal found.count, (found.select { |f| f.head_uuid.match /[a-f0-9]{32}\+\d+/}).count
+ end
+
+
end
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#user',
tail_uuid: users(:spectator).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#collection',
head_uuid: collections(:foo_file).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#user',
tail_uuid: users(:spectator).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#collection',
head_uuid: collections(:foo_file).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#user',
tail_uuid: users(:spectator).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#group',
head_uuid: groups(:private).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#group',
tail_uuid: groups(:private).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#collection',
head_uuid: collections(:foo_file).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#group',
tail_uuid: groups(:private).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#collection',
head_uuid: collections(:foo_file).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#user',
tail_uuid: users(:spectator).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#group',
head_uuid: groups(:private).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#user',
tail_uuid: users(:spectator).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#group',
head_uuid: groups(:private).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#group',
tail_uuid: groups(:private).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#group',
head_uuid: groups(:empty_lonely_group).uuid,
properties: {}
}
post "/arvados/v1/links", {
:format => :json,
:link => {
- tail_kind: 'arvados#group',
tail_uuid: groups(:empty_lonely_group).uuid,
link_class: 'permission',
name: 'can_read',
- head_kind: 'arvados#collection',
head_uuid: collections(:foo_file).uuid,
properties: {}
}
--- /dev/null
+require 'test_helper'
+
+class ValidLinksTest < ActionDispatch::IntegrationTest
+ fixtures :all
+
+ test "tail must exist on update" do
+ admin_auth = {'HTTP_AUTHORIZATION' => "OAuth2 #{api_client_authorizations(:admin).api_token}"}
+
+ post "/arvados/v1/links", {
+ :format => :json,
+ :link => {
+ link_class: 'test',
+ name: 'stuff',
+ head_uuid: users(:active).uuid,
+ tail_uuid: virtual_machines(:testvm).uuid
+ }
+ }, admin_auth
+ assert_response :success
+ u = jresponse['uuid']
+
+ put "/arvados/v1/links/#{u}", {
+ :format => :json,
+ :link => {
+ tail_uuid: virtual_machines(:testvm2).uuid
+ }
+ }, admin_auth
+ assert_response :success
+ #puts @response.body
+ #puts jresponse['tail_uuid']
+ #puts virtual_machines(:testvm2)
+ assert_equal virtual_machines(:testvm2).uuid, (ActiveSupport::JSON.decode @response.body)['tail_uuid']
+
+ put "/arvados/v1/links/#{u}", {
+ :format => :json,
+ :link => {
+ tail_uuid: 'zzzzz-tpzed-xyzxyzxerrrorxx'
+ }
+ }, admin_auth
+ assert_response 422
+ end
+
+end