Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
07925be2
Commit
07925be2
authored
Nov 24, 2014
by
Marin Jankovski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of dev.gitlab.org:gitlab/gitlab-ee
parents
4ff5c7c3
ac614ea1
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
346 additions
and
8 deletions
+346
-8
app/controllers/audit_events_controller.rb
app/controllers/audit_events_controller.rb
+39
-0
app/controllers/groups/group_members_controller.rb
app/controllers/groups/group_members_controller.rb
+41
-3
app/controllers/projects/team_members_controller.rb
app/controllers/projects/team_members_controller.rb
+38
-4
app/helpers/audit_events_helper.rb
app/helpers/audit_events_helper.rb
+14
-0
app/models/audit_event.rb
app/models/audit_event.rb
+19
-0
app/models/security_event.rb
app/models/security_event.rb
+2
-0
app/services/audit_event_service.rb
app/services/audit_event_service.rb
+15
-0
app/views/audit_events/_event_table.html.haml
app/views/audit_events/_event_table.html.haml
+29
-0
app/views/audit_events/group_log.html.haml
app/views/audit_events/group_log.html.haml
+9
-0
app/views/audit_events/project_log.html.haml
app/views/audit_events/project_log.html.haml
+4
-0
app/views/groups/_settings_nav.html.haml
app/views/groups/_settings_nav.html.haml
+4
-0
app/views/projects/_settings_nav.html.haml
app/views/projects/_settings_nav.html.haml
+4
-0
config/routes.rb
config/routes.rb
+4
-0
db/migrate/20141118150935_add_audit_event.rb
db/migrate/20141118150935_add_audit_event.rb
+22
-0
db/schema.rb
db/schema.rb
+15
-1
features/groups.feature
features/groups.feature
+11
-0
features/project/project.feature
features/project/project.feature
+11
-0
features/steps/groups.rb
features/steps/groups.rb
+27
-0
features/steps/project/project.rb
features/steps/project/project.rb
+38
-0
No files found.
app/controllers/audit_events_controller.rb
0 → 100644
View file @
07925be2
class
AuditEventsController
<
ApplicationController
# Authorize
before_filter
:repository
,
only: :project_log
before_filter
:authorize_admin_project!
,
only: :project_log
before_filter
:group
,
only: :group_log
before_filter
:authorize_admin_group!
,
only: :group_log
layout
:determine_layout
def
project_log
@events
=
AuditEvent
.
where
(
entity_type:
"Project"
,
entity_id:
project
.
id
).
page
(
params
[
:page
]).
per
(
20
)
end
def
group_log
@events
=
AuditEvent
.
where
(
entity_type:
"Group"
,
entity_id:
group
.
id
).
page
(
params
[
:page
]).
per
(
20
)
end
private
def
group
@group
||=
Group
.
find_by
(
path:
params
[
:group_id
])
end
def
authorize_admin_group!
render_404
unless
can?
(
current_user
,
:manage_group
,
group
)
end
def
determine_layout
if
@project
'project_settings'
elsif
@group
'group'
end
end
def
audit_events_params
params
.
permit
(
:project_id
,
:group_id
)
end
end
app/controllers/groups/group_members_controller.rb
View file @
07925be2
...
...
@@ -7,21 +7,59 @@ class Groups::GroupMembersController < ApplicationController
layout
'group'
def
create
@group
.
add_users
(
params
[
:user_ids
].
split
(
','
),
params
[
:access_level
])
access_level
=
params
[
:access_level
]
user_ids
=
params
[
:user_ids
].
split
(
','
)
@group
.
add_users
(
user_ids
,
access_level
)
users
=
User
.
where
(
id:
user_ids
).
pluck
(
:id
,
:name
)
users
.
each
do
|
user
|
details
=
{
add:
"user_access"
,
as:
Gitlab
::
Access
.
options_with_owner
.
key
(
access_level
.
to_i
),
target_id:
user
[
0
],
target_type:
"User"
,
target_details:
user
[
1
],
}
AuditEventService
.
new
(
current_user
,
@group
,
details
).
security_event
end
redirect_to
members_group_path
(
@group
),
notice:
'Users were successfully added.'
end
def
update
@member
=
@group
.
group_members
.
find
(
params
[
:id
])
@member
.
update_attributes
(
member_params
)
old_access_level
=
@member
.
human_access
if
@member
.
update_attributes
(
member_params
)
details
=
{
change:
"access_level"
,
from:
old_access_level
,
to:
@member
.
human_access
,
target_id:
@member
.
user_id
,
target_type:
"User"
,
target_details:
@member
.
user
.
name
,
}
AuditEventService
.
new
(
current_user
,
@group
,
details
).
security_event
end
end
def
destroy
@users_group
=
@group
.
group_members
.
find
(
params
[
:id
])
if
can?
(
current_user
,
:destroy
,
@users_group
)
# May fail if last owner.
@users_group
.
destroy
user_id
=
@users_group
.
id
user_name
=
@users_group
.
user
.
name
if
@users_group
.
destroy
details
=
{
remove:
"user_access"
,
target_id:
user_id
,
target_type:
"User"
,
target_details:
user_name
,
}
AuditEventService
.
new
(
current_user
,
@group
,
details
).
security_event
end
respond_to
do
|
format
|
format
.
html
{
redirect_to
members_group_path
(
@group
),
notice:
'User was successfully removed from group.'
}
format
.
js
{
render
nothing:
true
}
...
...
app/controllers/projects/team_members_controller.rb
View file @
07925be2
...
...
@@ -16,8 +16,19 @@ class Projects::TeamMembersController < Projects::ApplicationController
def
create
users
=
User
.
where
(
id:
params
[
:user_ids
].
split
(
','
))
@project
.
team
<<
[
users
,
params
[
:access_level
]]
access_level
=
params
[
:access_level
]
@project
.
team
<<
[
users
,
access_level
]
users
.
each
do
|
user
|
details
=
{
add:
"user_access"
,
as:
Gitlab
::
Access
.
options_with_owner
.
key
(
access_level
.
to_i
),
target_id:
user
.
id
,
target_type:
"User"
,
target_details:
user
.
name
,
}
AuditEventService
.
new
(
current_user
,
@project
,
details
).
security_event
end
if
params
[
:redirect_to
]
redirect_to
params
[
:redirect_to
]
...
...
@@ -28,7 +39,19 @@ class Projects::TeamMembersController < Projects::ApplicationController
def
update
@user_project_relation
=
@project
.
project_members
.
find_by
(
user_id:
member
)
@user_project_relation
.
update_attributes
(
member_params
)
old_access_level
=
@user_project_relation
.
human_access
if
@user_project_relation
.
update_attributes
(
member_params
)
details
=
{
change:
"access_level"
,
from:
old_access_level
,
to:
@user_project_relation
.
human_access
,
target_id:
@user_project_relation
.
user_id
,
target_type:
"User"
,
target_details:
@user_project_relation
.
user
.
name
,
}
AuditEventService
.
new
(
current_user
,
@project
,
details
).
security_event
end
unless
@user_project_relation
.
valid?
flash
[
:alert
]
=
"User should have at least one role"
...
...
@@ -38,7 +61,18 @@ class Projects::TeamMembersController < Projects::ApplicationController
def
destroy
@user_project_relation
=
@project
.
project_members
.
find_by
(
user_id:
member
)
@user_project_relation
.
destroy
user_id
=
@user_project_relation
.
user_id
user_name
=
@user_project_relation
.
user
.
name
if
@user_project_relation
.
destroy
details
=
{
remove:
"user_access"
,
target_id:
user_id
,
target_type:
"User"
,
target_details:
user_name
,
}
AuditEventService
.
new
(
current_user
,
@project
,
details
).
security_event
end
respond_to
do
|
format
|
format
.
html
{
redirect_to
project_team_index_path
(
@project
)
}
...
...
app/helpers/audit_events_helper.rb
0 → 100644
View file @
07925be2
module
AuditEventsHelper
def
human_text
(
details
)
details
.
map
{
|
key
,
value
|
select_keys
(
key
,
value
)
}.
join
(
" "
).
humanize
end
def
select_keys
(
key
,
value
)
if
key
.
match
(
/^target_.*/
)
""
else
"
#{
key
.
to_s
}
<strong>
#{
value
}
</strong>"
end
end
end
app/models/audit_event.rb
0 → 100644
View file @
07925be2
class
AuditEvent
<
ActiveRecord
::
Base
serialize
:details
,
Hash
belongs_to
:user
,
foreign_key: :author_id
validates
:author_id
,
presence:
true
validates
:entity_id
,
presence:
true
validates
:entity_type
,
presence:
true
after_initialize
:initialize_details
def
initialize_details
self
.
details
=
{}
if
details
.
nil?
end
def
author_name
self
.
user
.
name
end
end
app/models/security_event.rb
0 → 100644
View file @
07925be2
class
SecurityEvent
<
AuditEvent
end
app/services/audit_event_service.rb
0 → 100644
View file @
07925be2
class
AuditEventService
def
initialize
(
author
,
entity
,
details
=
{})
@author
,
@entity
,
@details
=
author
,
entity
,
details
end
def
security_event
SecurityEvent
.
create
(
author_id:
@author
.
id
,
entity_id:
@entity
.
id
,
entity_type:
@entity
.
class
.
name
,
details:
@details
)
end
end
app/views/audit_events/_event_table.html.haml
0 → 100644
View file @
07925be2
-
if
defined?
(
events
)
%table
.table
#audits
%thead
%tr
%th
%th
%th
Author
%th
%th
%th
Action
%th
%th
Target
%th
%th
At
%tbody
-
events
.
each
do
|
event
|
%tr
%td
%td
%td
#{
event
.
author_name
}
%td
%td
%td
#{
raw
human_text
(
event
.
details
)
}
%td
%td
#{
event
.
details
[
:target_details
]
}
%td
%td
#{
event
.
created_at
}
=
paginate
events
app/views/audit_events/group_log.html.haml
0 → 100644
View file @
07925be2
.row
.col-md-2
=
render
'groups/settings_nav'
.col-md-10
%h3
.page-title
Group Audit Events
%p
.light
Events in
#{
@group
.
name
}
=
render
'event_table'
,
events:
@events
app/views/audit_events/project_log.html.haml
0 → 100644
View file @
07925be2
%h3
.page-title
Project Audit Events
%p
.light
Events in
#{
@project
.
path_with_namespace
}
=
render
'event_table'
,
events:
@events
app/views/groups/_settings_nav.html.haml
View file @
07925be2
...
...
@@ -11,4 +11,8 @@
=
link_to
group_ldap_group_links_path
(
@group
)
do
%i
.icon-exchange
LDAP Groups
=
nav_link
(
controller: :audit_events
)
do
=
link_to
group_audit_events_path
(
@group
)
do
%i
.fa.fa-file-text-o
Audit Events
app/views/projects/_settings_nav.html.haml
View file @
07925be2
...
...
@@ -31,3 +31,7 @@
=
link_to
project_protected_branches_path
(
@project
)
do
%i
.fa.fa-lock
Protected branches
=
nav_link
(
controller: :audit_events
)
do
=
link_to
project_audit_events_path
(
@project
)
do
%i
.fa.fa-file-text-o
Audit Events
config/routes.rb
View file @
07925be2
...
...
@@ -184,6 +184,8 @@ Gitlab::Application.routes.draw do
resource
:avatar
,
only:
[
:destroy
]
resources
:milestones
end
get
"/audit_events"
=>
"audit_events#group_log"
end
get
'unsubscribes/:email'
,
to:
'unsubscribes#show'
,
as: :unsubscribe
...
...
@@ -358,6 +360,8 @@ Gitlab::Application.routes.draw do
end
end
end
get
"/audit_events"
=>
"audit_events#project_log"
end
get
':id'
=>
"namespaces#show"
,
constraints:
{
id:
/(?:[^.]|\.(?!atom$))+/
,
format:
/atom/
}
...
...
db/migrate/20141118150935_add_audit_event.rb
0 → 100644
View file @
07925be2
class
AddAuditEvent
<
ActiveRecord
::
Migration
def
change
create_table
:audit_events
do
|
t
|
t
.
integer
:author_id
,
null:
false
t
.
string
:type
,
null:
false
# "Namespace" where the change occurs
# eg. On a project, group or user
t
.
integer
:entity_id
,
null:
false
t
.
string
:entity_type
,
null:
false
# Details for the event
t
.
text
:details
t
.
timestamps
end
add_index
:audit_events
,
:author_id
add_index
:audit_events
,
:type
add_index
:audit_events
,
[
:entity_id
,
:entity_type
]
end
end
db/schema.rb
View file @
07925be2
...
...
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord
::
Schema
.
define
(
version:
201411
03160516
)
do
ActiveRecord
::
Schema
.
define
(
version:
201411
18150935
)
do
# These are extensions that must be enabled in order to support this database
enable_extension
"plpgsql"
...
...
@@ -25,6 +25,20 @@ ActiveRecord::Schema.define(version: 20141103160516) do
t
.
datetime
"updated_at"
end
create_table
"audit_events"
,
force:
true
do
|
t
|
t
.
integer
"author_id"
,
null:
false
t
.
string
"type"
,
null:
false
t
.
integer
"entity_id"
,
null:
false
t
.
string
"entity_type"
,
null:
false
t
.
text
"details"
t
.
datetime
"created_at"
t
.
datetime
"updated_at"
end
add_index
"audit_events"
,
[
"author_id"
],
name:
"index_audit_events_on_author_id"
,
using: :btree
add_index
"audit_events"
,
[
"entity_id"
,
"entity_type"
],
name:
"index_audit_events_on_entity_id_and_entity_type"
,
using: :btree
add_index
"audit_events"
,
[
"type"
],
name:
"index_audit_events_on_type"
,
using: :btree
create_table
"broadcast_messages"
,
force:
true
do
|
t
|
t
.
text
"message"
,
null:
false
t
.
datetime
"starts_at"
...
...
features/groups.feature
View file @
07925be2
...
...
@@ -146,3 +146,14 @@ Feature: Groups
And
I click on one group milestone
Then
I should see group milestone with descriptions and expiry date
And
I should see group milestone with all issues and MRs assigned to that milestone
@javascript
Scenario
:
I
should see audit events
Given
User
"Mary Jane"
exists
When
I visit group
"Owned"
members page
And
I select user
"Mary Jane"
from list with role
"Reporter"
And
I change the role to
"Developer"
And
I click on the
"Remove User From Group"
button for
"Mary Jane"
When
I visit group
"Owned"
settings page
And
I go to
"Audit Events"
Then
I should see the audit event listed
features/project/project.feature
View file @
07925be2
...
...
@@ -49,3 +49,14 @@ Feature: Project
Then
I should see project
"Forum"
README
And
I visit project
"Shop"
page
Then
I should see project
"Shop"
README
@javascript
Scenario
:
I
should see audit events
And
gitlab user
"Pete"
And
"Pete"
is
"Shop"
developer
When
I visit project
"Shop"
settings page
And
I go to
"Members"
And
I change
"Pete"
access level to master
When
I visit project
"Shop"
settings page
And
I go to
"Audit Events"
Then
I should see the audit event listed
features/steps/groups.rb
View file @
07925be2
...
...
@@ -57,6 +57,33 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
projects_with_access
.
should_not
have_content
(
"Mary Jane"
)
end
step
'I change the role to "Developer"'
do
user
=
User
.
find_by
(
name:
"Mary Jane"
)
member
=
Group
.
find_by
(
name:
"Owned"
).
members
.
where
(
user_id:
user
.
id
).
first
within
"#group_member_
#{
member
.
id
}
"
do
find
(
".btn-tiny.btn.js-toggle-button"
).
click
within
"#edit_group_member_
#{
member
.
id
}
"
do
select
'Developer'
,
from:
'group_member_access_level'
click_on
'Save'
end
end
end
step
'I go to "Audit Events"'
do
click_link
'Audit Events'
end
step
'I should see the audit event listed'
do
within
(
'table#audits'
)
do
page
.
should
have_content
'Add user access as reporter'
page
.
should
have_content
'Change access level from reporter to developer'
page
.
should
have_content
'Remove user access'
page
.
should
have_content
(
'John Doe'
,
count:
3
)
page
.
should
have_content
(
'Mary Jane'
,
count:
3
)
end
end
step
'project from group "Owned" has issues assigned to me'
do
create
:issue
,
project:
project
,
...
...
features/steps/project/project.rb
View file @
07925be2
...
...
@@ -2,6 +2,7 @@ class Spinach::Features::Project < Spinach::FeatureSteps
include
SharedAuthentication
include
SharedProject
include
SharedPaths
include
Select2Helper
step
'change project settings'
do
fill_in
'project_name_edit'
,
with:
'NewName'
...
...
@@ -69,4 +70,41 @@ class Spinach::Features::Project < Spinach::FeatureSteps
page
.
should
have_link
"README.md"
page
.
should
have_content
"testme"
end
step
'gitlab user "Pete"'
do
create
(
:user
,
name:
"Pete"
)
end
step
'"Pete" is "Shop" developer'
do
user
=
User
.
find_by
(
name:
"Pete"
)
project
=
Project
.
find_by
(
name:
"Shop"
)
project
.
team
<<
[
user
,
:developer
]
end
step
'I visit project "Shop" settings page'
do
click_link
'Settings'
end
step
'I go to "Members"'
do
click_link
'Members'
end
step
'I change "Pete" access level to master'
do
user
=
User
.
find_by
(
name:
"Pete"
)
within
"#user_
#{
user
.
id
}
"
do
select
"Master"
,
from:
"project_member_access_level"
end
end
step
'I go to "Audit Events"'
do
click_link
'Audit Events'
end
step
'I should see the audit event listed'
do
within
(
'table#audits'
)
do
page
.
should
have_content
"Change access level from developer to master"
page
.
should
have_content
(
project
.
owner
.
name
)
page
.
should
have_content
(
'Pete'
)
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment