summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG3
-rw-r--r--app/controllers/admin/application_settings_controller.rb1
-rw-r--r--app/models/application_setting.rb1
-rw-r--r--app/models/merge_request.rb4
-rw-r--r--app/models/user.rb2
-rw-r--r--app/views/admin/abuse_reports/_abuse_report.html.haml4
-rw-r--r--app/views/admin/application_settings/_form.html.haml7
-rw-r--r--app/views/users/show.html.haml5
-rw-r--r--db/migrate/20160608211215_add_user_default_external_to_application_settings.rb13
-rw-r--r--db/migrate/20160620110927_fix_no_validatable_import_url.rb32
-rw-r--r--db/schema.rb1
-rw-r--r--doc/api/groups.md247
-rw-r--r--doc/api/projects.md39
-rw-r--r--doc/ci/yaml/README.md2
-rw-r--r--doc/permissions/permissions.md3
-rw-r--r--lib/api/entities.rb12
-rw-r--r--lib/gitlab/current_settings.rb1
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb30
-rw-r--r--spec/models/user_spec.rb21
-rw-r--r--spec/requests/api/groups_spec.rb19
-rw-r--r--spec/requests/api/projects_spec.rb40
21 files changed, 428 insertions, 59 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 907e1765aa7..cc4af129bab 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -28,6 +28,7 @@ v 8.10.0 (unreleased)
- Wildcards for protected branches. !4665
- Allow importing from Github using Personal Access Tokens. (Eric K Idema)
- API: Todos !3188 (Robert Schilling)
+ - API: Expose shared groups for projects and shared projects for groups !5050 (Robert Schilling)
- Add "Enabled Git access protocols" to Application Settings
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- PipelinesFinder uses git cache data
@@ -45,6 +46,7 @@ v 8.10.0 (unreleased)
- RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info.
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
- Set import_url validation to be more strict
+ - Memoize MR merged/closed events retrieval
- Don't render discussion notes when requesting diff tab through AJAX
- Add basic system information like memory and disk usage to the admin panel
- Don't garbage collect commits that have related DB records like comments
@@ -54,6 +56,7 @@ v 8.10.0 (unreleased)
- Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests
- Add date when user joined the team on the member page
- Fix 404 redirect after validation fails importing a GitLab project
+ - Added setting to set new users by default as external !4545 (Dravere)
v 8.9.5
- Add more debug info to import/export and memory killer. !5108
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index cbdf2859898..23ba83aba0e 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -87,6 +87,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:version_check_enabled,
:admin_notification_email,
:user_oauth_applications,
+ :user_default_external,
:shared_runners_enabled,
:shared_runners_text,
:max_artifacts_size,
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 7bf618d60b9..c6f77cc055f 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -142,6 +142,7 @@ class ApplicationSetting < ActiveRecord::Base
send_user_confirmation_email: false,
container_registry_token_expire_delay: 5,
repository_storage: 'default',
+ user_default_external: false,
)
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 083e93f1ee7..393d8a72657 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -318,11 +318,11 @@ class MergeRequest < ActiveRecord::Base
end
def merge_event
- self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
+ @merge_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::MERGED).last
end
def closed_event
- self.target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
+ @closed_event ||= target_project.events.where(target_id: self.id, target_type: "MergeRequest", action: Event::CLOSED).last
end
WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze
diff --git a/app/models/user.rb b/app/models/user.rb
index 695a47ba6eb..79c670cb35a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -15,7 +15,7 @@ class User < ActiveRecord::Base
add_authentication_token_field :authentication_token
default_value_for :admin, false
- default_value_for :external, false
+ default_value_for(:external) { current_application_settings.user_default_external }
default_value_for :can_create_group, gitlab_config.default_can_create_group
default_value_for :can_create_team, false
default_value_for :hide_no_ssh_key, false
diff --git a/app/views/admin/abuse_reports/_abuse_report.html.haml b/app/views/admin/abuse_reports/_abuse_report.html.haml
index 862b86d9d4a..dd2e7ebd030 100644
--- a/app/views/admin/abuse_reports/_abuse_report.html.haml
+++ b/app/views/admin/abuse_reports/_abuse_report.html.haml
@@ -3,14 +3,14 @@
%tr
%td
- if user
- = link_to user.name, [:admin, user]
+ = link_to user.name, user
.light.small
Joined #{time_ago_with_tooltip(user.created_at)}
- else
(removed)
%td
- if reporter
- = link_to reporter.name, [:admin, reporter]
+ = link_to reporter.name, reporter
- else
(removed)
.light.small
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index eb325576e4f..8de28528cda 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -100,6 +100,13 @@
= f.label :user_oauth_applications do
= f.check_box :user_oauth_applications
Allow users to register any application to use GitLab as an OAuth provider
+ .form-group
+ = f.label :user_default_external, 'New users set to external', class: 'control-label col-sm-2'
+ .col-sm-10
+ .checkbox
+ = f.label :user_default_external do
+ = f.check_box :user_default_external
+ Newly registered users will by default be external
%fieldset
%legend Sign-in Restrictions
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 68665858c3e..db2b4885861 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -29,6 +29,11 @@
&nbsp;
= link_to user_path(@user, :atom, { private_token: current_user.private_token }), class: 'btn btn-gray' do
= icon('rss')
+ - if current_user.admin?
+ &nbsp;
+ = link_to [:admin, @user], class: 'btn btn-gray', title: 'View user in admin area',
+ data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('users')
.avatar-holder
= link_to avatar_icon(@user, 400), target: '_blank' do
diff --git a/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb b/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb
new file mode 100644
index 00000000000..34c702e3fa6
--- /dev/null
+++ b/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb
@@ -0,0 +1,13 @@
+class AddUserDefaultExternalToApplicationSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings, :user_default_external, :boolean,
+ default: false, allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :user_default_external)
+ end
+end
diff --git a/db/migrate/20160620110927_fix_no_validatable_import_url.rb b/db/migrate/20160620110927_fix_no_validatable_import_url.rb
index 82a616c62d9..a3f5073d511 100644
--- a/db/migrate/20160620110927_fix_no_validatable_import_url.rb
+++ b/db/migrate/20160620110927_fix_no_validatable_import_url.rb
@@ -11,7 +11,7 @@ class FixNoValidatableImportUrl < ActiveRecord::Migration
attr_reader :results, :query
- def initialize(batch_size: 100, query:)
+ def initialize(batch_size: 1000, query:)
@offset = 0
@batch_size = batch_size
@query = query
@@ -58,22 +58,38 @@ class FixNoValidatableImportUrl < ActiveRecord::Migration
return
end
+ say('Nullifying empty import URLs')
+
+ nullify_empty_urls
+
say('Cleaning up invalid import URLs... This may take a few minutes if we have a large number of imported projects.')
- invalid_import_url_project_ids.each { |project_id| cleanup_import_url(project_id) }
+ process_invalid_import_urls
end
- def invalid_import_url_project_ids
- ids = []
+ def process_invalid_import_urls
batches = SqlBatches.new(query: "SELECT id, import_url FROM projects WHERE import_url IS NOT NULL")
while batches.next?
+ project_ids = []
+
batches.results.each do |result|
- ids << result['id'] unless valid_url?(result['import_url'])
+ project_ids << result['id'] unless valid_url?(result['import_url'])
end
+
+ process_batch(project_ids)
end
- ids
+ end
+
+ def process_batch(project_ids)
+ Thread.new do
+ begin
+ project_ids.each { |project_id| cleanup_import_url(project_id) }
+ ensure
+ ActiveRecord::Base.connection.close
+ end
+ end.join
end
def valid_url?(url)
@@ -83,4 +99,8 @@ class FixNoValidatableImportUrl < ActiveRecord::Migration
def cleanup_import_url(project_id)
execute("UPDATE projects SET import_url = NULL WHERE id = #{project_id}")
end
+
+ def nullify_empty_urls
+ execute("UPDATE projects SET import_url = NULL WHERE import_url = ''")
+ end
end
diff --git a/db/schema.rb b/db/schema.rb
index 68b9425253c..a5eea3a697c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -84,6 +84,7 @@ ActiveRecord::Schema.define(version: 20160705163108) do
t.string "health_check_access_token"
t.boolean "send_user_confirmation_email", default: false
t.integer "container_registry_token_expire_delay", default: 5
+ t.boolean "user_default_external", default: false, null: false
t.text "after_sign_up_text"
t.string "repository_storage", default: "default"
t.string "enabled_git_access_protocol"
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 1ccb9715e96..87480bebfc4 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -42,46 +42,49 @@ Parameters:
```json
[
{
- "id": 4,
- "description": null,
+ "id": 9,
+ "description": "foo",
"default_branch": "master",
+ "tag_list": [],
"public": false,
- "visibility_level": 0,
- "ssh_url_to_repo": "git@example.com:diaspora/diaspora-client.git",
- "http_url_to_repo": "http://example.com/diaspora/diaspora-client.git",
- "web_url": "http://example.com/diaspora/diaspora-client",
- "tag_list": [
- "example",
- "disapora client"
- ],
- "owner": {
- "id": 3,
- "name": "Diaspora",
- "created_at": "2013-09-30T13: 46: 02Z"
- },
- "name": "Diaspora Client",
- "name_with_namespace": "Diaspora / Diaspora Client",
- "path": "diaspora-client",
- "path_with_namespace": "diaspora/diaspora-client",
+ "archived": false,
+ "visibility_level": 10,
+ "ssh_url_to_repo": "git@gitlab.example.com/html5-boilerplate.git",
+ "http_url_to_repo": "http://gitlab.example.com/h5bp/html5-boilerplate.git",
+ "web_url": "http://gitlab.example.com/h5bp/html5-boilerplate",
+ "name": "Html5 Boilerplate",
+ "name_with_namespace": "Experimental / Html5 Boilerplate",
+ "path": "html5-boilerplate",
+ "path_with_namespace": "h5bp/html5-boilerplate",
"issues_enabled": true,
"merge_requests_enabled": true,
- "builds_enabled": true,
"wiki_enabled": true,
- "snippets_enabled": false,
- "created_at": "2013-09-30T13: 46: 02Z",
- "last_activity_at": "2013-09-30T13: 46: 02Z",
- "creator_id": 3,
+ "builds_enabled": true,
+ "snippets_enabled": true,
+ "created_at": "2016-04-05T21:40:50.169Z",
+ "last_activity_at": "2016-04-06T16:52:08.432Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
"namespace": {
- "created_at": "2013-09-30T13: 46: 02Z",
- "description": "",
- "id": 3,
- "name": "Diaspora",
- "owner_id": 1,
- "path": "diaspora",
- "updated_at": "2013-09-30T13: 46: 02Z"
+ "id": 5,
+ "name": "Experimental",
+ "path": "h5bp",
+ "owner_id": null,
+ "created_at": "2016-04-05T21:40:49.152Z",
+ "updated_at": "2016-04-07T08:07:48.466Z",
+ "description": "foo",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 10
},
- "archived": false,
- "avatar_url": "http://example.com/uploads/project/avatar/4/uploads/avatar.png"
+ "avatar_url": null,
+ "star_count": 1,
+ "forks_count": 0,
+ "open_issues_count": 3,
+ "public_builds": true,
+ "shared_with_groups": []
}
]
```
@@ -96,7 +99,180 @@ GET /groups/:id
Parameters:
-- `id` (required) - The ID or path of a group
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or path of a group |
+
+```bash
+curl -H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/groups/4
+```
+
+Example response:
+
+```json
+{
+ "id": 4,
+ "name": "Twitter",
+ "path": "twitter",
+ "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
+ "visibility_level": 20,
+ "avatar_url": null,
+ "web_url": "https://gitlab.example.com/groups/twitter",
+ "projects": [
+ {
+ "id": 7,
+ "description": "Voluptas veniam qui et beatae voluptas doloremque explicabo facilis.",
+ "default_branch": "master",
+ "tag_list": [],
+ "public": true,
+ "archived": false,
+ "visibility_level": 20,
+ "ssh_url_to_repo": "git@gitlab.example.com:twitter/typeahead-js.git",
+ "http_url_to_repo": "https://gitlab.example.com/twitter/typeahead-js.git",
+ "web_url": "https://gitlab.example.com/twitter/typeahead-js",
+ "name": "Typeahead.Js",
+ "name_with_namespace": "Twitter / Typeahead.Js",
+ "path": "typeahead-js",
+ "path_with_namespace": "twitter/typeahead-js",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "builds_enabled": true,
+ "snippets_enabled": false,
+ "container_registry_enabled": true,
+ "created_at": "2016-06-17T07:47:25.578Z",
+ "last_activity_at": "2016-06-17T07:47:25.881Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
+ "namespace": {
+ "id": 4,
+ "name": "Twitter",
+ "path": "twitter",
+ "owner_id": null,
+ "created_at": "2016-06-17T07:47:24.216Z",
+ "updated_at": "2016-06-17T07:47:24.216Z",
+ "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 20
+ },
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 3,
+ "public_builds": true,
+ "shared_with_groups": []
+ },
+ {
+ "id": 6,
+ "description": "Aspernatur omnis repudiandae qui voluptatibus eaque.",
+ "default_branch": "master",
+ "tag_list": [],
+ "public": false,
+ "archived": false,
+ "visibility_level": 10,
+ "ssh_url_to_repo": "git@gitlab.example.com:twitter/flight.git",
+ "http_url_to_repo": "https://gitlab.example.com/twitter/flight.git",
+ "web_url": "https://gitlab.example.com/twitter/flight",
+ "name": "Flight",
+ "name_with_namespace": "Twitter / Flight",
+ "path": "flight",
+ "path_with_namespace": "twitter/flight",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "builds_enabled": true,
+ "snippets_enabled": false,
+ "container_registry_enabled": true,
+ "created_at": "2016-06-17T07:47:24.661Z",
+ "last_activity_at": "2016-06-17T07:47:24.838Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
+ "namespace": {
+ "id": 4,
+ "name": "Twitter",
+ "path": "twitter",
+ "owner_id": null,
+ "created_at": "2016-06-17T07:47:24.216Z",
+ "updated_at": "2016-06-17T07:47:24.216Z",
+ "description": "Aliquid qui quis dignissimos distinctio ut commodi voluptas est.",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 20
+ },
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 8,
+ "public_builds": true,
+ "shared_with_groups": []
+ }
+ ],
+ "shared_projects": [
+ {
+ "id": 8,
+ "description": "Velit eveniet provident fugiat saepe eligendi autem.",
+ "default_branch": "master",
+ "tag_list": [],
+ "public": false,
+ "archived": false,
+ "visibility_level": 0,
+ "ssh_url_to_repo": "git@gitlab.example.com:h5bp/html5-boilerplate.git",
+ "http_url_to_repo": "https://gitlab.example.com/h5bp/html5-boilerplate.git",
+ "web_url": "https://gitlab.example.com/h5bp/html5-boilerplate",
+ "name": "Html5 Boilerplate",
+ "name_with_namespace": "H5bp / Html5 Boilerplate",
+ "path": "html5-boilerplate",
+ "path_with_namespace": "h5bp/html5-boilerplate",
+ "issues_enabled": true,
+ "merge_requests_enabled": true,
+ "wiki_enabled": true,
+ "builds_enabled": true,
+ "snippets_enabled": false,
+ "container_registry_enabled": true,
+ "created_at": "2016-06-17T07:47:27.089Z",
+ "last_activity_at": "2016-06-17T07:47:27.310Z",
+ "shared_runners_enabled": true,
+ "creator_id": 1,
+ "namespace": {
+ "id": 5,
+ "name": "H5bp",
+ "path": "h5bp",
+ "owner_id": null,
+ "created_at": "2016-06-17T07:47:26.621Z",
+ "updated_at": "2016-06-17T07:47:26.621Z",
+ "description": "Id consequatur rem vel qui doloremque saepe.",
+ "avatar": {
+ "url": null
+ },
+ "share_with_group_lock": false,
+ "visibility_level": 20
+ },
+ "avatar_url": null,
+ "star_count": 0,
+ "forks_count": 0,
+ "open_issues_count": 4,
+ "public_builds": true,
+ "shared_with_groups": [
+ {
+ "group_id": 4,
+ "group_name": "Twitter",
+ "group_access_level": 30
+ },
+ {
+ "group_id": 3,
+ "group_name": "Gitlab Org",
+ "group_access_level": 10
+ }
+ ]
+ }
+ ]
+}
+```
## New group
@@ -201,7 +377,8 @@ Example response:
"star_count": 1,
"forks_count": 0,
"open_issues_count": 3,
- "public_builds": true
+ "public_builds": true,
+ "shared_with_groups": []
}
]
}
diff --git a/doc/api/projects.md b/doc/api/projects.md
index f5f195b97df..90f8c7f79bb 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -82,7 +82,8 @@ Parameters:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true
+ "public_builds": true,
+ "shared_with_groups": []
},
{
"id": 6,
@@ -140,7 +141,8 @@ Parameters:
"forks_count": 0,
"star_count": 0,
"runners_token": "b8547b1dc37721d05889db52fa2f02",
- "public_builds": true
+ "public_builds": true,
+ "shared_with_groups": []
}
]
```
@@ -262,7 +264,20 @@ Parameters:
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+ "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "public_builds": true,
+ "shared_with_groups": [
+ {
+ "group_id": 4,
+ "group_name": "Twitter",
+ "group_access_level": 30
+ },
+ {
+ "group_id": 3,
+ "group_name": "Gitlab Org",
+ "group_access_level": 10
+ }
+ ]
}
```
@@ -553,7 +568,9 @@ Example response:
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
- "star_count": 1
+ "star_count": 1,
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -616,7 +633,9 @@ Example response:
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
"shared_runners_enabled": true,
"forks_count": 0,
- "star_count": 0
+ "star_count": 0,
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -699,7 +718,9 @@ Example response:
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+ "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "public_builds": true,
+ "shared_with_groups": []
}
```
@@ -713,7 +734,7 @@ have the proper access rights, code 403 is returned. Status 404 is returned if t
doesn't exist, or is hidden to the user.
```
-POST /projects/:id/archive
+POST /projects/:id/unarchive
```
| Attribute | Type | Required | Description |
@@ -782,7 +803,9 @@ Example response:
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
- "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b"
+ "runners_token": "b8bc4a7a29eb76ea83cf79e4908c2b",
+ "public_builds": true,
+ "shared_with_groups": []
}
```
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index d2d1b04f893..eb81267242e 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -811,7 +811,7 @@ deploy:
It's possible to overwrite globally defined `before_script` and `after_script`:
```yaml
-before_script
+before_script:
- global before script
job:
diff --git a/doc/permissions/permissions.md b/doc/permissions/permissions.md
index 963b35de3a0..44f3f6d3b12 100644
--- a/doc/permissions/permissions.md
+++ b/doc/permissions/permissions.md
@@ -99,3 +99,6 @@ An administrator can flag a user as external [through the API](../api/users.md)
or by checking the checkbox on the admin panel. As an administrator, navigate
to **Admin > Users** to create a new user or edit an existing one. There, you
will find the option to flag the user as external.
+
+By default new users are not set as external users. This behavior can be changed
+by an administrator under **Admin > Application Settings**. \ No newline at end of file
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index db877d2eeb0..9076a0c3831 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -58,6 +58,14 @@ module API
expose :path, :path_with_namespace
end
+ class SharedGroup < Grape::Entity
+ expose :group_id
+ expose :group_name do |group_link, options|
+ group_link.group.name
+ end
+ expose :group_access, as: :group_access_level
+ end
+
class Project < Grape::Entity
expose :id, :description, :default_branch, :tag_list
expose :public?, as: :public
@@ -77,6 +85,9 @@ module API
expose :open_issues_count, if: lambda { |project, options| project.issues_enabled? && project.default_issues_tracker? }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :public_builds
+ expose :shared_with_groups do |project, options|
+ SharedGroup.represent(project.project_group_links.all, options)
+ end
end
class ProjectMember < UserBasic
@@ -93,6 +104,7 @@ module API
class GroupDetail < Group
expose :projects, using: Entities::Project
+ expose :shared_projects, using: Entities::Project
end
class GroupMember < UserBasic
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index 54b46e5d23f..ffc1814b29d 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -48,6 +48,7 @@ module Gitlab
akismet_enabled: false,
repository_checks_enabled: true,
container_registry_token_expire_delay: 5,
+ user_default_external: false,
)
end
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
new file mode 100644
index 00000000000..16baf7e9516
--- /dev/null
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe "Admin::AbuseReports", feature: true, js: true do
+ let(:user) { create(:user) }
+
+ context 'as an admin' do
+ describe 'if a user has been reported for abuse' do
+ before do
+ create(:abuse_report, user: user)
+ login_as :admin
+ end
+
+ describe 'in the abuse report view' do
+ it "should present a link to the user's profile" do
+ visit admin_abuse_reports_path
+
+ expect(page).to have_link user.name, href: user_path(user)
+ end
+ end
+
+ describe 'in the profile page of the user' do
+ it 'should show a link to the admin view of the user' do
+ visit user_path(user)
+
+ expect(page).to have_link '', href: admin_user_path(user)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 328254ed56b..3984b30ddf8 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -446,6 +446,7 @@ describe User, models: true do
it { expect(user.can_create_group?).to be_truthy }
it { expect(user.can_create_project?).to be_truthy }
it { expect(user.first_name).to eq('John') }
+ it { expect(user.external).to be_falsey }
end
describe 'with defaults' do
@@ -468,6 +469,26 @@ describe User, models: true do
expect(user.theme_id).to eq(1)
end
end
+
+ context 'when current_application_settings.user_default_external is true' do
+ before do
+ stub_application_setting(user_default_external: true)
+ end
+
+ it "creates external user by default" do
+ user = build(:user)
+
+ expect(user.external).to be_truthy
+ end
+
+ describe 'with default overrides' do
+ it "creates a non-external user" do
+ user = build(:user, external: false)
+
+ expect(user.external).to be_falsey
+ end
+ end
+ end
end
describe '.find_by_any_email' do
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 04141a45031..c2c94040ece 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -49,10 +49,25 @@ describe API::API, api: true do
describe "GET /groups/:id" do
context "when authenticated as user" do
- it "should return one of user1's groups" do
+ it "returns one of user1's groups" do
+ project = create(:project, namespace: group2, path: 'Foo')
+ create(:project_group_link, project: project, group: group1)
+
get api("/groups/#{group1.id}", user1)
+
expect(response).to have_http_status(200)
- json_response['name'] == group1.name
+ expect(json_response['id']).to eq(group1.id)
+ expect(json_response['name']).to eq(group1.name)
+ expect(json_response['path']).to eq(group1.path)
+ expect(json_response['description']).to eq(group1.description)
+ expect(json_response['visibility_level']).to eq(group1.visibility_level)
+ expect(json_response['avatar_url']).to eq(group1.avatar_url)
+ expect(json_response['web_url']).to eq(group1.web_url)
+ expect(json_response['projects']).to be_an Array
+ expect(json_response['projects'].length).to eq(2)
+ expect(json_response['shared_projects']).to be_an Array
+ expect(json_response['shared_projects'].length).to eq(1)
+ expect(json_response['shared_projects'][0]['id']).to eq(project.id)
end
it "should not return a non existing group" do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 611dd2a2a88..8a52725a893 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -392,11 +392,47 @@ describe API::API, api: true do
before { project }
before { project_member }
- it 'should return a project by id' do
+ it 'returns a project by id' do
+ group = create(:group)
+ link = create(:project_group_link, project: project, group: group)
+
get api("/projects/#{project.id}", user)
+
expect(response).to have_http_status(200)
+ expect(json_response['id']).to eq(project.id)
+ expect(json_response['description']).to eq(project.description)
+ expect(json_response['default_branch']).to eq(project.default_branch)
+ expect(json_response['tag_list']).to be_an Array
+ expect(json_response['public']).to be_falsey
+ expect(json_response['archived']).to be_falsey
+ expect(json_response['visibility_level']).to be_present
+ expect(json_response['ssh_url_to_repo']).to be_present
+ expect(json_response['http_url_to_repo']).to be_present
+ expect(json_response['web_url']).to be_present
+ expect(json_response['owner']).to be_a Hash
+ expect(json_response['owner']).to be_a Hash
expect(json_response['name']).to eq(project.name)
- expect(json_response['owner']['username']).to eq(user.username)
+ expect(json_response['path']).to be_present
+ expect(json_response['issues_enabled']).to be_present
+ expect(json_response['merge_requests_enabled']).to be_present
+ expect(json_response['wiki_enabled']).to be_present
+ expect(json_response['builds_enabled']).to be_present
+ expect(json_response['snippets_enabled']).to be_present
+ expect(json_response['container_registry_enabled']).to be_present
+ expect(json_response['created_at']).to be_present
+ expect(json_response['last_activity_at']).to be_present
+ expect(json_response['shared_runners_enabled']).to be_present
+ expect(json_response['creator_id']).to be_present
+ expect(json_response['namespace']).to be_present
+ expect(json_response['avatar_url']).to be_nil
+ expect(json_response['star_count']).to be_present
+ expect(json_response['forks_count']).to be_present
+ expect(json_response['public_builds']).to be_present
+ expect(json_response['shared_with_groups']).to be_an Array
+ expect(json_response['shared_with_groups'].length).to eq(1)
+ expect(json_response['shared_with_groups'][0]['group_id']).to eq(group.id)
+ expect(json_response['shared_with_groups'][0]['group_name']).to eq(group.name)
+ expect(json_response['shared_with_groups'][0]['group_access_level']).to eq(link.group_access)
end
it 'should return a project by path name' do