diff --git a/PREREQUISITES.md b/PREREQUISITES.md
index 3537d8ceaf..7284e948ae 100644
--- a/PREREQUISITES.md
+++ b/PREREQUISITES.md
@@ -3,6 +3,7 @@
The [Angular 2](https://angular.io/) based application development framework requires the following:
- An Alfresco Platform Repository (version [5.2.a-EA](https://wiki.alfresco.com/wiki/Community_file_list_201606-EA) or newer) to talk to, which has [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) enabled.
+- [Download and install Activiti](https://www.alfresco.com/products/bpm/alfresco-activiti/trial)
- [Node.js](https://nodejs.org/en/) JavaScript runtime.
- [npm](https://www.npmjs.com/) package manager for JavaScript.
@@ -10,84 +11,6 @@ The [Angular 2](https://angular.io/) based application development framework req
by running `node -v` and `npm -v` in a terminal/console window.
Older versions produce errors.
-## Installing Alfresco
-
-Alfresco comes with installers that will install all the servers, webapps, and tools needed to run Alfresco.
-
-- Download Alfresco Community from this [page](https://www.alfresco.com/products/community/download).
-- Install Alfresco following these [instructions](http://docs.alfresco.com/5.1/concepts/installs-eval-intro.html).
-
-This will install the following Alfresco web applications:
-
-- Alfresco Platform with the Content Repository, which we need so we can access content from our custom web client
-- Alfresco Solr, which we need so we can search for content from our custom web client
-- Alfresco Share, not technically needed, but can be useful for creating users and groups, and to access and upload content to the repository while we are developing the custom web client
-
-### Enable CORS in Alfresco
-
-The web client that we are building with the application development framework will be loaded from a different web server than the Alfresco Platform is running on.
-So we need to tell the Alfresco server that any request that comes in from this custom web client should be allowed access
-to the Content Repository. This is done by enabling CORS.
-
-To enable CORS in the Alfresco Platform do one of the following:
-
-**Download and install the enable CORS module**
-
-This is the easiest way, add the [enablecors](https://artifacts.alfresco.com/nexus/service/local/repositories/releases/content/org/alfresco/enablecors/1.0/enablecors-1.0.jar)
-platform module JAR to the *$ALF_INSTALL_DIR/modules/platform* directory and restart the server.
-
-Note. by default the CORS filter that is enabled will allow any orgin.
-
-**Manually update the web.xml file**
-
-Modify *$ALF_INSTALL_DIR/tomcat/webapps/alfresco/WEB-INF/web.xml* and uncomment the following section and update
-`cors.allowOrigin` to `http://localhost:3000`:
-
-```
- CORS
- com.thetransactioncompany.cors.CORSFilter
-
- cors.allowGenericHttpRequests
- true
-
-
- cors.allowOrigin
- http://localhost:3000
-
-
- cors.allowSubdomains
- true
-
-
- cors.supportedMethods
- GET, HEAD, POST, PUT, DELETE, OPTIONS
-
-
- cors.supportedHeaders
- origin, authorization, x-file-size, x-file-name, content-type, accept, x-file-type
-
-
- cors.supportsCredentials
- true
-
-
- cors.maxAge
- 3600
-
-
-```
-When specifying the `cors.allowOrigin` URL make sure to use the URL that will be used by the web client.
-
-Then uncomment filter mappings:
-
-```
- CORS
- /api/*
- /service/*
- /s/*
- /cmisbrowser/*
-
-```
## Installing Node.js
If you don't have Node.js installed then access this [page](https://nodejs.org/en/download/) and use the appropriate installer for your OS.
@@ -99,4 +22,8 @@ $ node -v
v5.12.0
```
+## Configure Nginx
+
+To correctly configure Nginx use the following file [nginx.conf](/nginx.conf).
+This will put Activiti, Alfresco and the app dev framework under the same domain.
diff --git a/demo-shell-ng2/app/app.component.css b/demo-shell-ng2/app/app.component.css
index 87031d33ee..700caa1af0 100644
--- a/demo-shell-ng2/app/app.component.css
+++ b/demo-shell-ng2/app/app.component.css
@@ -3,3 +3,7 @@
display: none;
}
}
+
+.mdl-layout-title{
+ font-size: 17px;
+}
diff --git a/demo-shell-ng2/app/components/login/login-demo.component.html b/demo-shell-ng2/app/components/login/login-demo.component.html
index dbc7ee20ca..8f732a3b28 100644
--- a/demo-shell-ng2/app/components/login/login-demo.component.html
+++ b/demo-shell-ng2/app/components/login/login-demo.component.html
@@ -11,12 +11,18 @@
BPM
+
+
+
-
diff --git a/demo-shell-ng2/app/components/login/login-demo.component.ts b/demo-shell-ng2/app/components/login/login-demo.component.ts
index 64e1eef1ca..4cdbf03042 100644
--- a/demo-shell-ng2/app/components/login/login-demo.component.ts
+++ b/demo-shell-ng2/app/components/login/login-demo.component.ts
@@ -33,6 +33,7 @@ export class LoginDemoComponent implements OnInit {
alfrescologin: any;
providers: string = 'ECM';
+ disableCsrf: boolean = false;
blackListUsername: string;
customValidation: any;
@@ -82,6 +83,10 @@ export class LoginDemoComponent implements OnInit {
}
}
+ toggleCSRF() {
+ this.disableCsrf = !this.disableCsrf;
+ }
+
validateForm(event: any) {
let values = event.values;
if (values.controls['username'].value === this.blackListUsername ) {
diff --git a/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthentication.service.ts b/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthentication.service.ts
index 174c626ae2..50313d5c89 100644
--- a/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthentication.service.ts
+++ b/ng2-components/ng2-alfresco-core/src/services/AlfrescoAuthentication.service.ts
@@ -44,7 +44,8 @@ export class AlfrescoAuthenticationService {
ticketBpm: this.getTicketBpm(),
hostEcm: this.settingsService.ecmHost,
hostBpm: this.settingsService.bpmHost,
- contextRoot: 'alfresco'
+ contextRoot: 'alfresco',
+ disableCsrf: true
});
settingsService.bpmHostSubject.subscribe((bpmHost) => {
@@ -55,6 +56,10 @@ export class AlfrescoAuthenticationService {
this.alfrescoApi.changeEcmHost(ecmHost);
});
+ settingsService.csrfSubject.subscribe((csrf) => {
+ this.alfrescoApi.changeCsrfConfig(csrf);
+ });
+
settingsService.providerSubject.subscribe((value) => {
this.alfrescoApi.config.provider = value;
});
diff --git a/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettings.service.ts b/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettings.service.ts
index 012e35c3a2..55a46de707 100644
--- a/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettings.service.ts
+++ b/ng2-components/ng2-alfresco-core/src/services/AlfrescoSettings.service.ts
@@ -23,11 +23,13 @@ export class AlfrescoSettingsService {
static DEFAULT_ECM_ADDRESS: string = 'http://' + window.location.hostname + ':8080';
static DEFAULT_BPM_ADDRESS: string = 'http://' + window.location.hostname + ':9999';
+ static DEFAULT_CSRF_CONFIG: boolean = false;
static DEFAULT_BPM_CONTEXT_PATH: string = '/activiti-app';
private _ecmHost: string = AlfrescoSettingsService.DEFAULT_ECM_ADDRESS;
private _bpmHost: string = AlfrescoSettingsService.DEFAULT_BPM_ADDRESS;
+ private _csrfDisabled: boolean = AlfrescoSettingsService.DEFAULT_CSRF_CONFIG;
private _bpmContextPath = AlfrescoSettingsService.DEFAULT_BPM_CONTEXT_PATH;
@@ -35,12 +37,18 @@ export class AlfrescoSettingsService {
public bpmHostSubject: Subject = new Subject();
public ecmHostSubject: Subject = new Subject();
+ public csrfSubject: Subject = new Subject();
public providerSubject: Subject = new Subject();
public get ecmHost(): string {
return this._ecmHost;
}
+ public set csrfDisabled(csrfDisabled: boolean) {
+ this.csrfSubject.next(csrfDisabled);
+ this._csrfDisabled = csrfDisabled;
+ }
+
public set ecmHost(ecmHostUrl: string) {
this.ecmHostSubject.next(ecmHostUrl);
this._ecmHost = ecmHostUrl;
diff --git a/ng2-components/ng2-alfresco-documentlist/src/assets/document-library.model.mock.ts b/ng2-components/ng2-alfresco-documentlist/src/assets/document-library.model.mock.ts
index 20e7820a7a..e314cd7d89 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/assets/document-library.model.mock.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/assets/document-library.model.mock.ts
@@ -17,25 +17,25 @@
import {
NodePaging,
- MinimalNodeEntity,
- MinimalNodeEntryEntity,
+ NodeMinimalEntry,
+ NodeMinimal,
PathInfoEntity,
ContentInfo,
NodePagingList
} from '../models/document-library.model';
export class PageNode extends NodePaging {
- constructor(entries?: MinimalNodeEntity[]) {
+ constructor(entries?: NodeMinimalEntry[]) {
super();
this.list = new NodePagingList();
this.list.entries = entries || [];
}
}
-export class FileNode extends MinimalNodeEntity {
+export class FileNode extends NodeMinimalEntry {
constructor(name?: string, mimeType?: string) {
super();
- this.entry = new MinimalNodeEntryEntity();
+ this.entry = new NodeMinimal();
this.entry.id = 'file-id';
this.entry.isFile = true;
this.entry.isFolder = false;
@@ -46,10 +46,10 @@ export class FileNode extends MinimalNodeEntity {
}
}
-export class FolderNode extends MinimalNodeEntity {
+export class FolderNode extends NodeMinimalEntry {
constructor(name?: string) {
super();
- this.entry = new MinimalNodeEntryEntity();
+ this.entry = new NodeMinimal();
this.entry.id = 'folder-id';
this.entry.isFile = false;
this.entry.isFolder = true;
diff --git a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts
index 4d2879db85..8e2da843bf 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/components/document-list.spec.ts
@@ -21,7 +21,7 @@ import { DocumentList } from './document-list';
import { DocumentListServiceMock } from './../assets/document-list.service.mock';
import { ContentActionModel } from '../models/content-action.model';
import { FileNode, FolderNode } from '../assets/document-library.model.mock';
-import { MinimalNodeEntity } from '../models/document-library.model';
+import { NodeMinimalEntry } from '../models/document-library.model';
describe('DocumentList', () => {
@@ -131,7 +131,7 @@ describe('DocumentList', () => {
documentButton.target = 'document';
documentList.actions = [documentButton];
- let node = new MinimalNodeEntity();
+ let node = new NodeMinimalEntry();
expect(documentList.getNodeActions(node)).toEqual([]);
node = new FileNode();
diff --git a/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.spec.ts b/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.spec.ts
index 27b44401a7..bfa17ec7b3 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.spec.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.spec.ts
@@ -130,7 +130,7 @@ describe('ShareDataTableAdapter', () => {
});
it('should covert cell value to formatted date', () => {
- let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
+ let rawValue = new Date(2015, 6, 15, 21, 43, 11); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
let dateValue = 'Jul 15, 2015, 9:43:11 PM';
let file = new FileNode();
@@ -150,7 +150,7 @@ describe('ShareDataTableAdapter', () => {
});
it('should use default date format as fallback', () => {
- let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
+ let rawValue = new Date(2015, 6, 15, 21, 43, 11); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
let dateValue = 'Jul 15, 2015, 9:43:11 PM';
let file = new FileNode();
@@ -170,7 +170,7 @@ describe('ShareDataTableAdapter', () => {
});
it('should return date value as string', () => {
- let rawValue = new Date(2015, 6, 15, 21, 43, 11).toString(); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
+ let rawValue = new Date(2015, 6, 15, 21, 43, 11); // Wed Jul 15 2015 21:43:11 GMT+0100 (BST);
let file = new FileNode();
file.entry.createdAt = rawValue;
@@ -190,7 +190,7 @@ describe('ShareDataTableAdapter', () => {
it('should log error when having date conversion issues', () => {
let dateValue = '[wrong-date]';
let file = new FileNode();
- file.entry.createdAt = dateValue;
+ file.entry.createdAt = dateValue;
let col = {
key: 'createdAt',
diff --git a/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts b/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts
index 1150ec9150..444d166337 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/data/share-datatable-adapter.ts
@@ -23,7 +23,7 @@ import {
DataRow, DataColumn, DataSorting
} from 'ng2-alfresco-datatable';
-import { NodePaging, MinimalNodeEntity } from './../models/document-library.model';
+import { NodePaging, NodeMinimalEntry } from './../models/document-library.model';
import { DocumentListService } from './../services/document-list.service';
export class ShareDataTableAdapter implements DataTableAdapter, PaginationProvider {
@@ -305,11 +305,11 @@ export class ShareDataRow implements DataRow {
isSelected: boolean = false;
- get node(): MinimalNodeEntity {
+ get node(): NodeMinimalEntry {
return this.obj;
}
- constructor(private obj: MinimalNodeEntity) {
+ constructor(private obj: NodeMinimalEntry) {
if (!obj) {
throw new Error(ShareDataRow.ERR_OBJECT_NOT_FOUND);
}
diff --git a/ng2-components/ng2-alfresco-documentlist/src/models/document-library.model.ts b/ng2-components/ng2-alfresco-documentlist/src/models/document-library.model.ts
index 1ef4ddd54d..c90ec1e724 100644
--- a/ng2-components/ng2-alfresco-documentlist/src/models/document-library.model.ts
+++ b/ng2-components/ng2-alfresco-documentlist/src/models/document-library.model.ts
@@ -17,18 +17,19 @@
// note: contains only limited subset of available fields
+import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
+
export class NodePaging {
list: NodePagingList;
}
export class NodePagingList {
pagination: Pagination;
- entries: MinimalNodeEntity[];
+ entries: NodeMinimalEntry[];
}
-// TODO: rename to NodeMinimalEntry
-export class MinimalNodeEntity {
- entry: MinimalNodeEntryEntity;
+export class NodeMinimalEntry implements MinimalNodeEntity {
+ entry: NodeMinimal;
}
export class Pagination {
@@ -39,17 +40,16 @@ export class Pagination {
maxItems: number;
}
-// TODO: rename to NodeMinimal
-export class MinimalNodeEntryEntity {
+export class NodeMinimal implements MinimalNodeEntryEntity {
id: string;
parentId: string;
name: string;
nodeType: string;
isFolder: boolean;
isFile: boolean;
- modifiedAt: string;
+ modifiedAt: Date;
modifiedByUser: UserInfo;
- createdAt: string;
+ createdAt: Date;
createdByUser: UserInfo;
content: ContentInfo;
path: PathInfoEntity;
diff --git a/ng2-components/ng2-alfresco-login/README.md b/ng2-components/ng2-alfresco-login/README.md
index d93e325e1a..38dfda9135 100644
--- a/ng2-components/ng2-alfresco-login/README.md
+++ b/ng2-components/ng2-alfresco-login/README.md
@@ -151,6 +151,7 @@ Attribute | Description |
Attribute | Options | Default | Description | Mandatory
--- | --- | --- | --- | ---
`providers` | *string* | ECM | Possible valid value are ECM, BPM or ALL. The default behaviour of this component will logged in only in the ECM . If you want log in in both system the correct value to use is ALL |
+`disableCsrf` | *boolean* | false | To prevent the CSRF Token from been submitted. Only for Activiti call |
## Custom logo and background
diff --git a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts
index a953380da7..c5c49b62ec 100644
--- a/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts
+++ b/ng2-components/ng2-alfresco-login/src/components/alfresco-login.component.ts
@@ -51,6 +51,9 @@ export class AlfrescoLoginComponent implements OnInit {
@Input()
fieldsValidation: any;
+ @Input()
+ disableCsrf: boolean;
+
@Output()
onSuccess = new EventEmitter();
@@ -107,6 +110,7 @@ export class AlfrescoLoginComponent implements OnInit {
return false;
}
this.settingsService.setProviders(this.providers);
+ this.settingsService.csrfDisabled = this.disableCsrf;
this.disableError();
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000000..272a57caa7
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,97 @@
+server {
+ listen 8888;
+ server_name dev-platform-proxy;
+
+ #set $allowOriginSite http://127.0.0.1:3000;
+ set $allowOriginSite *;
+
+ gzip on;
+ gzip_min_length 1000;
+ gzip_proxied expired no-cache no-store private auth;
+ underscores_in_headers on;
+ proxy_pass_request_headers on;
+ proxy_pass_header Set-Cookie;
+
+ location /alfresco/ {
+ proxy_pass http://localhost:8080/;
+ proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+ proxy_redirect off;
+ proxy_buffering off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass_header Set-Cookie;
+
+ if ($request_method = 'OPTIONS') {
+ more_set_headers 'Access-Control-Allow-Origin: $allowOriginSite';
+ #
+ # Om nom nom cookies
+ #
+ more_set_headers 'Access-Control-Allow-Credentials: true';
+ more_set_headers 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS';
+ #
+ # Custom headers and headers various browsers *should* be OK with but aren't
+ #
+ more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Content-Range, Content-Disposition, Content-Description, X-CSRF-TOKEN, Authorization';
+ #
+ # Tell client that this pre-flight info is valid for 20 days
+ #
+ more_set_headers 'Access-Control-Max-Age: 1728000';
+ more_set_headers 'Content-Type: text/plain charset=UTF-8';
+ more_set_headers 'Content-Length 0';
+ return 204;
+ }
+ }
+
+ location /activiti/ {
+ proxy_pass http://localhost:9999/;
+ proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+ proxy_redirect off;
+ proxy_buffering off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass_header Set-Cookie;
+ proxy_pass_request_headers on;
+
+ if ($request_method = 'OPTIONS') {
+ more_set_headers 'Access-Control-Allow-Origin: $allowOriginSite';
+ #
+ # Om nom nom cookies
+ #
+ more_set_headers 'Access-Control-Allow-Credentials: true';
+ more_set_headers 'Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS';
+ #
+ # Custom headers and headers various browsers *should* be OK with but aren't
+ #
+ more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Content-Range, Content-Disposition, Content-Description, X-CSRF-TOKEN, Authorization';
+ #
+ # Tell client that this pre-flight info is valid for 20 days
+ #
+ more_set_headers 'Access-Control-Max-Age: 1728000';
+ more_set_headers 'Content-Type: text/plain charset=UTF-8';
+ more_set_headers 'Content-Length 0';
+ return 204;
+ }
+
+ if ($request_method = 'POST') {
+ more_set_headers 'Access-Control-Allow-Origin: $allowOriginSite';
+ more_set_headers 'Access-Control-Allow-Credentials: true';
+ more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, DELETE';
+ more_set_headers 'Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Content-Range, Content-Disposition, Content-Description, X-CSRF-TOKEN, Authorization';
+ }
+ }
+
+ location / {
+ proxy_pass http://localhost:3000/;
+ proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
+ proxy_redirect off;
+ proxy_buffering off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-NginX-Proxy true;
+ proxy_pass_header Set-Cookie;
+ proxy_pass_request_headers on;
+ }
+ }
\ No newline at end of file