4253: Use same repo name logic whether or not user already existed before setup.
[arvados.git] / services / api / app / models / repository.rb
1 class Repository < ArvadosModel
2   include HasUuid
3   include KindAndEtag
4   include CommonApiTemplate
5
6   # Order is important here.  We must validate the owner before we can
7   # validate the name.
8   validate :valid_owner
9   validate :name_format, :if => Proc.new { |r| r.errors[:owner_uuid].empty? }
10   validates(:name, uniqueness: true, allow_nil: false)
11
12   api_accessible :user, extend: :common do |t|
13     t.add :name
14     t.add :fetch_url
15     t.add :push_url
16   end
17
18   def self.attributes_required_columns
19     super.merge({"push_url" => ["name"], "fetch_url" => ["name"]})
20   end
21
22   def push_url
23     "git@git.%s.arvadosapi.com:%s.git" % [Rails.configuration.uuid_prefix, name]
24   end
25
26   def fetch_url
27     push_url
28   end
29
30   def server_path
31     # Find where the repository is stored on the API server's filesystem,
32     # and return that path, or nil if not found.
33     # This method is only for the API server's internal use, and should not
34     # be exposed through the public API.  Following our current gitolite
35     # setup, it searches for repositories stored by UUID, then name; and it
36     # prefers bare repositories over checkouts.
37     [["%s.git"], ["%s", ".git"]].each do |repo_base, *join_args|
38       [:uuid, :name].each do |path_attr|
39         git_dir = File.join(Rails.configuration.git_repositories_dir,
40                             repo_base % send(path_attr), *join_args)
41         return git_dir if File.exist?(git_dir)
42       end
43     end
44     nil
45   end
46
47   protected
48
49   def permission_to_update
50     return false if not current_user
51     return true if current_user.is_admin
52     # For normal objects, this is a way to check whether you have
53     # write permission. Repositories should be brought closer to the
54     # normal permission model during #4253. Meanwhile, we'll
55     # special-case this so arv-git-httpd can detect write permission:
56     return super if changed_attributes.keys - ['modified_at', 'updated_at'] == []
57     false
58   end
59
60   def owner
61     User.find_by_uuid(owner_uuid)
62   end
63
64   def valid_owner
65     if owner.nil? or (owner.username.nil? and (owner.uuid != system_user_uuid))
66       errors.add(:owner_uuid, "must refer to a user with a username")
67       false
68     end
69   end
70
71   def name_format
72     if owner.uuid == system_user_uuid
73       prefix_match = ""
74       errmsg_start = "must be"
75     else
76       prefix_match = Regexp.escape(owner.username + "/")
77       errmsg_start = "must be the owner's username, then '/', then"
78     end
79     if not /^#{prefix_match}[A-Za-z][A-Za-z0-9]*$/.match(name)
80       errors.add(:name,
81                  "#{errmsg_start} a letter followed by alphanumerics")
82       false
83     end
84   end
85 end