Conflicts: app/assets/javascripts/angular/work_packages/controllers/work-package-details-controller.js karma/tests/controllers/work-package-details-controller-test.js lib/api/v3/work_packages/work_package_representer.rbpull/1611/head
parent
c083456661
commit
2c4483544c
@ -0,0 +1,50 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
angular.module('openproject.workPackages.directives') |
||||
|
||||
.directive('attachmentTitleCell', ['PathHelper', function(PathHelper){ |
||||
return { |
||||
restrict: 'A', |
||||
replace: false, |
||||
templateUrl: '/templates/work_packages/tabs/_attachment_title_cell.html', |
||||
scope: { |
||||
attachment: '=' |
||||
}, |
||||
link: function(scope, element, attributes) { |
||||
scope.attachmentPath = PathHelper.staticAttachmentPath(scope.attachment.props.id, scope.attachment.props.fileName); |
||||
scope.displayTitle = scope.attachment.props.fileName + " (" + formattedFilesize(scope.attachment.props.fileSize) + ")"; |
||||
|
||||
function formattedFilesize(fileSize) { |
||||
var size = parseFloat(fileSize); |
||||
return isNaN(size) ? "0kB" : (size / 1000).toFixed(2) + "kB"; |
||||
}; |
||||
|
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,47 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
angular.module('openproject.workPackages.directives') |
||||
|
||||
.directive('attachmentUserCell', ['PathHelper', function(PathHelper){ |
||||
return { |
||||
restrict: 'A', |
||||
templateUrl: '/templates/work_packages/tabs/_attachment_user_cell.html', |
||||
scope: { |
||||
attachment: '=' |
||||
}, |
||||
link: function(scope, element, attributes) { |
||||
scope.attachment.links.author.fetch() |
||||
.then(function(author){ |
||||
scope.authorName = author.props.name; |
||||
scope.authorId = author.props.id; |
||||
scope.userPath = PathHelper.staticUserPath(author.props.id); |
||||
}); |
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,42 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
angular.module('openproject.workPackages.directives') |
||||
|
||||
.directive('attachmentsTable', ['PathHelper', 'I18n', function(PathHelper, I18n){ |
||||
return { |
||||
restrict: 'E', |
||||
templateUrl: '/templates/work_packages/tabs/_attachments_table.html', |
||||
scope: { |
||||
attachments: '=' |
||||
}, |
||||
link: function(scope) { |
||||
scope.I18n = I18n; |
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,43 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
angular.module('openproject.workPackages.directives') |
||||
|
||||
.directive('attachmentsTitle', [function(){ |
||||
return { |
||||
restrict: 'E', |
||||
replace: true, |
||||
templateUrl: '/templates/work_packages/tabs/_attachments_title.html', |
||||
scope: { |
||||
attachments: '=' |
||||
}, |
||||
link: function(scope, element, attributes) { |
||||
scope.attachmentsTitle = "Attachments (" + scope.attachments.length + ")"; |
||||
} |
||||
}; |
||||
}]); |
@ -0,0 +1,175 @@ |
||||
package Apache::Authn::OpenProject; |
||||
|
||||
=head1 Apache::Authn::OpenProject |
||||
|
||||
OpenProject - a mod_perl module to authenticate webdav subversion users |
||||
against an OpenProject web service |
||||
|
||||
=head1 SYNOPSIS |
||||
|
||||
This module allow anonymous users to browse public project and |
||||
registred users to browse and commit their project. Authentication is |
||||
done against an OpenProject web service. |
||||
|
||||
=head1 INSTALLATION |
||||
|
||||
For this to automagically work, you need to have a recent reposman.rb. |
||||
|
||||
Sorry ruby users but you need some perl modules, at least mod_perl2 and apache2-svn. |
||||
|
||||
On debian/ubuntu you must do : |
||||
|
||||
aptitude install libapache2-mod-perl2 libapache2-svn |
||||
|
||||
=head1 CONFIGURATION |
||||
|
||||
## This module has to be in your perl path |
||||
## eg: /usr/lib/perl5/Apache/Authn/OpenProjectAuthentication.pm |
||||
PerlLoadModule Apache::Authn::OpenProjectAuthentication |
||||
<Location /svn> |
||||
DAV svn |
||||
SVNParentPath "/var/svn" |
||||
|
||||
AuthType Basic |
||||
AuthName OpenProject |
||||
Require valid-user |
||||
|
||||
PerlAccessHandler Apache::Authn::OpenProject::access_handler |
||||
PerlAuthenHandler Apache::Authn::OpenProject::authen_handler |
||||
|
||||
OpenProjectUrl "http://example.com/openproject/" |
||||
OpenProjectApiKey "<API key>" |
||||
</Location> |
||||
|
||||
To be able to browse repository inside openproject, you must add something |
||||
like that : |
||||
|
||||
<Location /svn-private> |
||||
DAV svn |
||||
SVNParentPath "/var/svn" |
||||
Order deny,allow |
||||
Deny from all |
||||
# only allow reading orders |
||||
<Limit GET PROPFIND OPTIONS REPORT> |
||||
Allow from openproject.server.ip |
||||
</Limit> |
||||
</Location> |
||||
|
||||
and you will have to use this reposman.rb command line to create repository : |
||||
|
||||
reposman.rb --openproject my.openproject.server --svn-dir /var/svn --owner www-data -u http://svn.server/svn-private/ |
||||
|
||||
=cut |
||||
|
||||
use strict; |
||||
use warnings FATAL => 'all', NONFATAL => 'redefine'; |
||||
|
||||
use Digest::SHA; |
||||
|
||||
use Apache2::Module; |
||||
use Apache2::Access; |
||||
use Apache2::ServerRec qw(); |
||||
use Apache2::RequestRec qw(); |
||||
use Apache2::RequestUtil qw(); |
||||
use Apache2::Const qw(:common :override :cmd_how); |
||||
use APR::Pool (); |
||||
use APR::Table (); |
||||
|
||||
use HTTP::Request::Common qw(POST); |
||||
use LWP::UserAgent; |
||||
|
||||
# use Apache2::Directive qw(); |
||||
|
||||
my @directives = ( |
||||
{ |
||||
name => 'OpenProjectUrl', |
||||
req_override => OR_AUTHCFG, |
||||
args_how => TAKE1, |
||||
errmsg => 'URL of your (local) OpenProject. (e.g. http://localhost/ or http://www.example.com/openproject/)', |
||||
}, |
||||
{ |
||||
name => 'OpenProjectApiKey', |
||||
req_override => OR_AUTHCFG, |
||||
args_how => TAKE1, |
||||
}, |
||||
); |
||||
|
||||
sub OpenProjectUrl { set_val('OpenProjectUrl', @_); } |
||||
sub OpenProjectApiKey { set_val('OpenProjectApiKey', @_); } |
||||
|
||||
sub trim { |
||||
my $string = shift; |
||||
$string =~ s/\s{2,}/ /g; |
||||
return $string; |
||||
} |
||||
|
||||
sub set_val { |
||||
my ($key, $self, $parms, $arg) = @_; |
||||
$self->{$key} = $arg; |
||||
} |
||||
|
||||
Apache2::Module::add(__PACKAGE__, \@directives); |
||||
|
||||
sub access_handler { |
||||
my $r = shift; |
||||
|
||||
unless ($r->some_auth_required) { |
||||
$r->log_reason("No authentication has been configured"); |
||||
return FORBIDDEN; |
||||
} |
||||
|
||||
return OK |
||||
} |
||||
|
||||
sub authen_handler { |
||||
my $r = shift; |
||||
|
||||
my ($status, $password) = $r->get_basic_auth_pw(); |
||||
my $login = $r->user; |
||||
|
||||
return $status unless $status == OK; |
||||
|
||||
my $identifier = get_project_identifier($r); |
||||
my $method = $r->method; |
||||
|
||||
if( is_access_allowed( $login, $password, $identifier, $method, $r ) ) { |
||||
return OK; |
||||
} else { |
||||
$r->note_auth_failure(); |
||||
return AUTH_REQUIRED; |
||||
} |
||||
} |
||||
|
||||
# we send a request to the openproject sys api |
||||
# and use the user's given login and password for basic auth |
||||
# for accessing the openproject sys api an api key is needed |
||||
sub is_access_allowed { |
||||
my $login = shift; |
||||
my $password = shift; |
||||
my $identifier = shift; |
||||
my $method = shift; |
||||
my $r = shift; |
||||
|
||||
my $cfg = Apache2::Module::get_config( __PACKAGE__, $r->server, $r->per_dir_config ); |
||||
|
||||
my $key = $cfg->{OpenProjectApiKey}; |
||||
my $openproject_url = $cfg->{OpenProjectUrl} . '/sys/repo_auth'; |
||||
|
||||
my $openproject_req = POST $openproject_url , [ repository => $identifier, key => $key, method => $method ]; |
||||
$openproject_req->authorization_basic( $login, $password ); |
||||
|
||||
my $ua = LWP::UserAgent->new; |
||||
my $response = $ua->request($openproject_req); |
||||
|
||||
return $response->is_success(); |
||||
} |
||||
|
||||
sub get_project_identifier { |
||||
my $r = shift; |
||||
|
||||
my $location = $r->location; |
||||
my ($identifier) = $r->uri =~ m{$location/*([^/]+)}; |
||||
$identifier; |
||||
} |
||||
|
||||
1; |
@ -1,52 +0,0 @@ |
||||
-- -- copyright |
||||
-- OpenProject is a project management system. |
||||
-- Copyright (C) 2012-2014 the OpenProject Foundation (OPF) |
||||
-- |
||||
-- This program is free software; you can redistribute it and/or |
||||
-- modify it under the terms of the GNU General Public License version 3. |
||||
-- |
||||
-- OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
-- Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
-- Copyright (C) 2010-2013 the ChiliProject Team |
||||
-- |
||||
-- This program is free software; you can redistribute it and/or |
||||
-- modify it under the terms of the GNU General Public License |
||||
-- as published by the Free Software Foundation; either version 2 |
||||
-- of the License, or (at your option) any later version. |
||||
-- |
||||
-- This program is distributed in the hope that it will be useful, |
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
-- GNU General Public License for more details. |
||||
-- |
||||
-- You should have received a copy of the GNU General Public License |
||||
-- along with this program; if not, write to the Free Software |
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
-- |
||||
-- See doc/COPYRIGHT.rdoc for more details. |
||||
-- ++ |
||||
|
||||
/* ssh views */ |
||||
|
||||
CREATE OR REPLACE VIEW ssh_users as |
||||
select login as username, hashed_password as password |
||||
from users |
||||
where status = 1; |
||||
|
||||
|
||||
/* nss views */ |
||||
|
||||
CREATE OR REPLACE VIEW nss_groups AS |
||||
select identifier AS name, (id + 5000) AS gid, 'x' AS password |
||||
from projects; |
||||
|
||||
CREATE OR REPLACE VIEW nss_users AS |
||||
select login AS username, CONCAT_WS(' ', firstname, lastname) as realname, (id + 5000) AS uid, 'x' AS password |
||||
from users |
||||
where status = 1; |
||||
|
||||
CREATE OR REPLACE VIEW nss_grouplist AS |
||||
select (members.project_id + 5000) AS gid, users.login AS username |
||||
from users, members |
||||
where users.id = members.user_id |
||||
and users.status = 1; |
@ -0,0 +1,72 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
describe('attachmentTitleCell Directive', function() { |
||||
var compile, element, rootScope, scope; |
||||
|
||||
beforeEach(angular.mock.module('openproject.workPackages.directives')); |
||||
beforeEach(module('templates')); |
||||
|
||||
beforeEach(inject(function($rootScope, $compile) { |
||||
var html; |
||||
html = '<td attachment-title-cell attachment="attachment"></td>'; |
||||
|
||||
element = angular.element(html); |
||||
rootScope = $rootScope; |
||||
scope = $rootScope.$new(); |
||||
|
||||
compile = function() { |
||||
$compile(element)(scope); |
||||
scope.$digest(); |
||||
}; |
||||
})); |
||||
|
||||
describe('element', function() { |
||||
beforeEach(function() { |
||||
scope.attachment = { |
||||
props: { |
||||
id: 1, |
||||
fileName: 'hearmi.now', |
||||
fileSize: '12340' |
||||
} |
||||
}; |
||||
|
||||
compile(); |
||||
}); |
||||
|
||||
it('should render element', function() { |
||||
expect(element.prop('tagName')).to.equal('TD'); |
||||
}); |
||||
|
||||
it('should render link to attachment', function() { |
||||
var link = element.find('a'); |
||||
expect(link.text()).to.equal('hearmi.now (12.34kB)'); |
||||
expect(link.attr('href')).to.equal('/attachments/1/hearmi.now'); |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1,79 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
describe('attachmentUserCell Directive', function() { |
||||
var compile, element, rootScope, scope; |
||||
|
||||
beforeEach(angular.mock.module('openproject.workPackages.directives')); |
||||
beforeEach(module('templates')); |
||||
|
||||
beforeEach(inject(function($rootScope, $compile) { |
||||
var html; |
||||
html = '<td attachment-user-cell attachment="attachment"></td>'; |
||||
|
||||
element = angular.element(html); |
||||
rootScope = $rootScope; |
||||
scope = $rootScope.$new(); |
||||
|
||||
compile = function() { |
||||
$compile(element)(scope); |
||||
scope.$digest(); |
||||
}; |
||||
})); |
||||
|
||||
describe('element', function() { |
||||
var userName = 'Big Phil Scolari'; |
||||
var userId = 5; |
||||
|
||||
beforeEach(inject(function($q) { |
||||
scope.attachment = { |
||||
links: { |
||||
author: { |
||||
fetch: function() { |
||||
deferred = $q.defer(); |
||||
deferred.resolve({ props: { id: userId, name: userName} } ); |
||||
return deferred.promise; |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
compile(); |
||||
})); |
||||
|
||||
it('should render element', function() { |
||||
expect(element.prop('tagName')).to.equal('TD'); |
||||
}); |
||||
|
||||
it('should render link to user', function() { |
||||
var link = element.find('a'); |
||||
expect(link.text()).to.equal(userName); |
||||
expect(link.attr('href')).to.equal('/users/' + userId); |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1,67 @@ |
||||
//-- copyright
|
||||
// OpenProject is a project management system.
|
||||
// Copyright (C) 2012-2014 the OpenProject Foundation (OPF)
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License version 3.
|
||||
//
|
||||
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
// Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
// Copyright (C) 2010-2013 the ChiliProject Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// See doc/COPYRIGHT.rdoc for more details.
|
||||
//++
|
||||
|
||||
describe('attachmentsTitle Directive', function() { |
||||
var compile, element, rootScope, scope; |
||||
|
||||
beforeEach(angular.mock.module('openproject.workPackages.directives')); |
||||
beforeEach(module('templates')); |
||||
|
||||
beforeEach(inject(function($rootScope, $compile) { |
||||
var html; |
||||
html = '<attachments-title attachments="attachments"></attachments-title>'; |
||||
|
||||
element = angular.element(html); |
||||
rootScope = $rootScope; |
||||
scope = $rootScope.$new(); |
||||
|
||||
compile = function() { |
||||
$compile(element)(scope); |
||||
scope.$digest(); |
||||
}; |
||||
})); |
||||
|
||||
describe('element', function() { |
||||
beforeEach(function() { |
||||
scope.attachments = [ |
||||
{ filename: 'bomba' }, |
||||
{ filename: 'clat' } |
||||
]; |
||||
|
||||
compile(); |
||||
}); |
||||
|
||||
it('should render element', function() { |
||||
expect(element.prop('tagName')).to.equal('H3'); |
||||
}); |
||||
|
||||
it('should render title', function() { |
||||
expect(element.text()).to.equal('Attachments (2)'); |
||||
}); |
||||
}); |
||||
}); |
@ -0,0 +1 @@ |
||||
<a ng-href="{{ attachmentPath }}" ng-bind="displayTitle"></a> |
@ -0,0 +1 @@ |
||||
<a ng-href="{{ userPath }}" ng-bind="authorName"></a> |
@ -0,0 +1,19 @@ |
||||
|
||||
<table ng-if="attachments.length"> |
||||
<tbody> |
||||
<tr> |
||||
<th>{{ I18n.t('js.label_filename')}}</th> |
||||
<th>{{ I18n.t('js.label_filesize')}}</th> |
||||
<th>{{ I18n.t('js.label_description')}}</th> |
||||
<th>{{ I18n.t('js.label_date')}}</th> |
||||
<th></th> |
||||
</tr> |
||||
<tr ng-repeat="attachment in attachments" |
||||
attachment="attachment"> |
||||
<td attachment-title-cell attachment="attachment"></td> |
||||
<td attachment-user-cell attachment="attachment"></td> |
||||
<td>{{ attachment.props.description }}</td> |
||||
<td><date-time date-value="attachment.props.createdAt"></date></td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
@ -0,0 +1 @@ |
||||
<h3>{{ attachmentsTitle }}</h3> |
@ -1,6 +1,8 @@ |
||||
<div class="detail-panel-description"> |
||||
<h3>Attachments</h3> |
||||
<attachments-title attachments="attachments"></attachments-title> |
||||
<div class="detail-panel-description-content"> |
||||
... |
||||
<div class="attachments-container"> |
||||
<attachments-table attachments="attachments"></attachments-table> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
@ -0,0 +1,229 @@ |
||||
require 'spec_helper' |
||||
|
||||
module OpenProjectRepositoryAuthenticationSpecs |
||||
describe SysController do |
||||
let(:commit_role) { FactoryGirl.create(:role, :permissions => [:commit_access, |
||||
:browse_repository]) } |
||||
let(:browse_role) { FactoryGirl.create(:role, :permissions => [:browse_repository]) } |
||||
let(:guest_role) { FactoryGirl.create(:role, :permissions => []) } |
||||
let(:valid_user_password) { "Top Secret Password" } |
||||
let(:valid_user) { FactoryGirl.create(:user, :login => "johndoe", |
||||
:password => valid_user_password, |
||||
:password_confirmation => valid_user_password)} |
||||
|
||||
before(:each) do |
||||
FactoryGirl.create(:non_member, :permissions => [:browse_repository]) |
||||
DeletedUser.first # creating it first in order to avoid problems with should_receive |
||||
|
||||
random_project = FactoryGirl.create(:project, :is_public => false) |
||||
@member = FactoryGirl.create(:member, :user => valid_user, |
||||
:roles => [browse_role], |
||||
:project => random_project) |
||||
Setting.stub(:sys_api_key).and_return("12345678") |
||||
Setting.stub(:sys_api_enabled?).and_return(true) |
||||
Setting.stub(:repository_authentication_caching_enabled?).and_return(true) |
||||
end |
||||
|
||||
describe :repo_auth, "for valid login, but no access to repo_auth" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password) |
||||
post "repo_auth", { :key => @key, :repository => "without-access", :method => "GET" } |
||||
end |
||||
|
||||
it "should respond 403 not allowed" do |
||||
response.code.should == "403" |
||||
response.body.should == "Not allowed" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for valid login and user has browse repository permission (role reporter) for project" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
@project = FactoryGirl.create(:project, :is_public => false) |
||||
@member = FactoryGirl.create(:member, :user => valid_user, |
||||
:roles => [browse_role], |
||||
:project => @project) |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password) |
||||
end |
||||
|
||||
it "should respond 200 okay dokay for GET" do |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "GET" } |
||||
response.code.should == "200" |
||||
end |
||||
|
||||
it "should respond 403 not allowed for POST" do |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "POST" } |
||||
response.code.should == "403" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for valid login and user has commit access permission (role developer) for project" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
@project = FactoryGirl.create(:project, :is_public => false) |
||||
@member = FactoryGirl.create(:member, :user => valid_user, |
||||
:roles => [commit_role], |
||||
:project => @project ) |
||||
valid_user.save |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password) |
||||
end |
||||
|
||||
it "should respond 200 okay dokay for GET" do |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "GET" } |
||||
response.code.should == "200" |
||||
end |
||||
|
||||
it "should respond 200 okay dokay for POST" do |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "POST" } |
||||
response.code.should == "200" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for invalid login and user has role manager for project" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
@project = FactoryGirl.create(:project, :is_public => false ) |
||||
@member = FactoryGirl.create(:member, :user => valid_user, |
||||
:roles => [commit_role], |
||||
:project => @project) |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password + "made invalid") |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "GET" } |
||||
end |
||||
|
||||
it "should respond 401 auth required" do |
||||
response.code.should == "401" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for valid login and user is not member for project" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
@project = FactoryGirl.create(:project, :is_public => false) |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password) |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "GET" } |
||||
end |
||||
|
||||
it "should respond 403 not allowed" do |
||||
response.code.should == "403" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for valid login and project is public" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
@project = FactoryGirl.create(:project, :is_public => true) |
||||
|
||||
random_project = FactoryGirl.create(:project, :is_public => false) |
||||
@member = FactoryGirl.create(:member, :user => valid_user, |
||||
:roles => [browse_role], |
||||
:project => random_project) |
||||
|
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password) |
||||
post "repo_auth", { :key => @key, :repository => @project.identifier, :method => "GET" } |
||||
end |
||||
|
||||
it "should respond 200 OK" do |
||||
response.code.should == "200" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for invalid credentials" do |
||||
before(:each) do |
||||
@key = Setting.sys_api_key |
||||
post "repo_auth", { :key => @key, :repository => "any-repo", :method => "GET" } |
||||
end |
||||
|
||||
it "should respond 401 auth required" do |
||||
response.code.should == "401" |
||||
response.body.should == "Authorization required" |
||||
end |
||||
end |
||||
|
||||
describe :repo_auth, "for invalid api key" do |
||||
before(:each) do |
||||
@key = "invalid" |
||||
end |
||||
|
||||
it "should respond 403 for valid username/password" do |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(valid_user.login, valid_user_password) |
||||
post "repo_auth", { :key => @key, :repository => "any-repo", :method => "GET" } |
||||
response.code.should == "403" |
||||
response.body.should == "Access denied. Repository management WS is disabled or key is invalid." |
||||
end |
||||
|
||||
it "should respond 403 for invalid username/password" do |
||||
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials("invalid", "invalid") |
||||
post "repo_auth", { :key => @key, :repository => "any-repo", :method => "GET" } |
||||
response.code.should == "403" |
||||
response.body.should == "Access denied. Repository management WS is disabled or key is invalid." |
||||
end |
||||
end |
||||
|
||||
before(:each) do |
||||
Rails.cache.clear |
||||
Rails.cache.stub(:kind_of?).with(anything).and_return(false) |
||||
end |
||||
|
||||
describe :cached_user_login do |
||||
let(:cache_key) { OpenProject::RepositoryAuthentication::CACHE_PREFIX + |
||||
Digest::SHA1.hexdigest("#{valid_user.login}#{valid_user_password}") } |
||||
let(:cache_expiry) { OpenProject::RepositoryAuthentication::CACHE_EXPIRES_AFTER } |
||||
|
||||
it "should call user_login only once when called twice" do |
||||
controller.should_receive(:user_login).once.and_return(valid_user) |
||||
2.times { controller.send(:cached_user_login, valid_user.login, valid_user_password) } |
||||
end |
||||
|
||||
it "should return the same as user_login for valid creds" do |
||||
controller.send(:cached_user_login, valid_user.login, valid_user_password).should == |
||||
controller.send(:user_login, valid_user.login, valid_user_password) |
||||
end |
||||
|
||||
it "should return the same as user_login for invalid creds" do |
||||
controller.send(:cached_user_login, "invalid", "invalid").should == |
||||
controller.send(:user_login, "invalid", "invalid") |
||||
end |
||||
|
||||
it "should use cache" do |
||||
# allow the cache to return something reasonable for |
||||
# other requests, while ensuring that it is not queried |
||||
# with the cache key in question |
||||
|
||||
# unfortunately, and_call_original currently fails |
||||
Rails.cache.stub(:fetch) do |*args| |
||||
args.first.should_not == cache_key |
||||
|
||||
name = args.first.split("/").last |
||||
Marshal.dump(Setting.send(:find_or_default, name).value) |
||||
end |
||||
#Rails.cache.should_receive(:fetch).with(anything).and_call_original |
||||
Rails.cache.should_receive(:fetch).with(cache_key, :expires_in => cache_expiry) \ |
||||
.and_return(Marshal.dump(valid_user.id.to_s)) |
||||
controller.send(:cached_user_login, valid_user.login, valid_user_password) |
||||
end |
||||
|
||||
describe "with caching disabled" do |
||||
before do |
||||
Setting.stub(:repository_authentication_caching_enabled?).and_return(false) |
||||
end |
||||
|
||||
it 'should not use a cache' do |
||||
# allow the cache to return something reasonable for |
||||
# other requests, while ensuring that it is not queried |
||||
# with the cache key in question |
||||
# |
||||
# unfortunately, and_call_original currently fails |
||||
Rails.cache.stub(:fetch) do |*args| |
||||
args.first.should_not == cache_key |
||||
|
||||
name = args.first.split("/").last |
||||
Marshal.dump(Setting.send(:find_or_default, name).value) |
||||
end |
||||
|
||||
controller.send(:cached_user_login, valid_user.login, valid_user_password) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue