AdminstrationGuide

ProjectForge® 2013

Version: 5.4
Date: 2014-05-15
Project: ProjectForge® 2013
URL: www.projectforge.org
Author: Kai Reinhard
mailtok.reinhard@me.com

downloadPrint-friendly version: AdministrationGuide.pdf

Contents

1Introduction
2Setting up the application working directory
3Setting up the database
3.1 Desktop database Hypersonic
3.2 Initialization, first login and set-up dialogue
3.3 PostgreSQL
3.3.1 Mac OS X
3.3.2 Configuration
3.3.3 Setting up the database
3.4 Create database indices
4Configuration
4.1 Base directory (application's home)
4.2 Configuration file config.xml
4.3 Customization
4.3.1 Logo ant title in pdf outputs
4.4 Configuration settings (web interface)
4.5 Using ttf fonts for PDF render engine
4.6 HTML formatted E-Mail templates
4.7 Configuration of Mobile Enterprise Blogging (MEB)
4.7.1 E-Mail
4.7.2 Servlet-Call
4.7.3 Easy creation of JIRA-Issues
4.8 Asterisk connection: phone calls and texting with ProjectForge
4.8.1 Phone calls
4.8.2 Texting
4.8.3 PhoneLookupServlet
4.9 business assessment / BWA
4.10 SecurityConfig
4.10.1 Secure passwords
4.10.1.1 Protection against brute force attacks
4.10.1.2 Salted passwords
4.10.1.3 Salted passwords with pepper
4.11 LDAP
4.11.1 Requirements
4.11.2 Configuration
4.11.3 Local (admin) users
4.11.4 LDAP over SSL
4.11.4.1 Configure certificate in config.xml
4.11.4.2 Import the certificate to your keystore
4.11.5 ProjectForge as LDAP master
4.11.5.1 LDAP entries
4.11.5.2 Managing POSIX accounts
4.11.6 Managing Samba accounts
4.11.7 ProjectForge as LDAP client
4.11.7.1 Simple mode
4.11.7.2 Users mode
4.11.7.3 Users-groups mode
5Maintenance
5.1 Updating by simple clicks
5.2 Re-indexing the database
5.3 Starting ProjectForge from command-line (without Tomcat)
5.4 Restart/Shutdown
5.5 Analysing tools
5.6 XML-backup and restore and data-base migration
5.6.1 Export
5.6.2 Import
5.6.3 Limitations
5.7 Backup
5.8 Restoring a backup
5.9 Automatical backup
5.9.1 Backup script
5.9.2 Adding crontab
5.9.3 Remote backup
5.9.4 Polling remote backup
5.10 Monitoring
5.11 Scheduler
5.11.1 Data base search index
5.12 Spaces
5.12.1 Store
5.12.2 Deletion or historization of spaces
5.13 Uninstalling ProjectForge
6Webserver Tomcat
6.1 server.xml
6.2 context.xml
6.3 Increase memory and environment for Tomcat
6.4 Generating SSL key
6.5 Webapp Lambda-Probe
7Plugins
7.1 Liquidity planning
7.1.1 Description
7.1.2 Configuration
7.2 Software license management
7.2.1 Description
7.2.2 Configuration
8FAQ
8.1 Reset passwords
8.2 Hypersonic: Could not insert entries to the data base.

List of figures

1Initiating phone calls
2Texting with ProjectForge
3LDAP user entry managed or expected by ProjectForge
4LDAP group entry managed or expected by ProjectForge
5LDAP Posix accounts managed by ProjectForge
6LDAP Samba and POSIX accounts managed by ProjectForge
7ProjectForge provides a convenient method for system updates. The data base scheme will be updated and the data base will be migrated automatically by scripts.
8Management of company's software licenses with ProjectForge

1 Introduction

This documents describes the administration of ProjectForge®.

2 Setting up the application working directory

  1. mkdir -p ${HOME}/ProjectForge/hibernate-search
    mkdir ${HOME}/ProjectForge/tmp mkdir ${HOME}/ProjectForge/work
  2. cp -r resources ${HOME}/ProjectForge/

3 Setting up the database

3.1 Desktop database Hypersonic

  1. cp hsqldb-1.8.0.7.jar apache-tomcat/common/lib/ (for tomcat 6: apache-tomcat/lib )
  2. mkdir ${user.home}/ProjectForge
  3. Start ProjectForge® (via Tomcat or Eclipse WTP-Plugin)
The database will be written at default to ${user.home}/ProjectForge.

3.2 Initialization, first login and set-up dialogue

After the first start of ProjectForge® you will see ProjectForge®'s set-up dialogue. Please configure at minimum the adminstrator's password and the target (empty data-base for a productive system or pre-filled with test data). You can configure or change all other settings such as time zone, e-mail addresses etc. any time later.

3.3 PostgreSQL

3.3.1 Mac OS X

Install PostgreSQL e.g. via fink install postgresql . Shared memory regions are set during the system's startup. Unfortunately, once the shared memory regions have been configured on Mac OS X, it appears they can't be changed. Here's how to increase them on your system. Edit /etc/sysctl.conf and set higher numbers there (from wiki.finkproject.org/index.php/Shared_Memory_Regions_on_Darwin ):
 File: /etc/sysctl.conf
1
2
3
4
5
kern.sysv.shmmax=16777216
kern.sysv.shmmin=1
kern.sysv.shmmni=64
kern.sysv.shmseg=8
kern.sysv.shmall=32768
Remember to set all of the 5 values above, otherwise your settings will be overridden by /etc/rc.

Hint

For more convinient start and stop of the PostgreSQL as normal user, try this:
1
2
3
Archon:~ admin$ sudo visudo
kai   ALL = NOPASSWD: /sw/bin/pgsql.sh start
kai   ALL = NOPASSWD: /sw/bin/pgsql.sh stop
Afterwards you can start without su as normal user the database with /sw/bin/pgsql.sh start and stop with /sw/bin/pgsql.sh stop without entering any password. (Currently I've problems with: "could not identify current directory: Permission denied" . The hotfix is to change the directory to any which is readable for the super user: cd /tmp; sudo /sw/bin/pgsql.sh start; cd - .

3.3.2 Configuration

 File: pg_hba.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
# Database administrative login by UNIX sockets
local   projectforge projectforge                     ident sameuser

# TYPE  DATABASE    USER        CIDR-ADDRESS          METHOD

# "local" is for Unix domain socket connections only
local   all         all                               md5
local   all         all                               ident sameuser
# IPv4 local connections:
host    all         all         192.168.12.34/32      md5
host    all         all         127.0.0.1/32          md5
# IPv6 local connections:
host    all         all         ::1/128               md5

3.3.3 Setting up the database

  1. Edit postgresql.conf:
     File: postgresql.conf
    1
    2
    3
    ...
    max_connections = 200                   # (change requires restart)
    ...
  2. createuser -U postgres -P projectforge as e.g. admin user.
  3. createdb -U postgres -E UTF-8 -O projectforge projectforge as e.g. admin user.
  4. You can drop any existing user and database with: dropdb projectforge and dropuser projectforge
  5. Re-use of existing database (use a dump)
    psql -q -f projectforge_2008-04-02_02-00.sql -U postgres projectforge 2>&1 > log.txt
  6. cp postgresql-8.0-318.jdbc3.jar apache-tomcat/common/lib/ (for tomcat 6: apache-tomcat/lib )
  7. Creation of the new database scheme
    1. Create ProjectForge.xml in conf/Catalina/localhost/ ($CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml). and modify
      schemaUpdate=true
    2. Start ProjectForge® for automatically creation of the new database scheme (see log files for detail).
    3. Stop ProjectForge®
    4. Restore setting in $CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml
      schemaUpdate=false

3.4 Create database indices

The creation script of all proposed indices can be downloaded via the admin web. The most indices for the foreign keys are build out of the metadata of the PostgreSQL database.

4 Configuration

4.1 Base directory (application's home)

ProjectForge® needs a base directory which is set in $CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml of the web server. By default it is ${user.home}/ProjectForge . You should prepare this directory for use-age of ProjectForge®. The following directories must exist:
ProjectForge/hibernate-search Here the lucene indices are stored. If corrupted, delete all files and directories in this directory and re-build data base indices via the web admin console.
ProjectForge/resources/fonts For additional fonts used e. g. by the pdf renderers.
ProjectForge/resources/images For images e. g. by the pdf renderers.
ProjectForge/work For uploaded files etc.

4.2 Configuration file config.xml

The format of the file is:
 File: <app-home>/config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="UTF-8" ?>
<config>
  <!-- Uncomment this, if ProjectForge runs in root context: -->
  <!--servletContextPath></servletContextPath-->
  <!-- Uncomment this, if ProjectForge does not regognize your host
       correctly for e. g. ImageCropper: -->

  <!--domain>https://projectforge.acme.com:8443</domain-->
  <!-- Enable marketing plugin and plugin to manage software license keys (Adobe, Microsoft etc.): -->
  <!--pluginMainClasses>
    org.projectforge.plugins.marketing.MarketingPlugin
  </pluginMainClasses-->

  <!-- Customized logo file relative to <app-home>/resources/images: -->
  <!-- logoFile>Micromata.png</logoFile-->
  <telephoneSystemUrl>http://asterisk.acme.com/originatecall.php\
  ?source=#source&amp;target=#target</telephoneSystemUrl>
  <telephoneSystemNumber>0561316793</telephoneSystemNumber>
  <telephoneSystemOperatorPanelUrl><![CDATA[
    <a onclick=
"var w = window.open('http://192.168.76.25/', 'asterisk',\
                'scrollbars=no,resizable=yes,width=800,height=800');\
                w.focus();"
 href="#">
      <img src="../images/asteriskOperatorPanel.png"
           title="Asterisk operator panel - available over the intranet." />
    </a>]]></telephoneSystemOperatorPanelUrl>
  <smsUrl>http://asterisk.acme.com/sms.php?number=#number&amp;message=#message</smsUrl>
  <defaultLocale>DE</defaultLocale>
  <defaultTimeNotation>h24</defaultTimeNotation>
  <sendMail>
    <protocol>smtp</protocol>
    <host>localhost</host>
    <port>25</port>
    <debug>false</debug>
  </sendMail>
  <jiraBrowseBaseUrl>https://jira.acme.com/jira/browse/</jiraBrowseBaseUrl>
  <holidays>
    <holiday label="ACME 10th anniversary" year="2010" month="5" dayOfMonth="18"
             workingDay="false" />
    <!-- New holiday: -->
    <holiday label="Erster Mai" month="4" dayOfMonth="1" workingDay="false" />
    <holiday label="Dritter Oktober" month="9" dayOfMonth="3" workingDay="false" />
    <!-- Xmas Eve as half working day: -->
    <holiday id="XMAS_EVE" workingDay="true" workFraction="0.5" />
    <!-- New year eve as half working day: -->
    <holiday id="SYLVESTER" workingDay="true" workFraction="0.5" />
    <!-- Ignore shrove tuesday: -->
    <holiday id="SHROVE_TUESDAY" ignore="true" />
  </holidays>
  <contractTypes>
    <contractType value="COF" label="Contract of employment" />
    <contractType value="FC" label="Frame contract" />
    <contractType value="PC" label="Project contract" />
    <contractType value="SC" label="Service contract" />
  </contractTypes>
  <menuConfig>
    <sub-menu>
      <!-- Change the following menu's visibility: -->
      <menu-entry id="IMAGE_CROPPER" visible="true" />
      <menu-entry id="DOCUMENTATION" visible="false" />
    </sub-menu>
  </menuConfig>
  <!-- Use TaskTreePage instead of CalendarPage as default page (e. g. after login): -->
  <webConfig defaultPage="org.projectforge.web.task.TaskTreePage" />
</config>
Parameter Description
logoFile If you want to place your own compony logo file at the top of the navigation panel, you can specify the logo file. The path is relative to the <app-dir>/resources/images directory.
telephoneSystemUrl (#source and #target will be replaced by ProjectForge®):
http://asterisk.acme.com/originatecall.php ?source=#source&target=#target
telephoneSystemNumber For internal direct calls, the telephone system number will be removed if a number starts with it, e.g. 0123: 012345 -> 45.
telephoneSystemOperatorPanelUrl Here you can define any existing operating panel (see example config.xml above).
smsUrl ProjectForge® supports the sending of SMS if a servlet is available (#number and #message will be replaced by ProjectForge®):
http://asterisk.acme.com/sms.php ?number=#number&message=#message"
defaultLocale Default locale is used for formatting the week of year (which depends on the locale). All user's of ProjectForge® therefore will have the same definition of the weeks of year by using this locale application wide and not the user's locale.
defaultTimeNotation Default time notation used for user's without a personal time notation setting. The default time notation is 24-hours for German user languages (starting with "de") or 12-hours for all other languages. Supported values: "H12" and "H24".
excelDefaultPaperSize Default paper size for excel exports (default is DINA4). Supported values: "Letter"
jiraBrowseBaseUrl Base url for linking JIRA issues: https://jira.acme.com/jira/browse/PROJECTFORGE-222. The issue name UPPERCASE_LETTERS-### will be appended to this url. ProjectForge® parses the user's text input for [A-Z][A-Z0-9*]-[0-9]* and displays a list of detected JIRA-issues with a link beside the text area containing such issues. Example: https://jira.acme.com/jira/browse/ (don't forget closing '/').
If null, the no text input will be parsed and no JIRA link will be displayed.
holidays ProjectForges pre-defined holidays can be extended or declared as to be ignored (see example above in config.xml).
Pre-defined holidays (referenced by id) are:
NEW_YEAR, XMAS_EVE, FIRST_XMAS_DAY, SECOND_XMAS_DAY, SYLVESTER, SHROVE_MONDAY, SHROVE_TUESDAY, ASH_WEDNESDAY, PALM_SUNDAY, MAUNDY_THURSDAY, GOOD_FRIDAY, EASTER_SUNDAY, EASTER_MONDAY, ASCENSION, WHIT_SUNDAY, WHIT_MONDAY, CORPUS_CHRISTI.
If not given, only the pre-defined holidays will be used.
portletMode If configured (as true) then only the content html layer is shown (no menu, no logos, no headbar). This is use-ful for iFrame integration or integration in e. g. Liferay.
contractTypes If you're organizing contracts with ProjectForge you should configure your required contract types (s. examples in the config file above). If you delete or rename contract types (values) in your configuration any existing data base entry should be changed by you manually in the data base!
menuConfig You can configure menu entries as invisible by adding them here (s. above in the example). To add new menu entries, please use the plugin technology.
You can find a list of all id's of the ProjectForge menu entries here: MenuItemDef.html
The ImageCropper is de-activated at default because it's SSL (https) required for correct functioning (required by the Adobe Flash player).
Please note: a re-start of ProjectForge is required after any changes of menuConfig.
pluginMainClasses Here you can define further third party plug-ins or own plugins. The classes defined here must be derived from AbstractPlugin. Multiple entries should be separated by white chars and/or commas.
Please note: a re-start of ProjectForge is required after any changes of menuConfig.
cronExpressionNightlyJob Cron expression for starting the nightly job. The nightly job re-indexes the data base (full re-index) and starts the MEB polling job (imports all mails from mail account, if not already imported and MEB mail account is configured). Default value is (every night at 2 am UTC, s. CronSetup.java):
0 0 2 * * ?
See the documentation of the Quartz scheduling framework for further information.
cronExpressionMebPollingJob Cron expression for starting the meb polling job for getting unseen mails from the mail server (only if MEB mail account is configured). Default value is (every 10 minutes: 5, 15, 25, ..., s. CronSetup.java):
0 5/10 * * * ?
See the documentation of the Quartz scheduling framework for further information.

4.3 Customization

4.3.1 Logo ant title in pdf outputs

The file used for a logo in pdf outputs (for pdf export of time-sheets and monthly employee reports) is <app-dir>/resources/images/pdf-logo.png. At default, this file is not present. The logo is placed at the top right.
Under the configuration menu of the web application you can enter your organization name. This name will be used as headline for the pdf outputs.

4.4 Configuration settings (web interface)

Please go to this page for setting different parameters of ProjectForge® such as default time zone etc. You'll find the documentation there.

4.5 Using ttf fonts for PDF render engine

FOP is used as internal render engine. For enabling True Type Fonts please refer the FOP documentation.
1
2
java -cp build/fop.jar:lib/avalon-framework-4.2.0.jar:lib/commons-logging-1.0.4.jar:lib/commons-io-1.3.1.jar \
          org.apache.fop.fonts.apps.PFMReader <path>/<font>.pfm ttf<font>.xml

4.6 HTML formatted E-Mail templates

ProjectForge works with Groovy templates for generating e-mails (as notifications). You'll find the templates inside your web archive of the ProjectForge installation: WEB-INF/classes/mail/. You can modify any template of this directory if needed by simply copiing the file(s) you want to modify into your ProjectForge application dir, which is also the destination of config.xml:
 cp {PROJECTFORGE_WEB_DIR}/WEB-INF/classes/mail/templatefile {PROJECTFORGE_APP_DIR}/mail/
Afterwards you can edit this file. ProjectForge looks first in this ProjectForge app directory for loading templates and if not found it uses the resources path.
The templates are internationalized with the locale of the receiving user.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<html>
<html>
#INCLUDE{mail/mailHead.html}
<body>
#INCLUDE{mail/mailOpening.html}
<br />
Here you can place content (don't forget to use i18n keys for supporting internationalized e-mails).
...
<br />
<%= pf.getString("link") %><a href="${requestUrl}">${requestUrl}</a>
<br />
This is an example of using dynamic data (here a list of positions will be printed):
<table>
  <% for (position in order.positions) { %>
    <tr>
      <th><%= pf.getString("title") %></th>
      <td>${position.title}</td>
      ...
    </tr>
  <% } %>
</table>

#INCLUDE{mail/mailHistoryTable.html}

#INCLUDE{mail/mailClosing.html}
#INCLUDE{mail/mailFooter.html}
</body>
</html>
If you don't like html-formatted e-mails, you can simply remove all html tags (ignore the html suffix then).

4.7 Configuration of Mobile Enterprise Blogging (MEB)

ProjectForge supports two ways of receiving SMS: e-mail and/or servlet-call. You can use both or at least one of the two ways:
 File: config.xml
1
2
3
4
5
6
7
8
9
...
  <receiveSmsKey>kds8uijkqw6idg</receiveSmsKey>
  <mebMailAccount>
    <hostname>mail.acme.com</hostname>
    <username>pf-sms</username>
    <password>h7ishd6d</password>
    <protocol>imaps</protocol>
  </mebMailAccount>
  ...
ProjectForges ensures that messages will be imported only once.

4.7.1 E-Mail

ProjectForge can receive messages from a mail server (e. g. IMAP mail account). The e-mails will be parsed as key-value:
 File: Mail
1
2
3
date=xxx
sender=0123456789
msg=JIRA issue: fix the encoding bug
The date can have one of the two formats: either seconds since 01/01/70 or 201006121738 (yyyymmddhhMMss).
There are two cron jobs which are responsible for getting new messages:
  1. The first runs every 10 minutes (configurable in confix.xml) and get unseen (recent) mails from the mail server. If not already imported then a new entry is created.
  2. The second runs nightly and read all mails from the inbox and creates new entries for not yet imported messages. This job ensures that no mail is lost e. g. if another mail client has read the mails from this inbox. The first job ignores already seen mails.

4.7.2 Servlet-Call

You can implement a servlet call whenever your system receives an SMS:
https://pf.acme.com/secure/SMSReceiver?key=kds8uijkqw6idg&date=20101105171233&sender=01234567&msg=Hello...
The format of the values are the same as described above. The encoding should be UTF-8. The key is a communication key and should be configured in your config.xml (see above).
Please deploy the following php script on your Asterisk web server (many thanks to Thomas Koch for this great work):
 File: sms_receive.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/usr/bin/php
<?
SMS2ProjectForge

$SMS_DIR="/var/spool/asterisk/sms/mtrx/";
$PF_EMAIL="projectforge@change-to-your-domain.de";
$FROM="smsgateway@change-to-your-domain.de";
$PF_URL="https://change-to-your-domain.de/secure/SMSReceiver?key=<change-to-your-key>&date=%s&sender=%s&msg=%s";

function parseFile($file, $recipient) {

  if(!$file)
    return;
  if(is_file($file)) {
    $content = file($file);
  } else {
    print("$file is missing\n");
    return;
  }
  foreach($content as $line) {
    if(preg_match("/oa=(\d+)/", $line, $match)) {
#print("Absender " . $match[1] . "\n");
      $oa = $match[1];
    }
    if(preg_match("/ud=(.*)/", $line, $match)) {
#print("Text " . $match[1] . "\n");
      $text = $match[1];
    }
  }
  if($recipient == "pf") {
    $time = time();
#$mailtext = sprintf("date=%s\nsender=%s\nmsg=%s\n", time(), $oa, utf8_encode($text));
    $mailtext = sprintf("date=%s\nsender=%s\nmsg=%s\n", time(), $oa, $text);
    mail($PF_EMAIL"SMS", $mailtext, "From: smsgateway <$FROM>");
    $url = sprintf($PF_URL),
        $time,
        $oa,
        urlencode($text));
    $pig = fopen($url, "r");
    # XXX check answer!
    #$ret = stream_get_contents($pig);
  }
  return(1);
}

function getRecipient($file) {
  if(!$file)
    return;
  # pf.2010-05-04T16:46:01-11 
  if(preg_match("/(\w+)\.\d\d\d\d-\d\d-\d\d.\d\d:\d\d:\d\d-\d+/", $file, $match)) {
    return($match[1]);
  }
  return;
}

##
Main
#
$content = array();
if(is_dir($SMS_DIR)) {
  if($dh = opendir($SMS_DIR)) {
    while(($file = readdir($dh)) !== false) {
      if($file != "." && $file != "..") {
        if(parseFile($SMS_DIR . $file, getRecipient($file))) {
          unlink($SMS_DIR . $file);
        }
      }
    }
  }
}
?>

4.7.3 Easy creation of JIRA-Issues

 File: config.xml
1
2
3
4
5
6
7
8
9
10
11
12
...        
  <jiraConfig>
    <createIssueUrl>https://jira.acme.com/jira/secure/CreateIssueDetails!init.jspa</createIssueUrl>
    <issueTypes>
      <issueType label="Bug" value="1" />
      <issueType label="New functionality" value="2" />
      <issueType label="Task" value="3" />
      <issueType label="Improvement" value="4" />
      <issueType label="Claim" value="5" />
      <issueType label="Open Requirement" value="6" />
    </issueTypes>
  </jiraConfig>
First you have to define your URL for creating JIRA issues. Afterwards you should define your issue types. Every user has to define his favorite projects. This is necessary because JIRA does not provide a creation URL where you can choose your project and issue type and a pre-filled summary of the issue!

4.8 Asterisk connection: phone calls and texting with ProjectForge

4.8.1 Phone calls

If configured the users are able to initiate phone calls directly by clicking on a phone number of an address or by entering a name or a phone number in the direct phone call page.
Figure 1: You can initiate a phone call by simply clicking on a phone number of an address or by entering a name or number into the number field.
Please deploy the following php script on your Asterisk web server (many thanks to Thomas Koch for this great work):
 File: originatecall.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?
# originates call from ProjectForge
# 03/09 by t.koch@micromata.de

$USERNAME = "admin";
$PASSWORD = "secret";

function doCall($source, $target) {
  global $USERNAME, $PASSWORD;
  $socket = fsockopen("127.0.0.1","5038", $errno, $errstr, $timeout); 
  if(!$socket) {
    return(1);
  }
  fputs($socket, "Action: Login\r\n");                   
  fputs($socket, "UserName: $USERNAME\r\n");            
  fputs($socket, "Secret: $PASSWORD\r\n\r\n");         
  fputs($socket, sprintf("Action: Originate\r\nChannel: Local/%s@intern\r\nContext: intern\r\nExten: %s\r\nPriority: 1\r\nCallerid: %s\r\nTimeout: 8000\r\nVariable: var1=23|var2=24|var3=25\r\nActionID: ABC45678901234567890\r\n\r\nAction: Logoff\r\n\r\n", $source, $target, $source));
  return(0);

  if($debug) {
    while (!feof($socket)) {
      print(fread($socket, 8192));              
    }
    fclose($socket);                               
  }
}

$SOURCE = $_GET{source};
$TARGET = $_GET{target};

if(!is_numeric($SOURCE)) {
  print(2);
  exit(2);
}
if(!is_numeric($TARGET)) {
  print(3);
  exit(3);
}
if(doCall($SOURCE, $TARGET)) 
  print(1);
else
  print(0);
?>
Please check this servlet manually. It has to be available from your ProjectForge server. Then configure your servlet:
 File: config.xml
1
2
3
4
5
6
7
8
<config>
  ...
  <telephoneSystemUrl>http://asterisk.acme.priv/originatecall.php?source=#source&amp;target=#target</telephoneSystemUrl>
  <!-- If the system number is given, ProjectForge will shorten your phone numbers starting with -->
  <!-- this number automatically. This enables internal calls. -->
  <telephoneSystemNumber>0561316793</telephoneSystemNumber>
  ...
</config>
To use the full functionality of ProjectForge please configure the address book feature. Don't forget to configure your default country phone prefix in the configuration web page.

4.8.2 Texting

If configured the users are able to text by clicking on the SMS symbol of an address or by entering a name or a cell phone number.
Figure 2: You can send text messages by simply clicking on the SMS symbol of an address or by entering a name or cell phone number.
Please deploy the following php script on your Asterisk web server (many thanks to Thomas Koch for this great work):
 File: sms.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?
/*
   Texting with ProjectForge and Asterisk
   07.09.2009 by t.koch@micromata.de v1
*/


$NUMBER = $_REQUEST{number};
$MESSAGE = $_REQUEST{message};

if(!is_numeric($NUMBER)) {
  print("2\nwrong destination number");
  return(2);
}
if(!$MESSAGE) {
  print("1\nmissing message");
  return(1);
}
if(strlen($MESSAGE) > 160) {
  print("3\nmessage > 160");
  return(3);
}
$rand = rand(100000, 4000000);
usleep($rand);

XXX concurrent == maximum number of b channels
system(sprintf("/usr/sbin/smsq '--concurrent=8' '--spool-dir=/var/spool/asterisk/' '--motx-channel=DIALOGICDIVA/contr1/0193010' '--da=%s' '--motx-callerid=<callerid>' '--ud=%s' >/tmp/sms.$rand 2>/tmp/sms.$rand", $NUMBER, $MESSAGE));
print("0\nok");
?>
Please check this servlet manually. It has to be available from your ProjectForge server. Then configure your servlet:
 File: config.xml
1
2
3
4
5
<config>
  ...
  <smsUrl>http://asterisk.acme.priv/sms.php?number=#number&amp;message=#message</smsUrl>
  ...
</config>
To use the full functionality of ProjectForge please configure the address book feature. Don't forget to configure your default country phone prefix in the configuration web page.

4.8.3 PhoneLookupServlet

With the phone lookup servlet a telephony system (such as Asterix) may lookup incoming phone calls:
 File: config.xml
1
2
3
4
5
<config>
  ...
  <phoneLookupKey>3hjsd9j23kx73bn</phoneLookupKey>
  ...
</config>
The phone lookup key is needed for authorization. After configuring the key, the telephony system may call (from the ProjectForge's address book):
 https://projectforge.acme.com/phoneLookup?key=3hjsd9j23kx73bn&nr=05613167930
and the result of this call is:
 Reinhard, Kai; Micromata GmbH

4.9 business assessment / BWA

If you work with accounting records (DATEV) you may be want to have business assessments (BWA in German). The business assessments of DATEV constist of rows. Each row has a line number (no) and a title (for displaying). The accountRange defines which DATEV accounts matches the row. Please note, that a record is assigned to the first row found.
If the priorty of a row is not high, the row will not be shown in the short form of business assessments. The value defines row amounts which are calculated (see example below).
 File: config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<config>
  ...
  <accountingConfig debitorsAccountNumberRanges="10000-12999" creditorsAccountNumberRanges="70000-79999">
  <businessAssessment heading="BWA" overallPerformance="gesamtleistung"
     merchandisePurchase="matWareneinkauf" preliminaryResult="vorlaeufigesErgebnis">
    <!-- Please note: The calculations (if value is given) are done row by row, therefore you can't refer row amounts of successive rows. -->
    <rows>
      <!-- Empty row: -->
      <row no="1010" />
      <row no="1020" id="umsatzErloese" accountRange="4000-4799" priority="middle" title="Umsatzerlöse" indent="1" />
      <row no="1040" id="bestVerdg" priority="low" title="Best.Verdg. FE/UE" indent="1" />
      <row no="1045" id="aktEigenleistungen" priority="low" title="Akt.Eigenleistungen" indent="1" />
      <row no="1050" />
      <row no="1051" id="gesamtleistung" value="=umsatzErloese+bestVerdg+aktEigenleistungen" priority="high" title="Gesamtleistung" />
      <row no="1052" />
      <row no="1060" id="matWareneinkauf" accountRange="5700-5999" priority="high" title="Mat./Wareneinkauf" indent="1" />
      <row no="1070" />
      <row no="1080" id="rohertrag" value="=gesamtleistung+matWareneinkauf" priority="high" title="Rohertrag" />
      <row no="1081" />
      <row no="1090" id="soBetrErloese" accountRange="4830,4947" priority="low" title="So. betr. Erlöse" indent="1" />
      <row no="1091" />
      <row no="1092" id="betrieblRohertrag" value="=rohertrag+soBetrErloese" priority="middle" title="Betriebl. Rohertrag" />
      <row no="1093" />
      <row no="1094" id="kostenarten" priority="low" title="Kostenarten" />
      <row no="1100" id="personalkosten" accountRange="6000-6199" priority="high" title="Personalkosten" indent="1" />
      <row no="1120" id="raumkosten" accountRange="6310-6350" priority="low" title="Raumkosten" indent="1" />
      <row no="1140" id="betrieblSteuern" accountRange="7685" priority="low" title="Betriebl. Steuern" indent="1" />
      <row no="1150" id="versichBeitraege" accountRange="6400-6430" priority="low" title="Versich./Beiträge" indent="1" />
      <row no="1160" id="fremdleistungen" accountRange="7800" priority="low" title="Fremdleistungen" indent="1" />
      <row no="1180" id="kfzKosten" accountRange="6520-6599" priority="low" title="Kfz-Kosten (o. St.)" indent="1" />
      <row no="1200" id="werbeReisekosten" accountRange="6600-6699" priority="low" title="Werbe-/Reisekosten" indent="1" />
      <row no="1220" id="kostenWarenabgabe" accountRange="6740" priority="low" title="Kosten Warenabgabe" indent="1" />
      <row no="1240" id="abschreibungen" accountRange="6200-6299" priority="low" title="Abschreibungen" indent="1" />
      <row no="1250" id="reparaturInstandh" accountRange="6470-6490" priority="low" title="Reparatur/Instandh." indent="1" />
      <row no="1260" id="sonstigeKosten" accountRange="6300,6800-6855" priority="low" title="sonstige Kosten" />
      <row no="1280" id="gesamtKosten"
        value="=personalkosten+raumkosten+betrieblSteuern+versichBeitraege+fremdleistungen+kfzKosten+werbeReisekosten+kostenWarenabgabe+abschreibungen+reparaturInstandh+sonstigeKosten"
        priority="high" title="Gesamtkosten" />
      <row no="1290" />
      <row no="1300" id="betriebsErgebnis" value="=betrieblRohertrag+gesamtKosten" priority="high" title="Betriebsergebnis" />
      <row no="1301" />
      <row no="1310" id="zinsaufwand" accountRange="7305,7310" priority="low" indent="2" title="Zinsaufwand" />
      <row no="1312" id="sonstNeutrAufw" accountRange="6392,6895,6960" priority="low" indent="2" title="Sonst. neutr. Aufw." />
      <row no="1320" id="neutralerAufwand" value="=zinsaufwand+sonstNeutrAufw" priority="low" indent="1" title="Neutraler Aufwand" />
      <row no="1321" />
      <row no="1322" id="zinsertraege" accountRange="7100,7110" priority="low" indent="2" title="Zinserträge" />
      <row no="1323" id="sonstNeutrErtr" accountRange="4845,4855,4925,4930,4937,4960,4970,4975" priority="low" indent="2" title="Sonst. neutr. Ertr" />
      <row no="1324" id="verrKalkKosten" priority="low" indent="2" title="Verr. kalk. Kosten" />
      <row no="1330" id="neutralerErtrag" value="=zinsertraege+sonstNeutrErtr+verrKalkKosten" priority="low" indent="1" title="Neutraler Ertrag" />
      <row no="1331" />
      <row no="1340" id="kontenklUnbesetzt" priority="low" indent="1" title="Kontenkl. unbesetzt" />
      <row no="1342" />
      <row no="1345" id="ergebnisVorSteuern" value="=betriebsErgebnis+neutralerAufwand+neutralerErtrag" priority="high" title="Ergebnis vor Steuern" />
      <row no="1350" />
      <row no="1355" id="steuernEinkUErtr" accountRange="7600-7640" priority="low" indent="1" title="Steuern Eink.u.Ertr" />
      <row no="1360" />
      <row no="1380" id="vorlaeufigesErgebnis" value="=ergebnisVorSteuern+steuernEinkUErtr" priority="high" title="Vorläufiges Ergebnis" />
      <row no="1390" />
      <row no="" id="erfolgsquote" priority="high" title="Erfolgsquote" scale="0" unit="%">
        <value>
          if (gesamtleistung != 0.0) {
          return betriebsErgebnis * 100 / gesamtleistung;
          } else {
          return 0.0;
          }
        </value>
      </row>
      <row no="" id="relativePerformance" priority="high" title="relative Performance" scale="3" unit="-">
        <value>
          if (gesamtleistung != 0.0) {
          return vorlaeufigesErgebnis / gesamtleistung;
          } else {
          return 0.0;
          }
        </value>
      </row>
    </rows>
  </businessAssessment>
  </accountingConfig>
  ...
</config>

4.10 SecurityConfig

4.10.1 Secure passwords

Every password is stored in the database as SHA256 hashed password. For reducing brute force attacks several security mechanism are implemented.

4.10.1.1 Protection against brute force attacks

If the user login failed (via web page or rest service) a penalty time is given for usernames and IP addresses. For every failed login for an username the penalty time is increased by one second before the next try of an username/password combination for that username is allowed.
The same mechanism is used for failed login failures from an IP address (one second penalty per thousand failed logins).
Please refer the source code for more information.

4.10.1.2 Salted passwords

Since version 5.3 of ProjectForge® salted passwords are used. This means, that every password is first concatenated with an salt value (random string per user) and then hashed. Therefore so called rainbow tables are useless for attacking passwords. After migrating to version 5.3 every password is salted after login of the user or if the user is changing his password.

4.10.1.3 Salted passwords with pepper

Since version 5.3 of ProjectForge® the administrator is able to configure a pepper string in the config.xml. Before hashing a password the pepper string is concatenated to the salt and password. Therefore no brute force attack is possible if an attacker has access to the database dump etc.
Please configure the pepper string like this:
 File: config.xml
1
2
3
4
5
6
7
<config>
  ...
  <securityConfig>
    <passwordPepper>Sa9nohzoTeeth1ee</passwordPepper>
  </securityConfig>
  ...
</config>
All passwords are automatically updated after any login of an user (if no pepper and/or salt was yet used for the user's password) or after any password change.

Hint

Please do not change the pepper value a second time! If you do so, no login will be possible for all user's having already a password hashed with the old pepper string!

4.11 LDAP

4.11.1 Requirements

The LDAP must support the following additional schemas (example of slapd.conf of OpenLDAP):
1
2
include /sw/etc/openldap/schema/cosine.schema
include /sw/etc/openldap/schema/inetorgperson.schema
eingefügt werden.

4.11.2 Configuration

 File: config.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<config>
  ...
  <ldapConfig>
    <server>ldap://ldap.acme.priv</server>
    <baseDN>dc=acme,dc=com</baseDN>
    <managerUser>cn=admin</managerUser>
    <managerPassword>secret</managerPassword>
    <port>636</port>
    <sslCertificateFile>/Users/kai/ProjectForge/ldap.crt</sslCertificateFile>
    <groupBase>ou=groups</groupBase>
    <userBase>ou=users</userBase>
    <authentication>simple</authentication>
  </ldapConfig>
  ...
</config>
The groupBase setting is only needed in master mode. The managerUser is not needed in simple slave mode. For further information see below.

4.11.3 Local (admin) users

Please login by using the stay-logged-in checkbox on the login screen as administrator (no LDAP should be configured). Restart ProjectForge with LDAP configured and use the same browser. You should be logged-in. Please go to the user list and select option local user for every user who should be authenticated against ProjectForge (instead of LDAP) and save them. Now the local users may log-in without LDAP credentials. This is especially use-ful for administrator users of ProjectForge.

4.11.4 LDAP over SSL

openssl s_client -showcerts -connect ldap.acme.priv:636 > ldap.pem Copy the lines including -----BEGIN CERTIFICATE----- until -----END CERTIFICATE----- (including) to a file called ldap.cert. Now you can configure the certificate file in config.xml or you can import the certificate to your java keystore. The first solution is independent of your JAVA version and is recommended first.

4.11.4.1 Configure certificate in config.xml

Add the certificate to the config.xml as attribute keystoreFile .
 File: config.xml
1
2
3
4
5
6
7
8
9
<config>
  ...
  <ldapConfig>
    <sslCertificateFile>/Users/kai/ProjectForge/ldap.crt</sslCertificateFile>
    <server>ldaps://ldap.acme.priv</server>
    ...
  </ldapConfig>
  ...
</config>

4.11.4.2 Import the certificate to your keystore

You can import your certificate in the keystore of your Java vm. Don't forget to import your certificate again if you'll change the Java vm (e. g. for an update). <JAVA_HOME>/bin/keytool -import -v -trustcacerts -alias ldap -file ldap.cert -keystore <JAVA_HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit

4.11.5 ProjectForge as LDAP master

The LDAP master mode is the most tested mode of ProjectForge and is used in production mode at the ProjectForge developer's company. In this mode, ProjectForge needs a LDAP user with write access to groups and users. The ProjectForge user's will be synchronized in LDAP. If there is any conflict between LDAP and ProjectForge, the ProjectForge settings are used. The configuration of this mode is simple:
 File: config.xml
1
2
3
4
5
6
7
<config>
  ...
  <loginHandlerClass>org.projectforge.ldap.LdapMasterLoginHandler</loginHandlerClass>
  <ldapConfig>
    ...
  </ldapConfig>
</config>
  1. This LDAP login handler has read-write access to the LDAP server and acts as master of the user and group data. All changes of ProjectForge's users and groups will be written through.
  2. Any change of the LDAP server will be ignored and may be overwritten by ProjectForge.
  3. Passwords
    After each successful login-in at ProjectForge (via LoginForm) ProjectForges tries to authenticate the user with the given username/password credentials at LDAP. If the LDAP authentication fails ProjectForge changes the password with the actual password of the user (given in the LoginForm).
  4. Deactivated users
    Deactivated users will be moved to an sub userbase called "deactivated". The e-mail will be invalidated and the password will be deleted. Deleted and deactivated users are removed from any LDAP group. After reactivating the user, the password has to be reset if the user logins the next time via LoginForm.
  5. Deleted Users
    Deleted users will not be synchronized and removed in LDAP if exist.
  6. Stay-logged-in
    The stay-logged-in mechanism will be ignored if the LDAP password (or Samba password) of the user isn't set yet (is null). Any existing LDAP password doesn't interrupt the normal stay-logged-in mechanism. After login of those users the stay-logged-in mechanism works again for further log-ins.
  7. New users
    New users (created with ProjectForge's UserEditPage) will be created first without password in the LDAP system directly. Such users need to log-in first at ProjectForge, otherwise their LDAP passwords aren't set (no log-in at any other system connecting to the LDAP is possible until the first log-in at ProjectForge).
  8. Modifiing fields in LDAP
    ProjectForge does only modify supported fields of known LDAP users. If any modification is done in LDAP of fields and users/groups known by ProjectForge they will be overwritten by ProjectForge during the next synchronization run. If any modification in other fields of LDAP users are done, the should be left untouched by ProjectForge.
  9. Synchronization
    After any modification of any ProjectForge user or group, the synchronization is started for all LDAP users and groups. If no modification is done, the synchronization is done approximately hourly, but only if any user activity is detected in ProjectForge. You can force a synchronization by refreshing all caches (including the UserGroupCache) in the system web page or by restarting ProjectForge.
  10. Groups and assigned users
    Users will be added as uniqueMember entries in the LDAP groups if also assigned in ProjectForge to the same ProjectForge group.

4.11.5.1 LDAP entries

See figures 3 and 4 for detailled information of how does ProjectForge stores and expect LDAP fields and object classes.
Figure 3: ProjectForge uses the fields and object classes shown in this figure for users. The object class posixAccount with the fields uidNumber, gidNumber, homeDirectory and loginShell are only used and managed if configured (see 4.11.5.2 ). The field employeeNumber is used by ProjectForge for storing the primary key of the ProjectForge user entry in LDAP (for a better syncronization). So the renaming of user names should work.
Figure 4: ProjectForge uses the fields and object classes shown in this figure for groups. The field businessCategory is used by ProjectForge for storing the primary key of the ProjectForge group entry in LDAP (for a better syncronization). So the renaming of group names should work.

4.11.5.2 Managing POSIX accounts

ProjectForge supports the management of POSIX accounts with the data uidNumber, gidNumber, homeDirectory, and loginShell. The configuration looks like:
 File: config.xml
1
2
3
4
5
6
7
8
<config>
  <ldapConfig>
    ...
    <posixAccounts defaultGidNumber="515"
                   homeDirectoryPrefix="/home/"
                   defaultLoginShell="/bin/bash" />
  </ldapConfig>
</config>
You can adminster the POSIX account data in the UserEditPage after configuring the config.xml like the above example. Pleaser refer the tool-tips for further information:
Figure 5: ProjectForge is able to manage POSIX accounts in LDAP master mode.

4.11.6 Managing Samba accounts

 File: config.xml
1
2
3
4
5
6
<config>
  <ldapConfig>
    ...
    <sambaAccounts sambaSIDPrefix="S-1-5-21-1654374101-3569970681-3921896634" defaultSambaPrimaryGroupSID="515" />
  </ldapConfig>
</config>
Figure 6: ProjectForge is able to manage POSIX and Samba accounts in LDAP master mode.

4.11.7 ProjectForge as LDAP client

This LDAP login handler acts as a LDAP slave, meaning, that LDAP will be accessed in read-only mode. There are 3 modes available: simple, users and users-groups. The configuration of this mode is simple:
 File: config.xml
1
2
3
4
5
6
7
<config>
  ...
  <loginHandlerClass>org.projectforge.ldap.LdapSlaveLoginHandler</loginHandlerClass>
  <ldapConfig>
    ...
  </ldapConfig>
</config>

4.11.7.1 Simple mode

The simple mode is assumed if no ldap managerUser is given in the config.xml.

4.11.7.2 Users mode

The normal user mode is assumed if a LDAP managerUser is given in the config.xml.

4.11.7.3 Users-groups mode

This mode is not yet implemented, the users-mode is used instead.

5 Maintenance

5.1 Updating by simple clicks

ProjectForge provides a very convenient method for updating to new versions (improved again since version 3.5.2). Please call the menu "Update system".
Figure 7: ProjectForge provides a convenient method for system updates. The data base scheme will be updated and the data base will be migrated automatically by scripts.
This dialog is called automatically on start-up if a new ProjectForge-Release detects something to up-date. Please select the check-box "Show old updates" to see, that your ProjectForge is completely up-to-date. You can update from any older version.

Hint

If your ProjectForge installation is running with the schema-update option true then most of the updates below are done by the data-base layer (Hibernate). So you'll find no update entries in the table t_database_update. It's highly recommended to set schema-update option to false in production mode (please use this option only for the first start-up).

Hint

ProjectForge checks only the newest update entries (sorted by date) of every plugin and the ProjectForge's core for update. Any older update entries aren't tested. If you want tho check older update entries, please check them via SystemUpdatePage.

5.2 Re-indexing the database

Should be done after setup: Use the adminstration menu.

5.3 Starting ProjectForge from command-line (without Tomcat)

You may start ProjectForge from command-line with the embedded Jetty web-server. No Tomcat is needed for this scenario. Please use the script projectforge-webserver.sh. The command-line options are:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
usage: projectforge-webserver [-b <boolean>] [-h] [-ja <string>] [-jc
       <string>] [-jp <string>] [-ju <string>] [-l <string>] [-p <port>]
       [-u <boolean>] [-v <boolean>] [-w <war>]
 -b,--launch-browser <boolean>     If true then the browser is launched
                                   automatically after start-up, default
                                   is true.
 -h,--help                         Print this help.
 -ja,--jdbc-url <string>           If not given then
                                   'jdbc:hsqldb:<location>/database/Projec
                                   tForgeDB'is used.
 -jc,--jdbc-driver <string>        If not given then
                                   'org.hsqldb.jdbcDriver.
 -jp,--jdbc-password <string>      If not given then no password is
                                   assumed.
 -ju,--jdbc-user <string>          If not given then 'sa'is used.
 -l,--location <string>            The home directory of ProjectForge,
                                   default is the current directory.
 -p,--port <port>                  The http port, default is 8080.
 -u,--schema-update <boolean>      If true then the schema update of
                                   Hibernate is enabled (for development
                                   mode only), default is false.
 -v,--development-mode <boolean>   If true, ProjectForge will be started
                                   in development mode.
 -w,--war <war>                    war file, default is ProjectForge.war

Hint

Please note: https isn't yet supported by this command-line tool. Please request this feature if required.

5.4 Restart/Shutdown

Please use the containers shutdown mechanism (e.g. catalina.sh stop ). During the undeployment of the ProjectForge®-War for example the user preferences cache will be flushed to the database, otherwise user preferences will may be lost.

5.5 Analysing tools

Useful commandes are
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
projectforge@vprojectforge:~$ jps
19533 Bootstrap
2261 Jps
projectforge@vprojectforge:~$ jstack 19533
2008-02-14 09:58:28
Full thread dump Java HotSpot(TM) 64-Bit Server VM (1.6.0_03-b05 mixed mode):

"Attach Listener" daemon prio=10 tid=0x00002aaaf4a6e800 nid=0x8fa waiting on condition [0x0000000000000000..0x0000000000000000]
   java.lang.Thread.State: RUNNABLE

"http-8443-10" daemon prio=10 tid=0x00002aaaf4a94800 nid=0x716c in Object.wait() [0x0000000041f47000..0x0000000041f47e40]
   java.lang.Thread.State: WAITING (on object monitor)
  at java.lang.Object.wait(Native Method)
  - waiting on <0x00002aaaee262530> (a org.apache.tomcat.util.net.JIoEndpoint$Worker)
  at java.lang.Object.wait(Object.java:485)
  at org.apache.tomcat.util.net.JIoEndpoint$Worker.await(JIoEndpoint.java:416)
  ...

5.6 XML-backup and restore and data-base migration

ProjectForge supports the import and export of its whole data-base as XML. It's independent from the data-base (Hypersonic, PostgreSQL, MySQL, Oracle etc.). You can choose this method to migrate your data-base from one data-base to any other data-base supported by ProjectForge.

5.6.1 Export

It's possible to export an XML-Dump from your data-base using the system administration dialogue (web). This backup contains all data of ProjectForge in one zipped xml file.

5.6.2 Import

  1. First you need a fresh data-base (without any tables and data).
  2. Afterwards start ProjectForge with the connection data to your new data-base.
  3. Upload the XML or zipped XML file inside the setup-page (which is shown automatically in your web-browser for empty data-bases). Leave any other input fields such as password etc. untouched.
  4. Press the upload button.
  5. Watch the results in the log messages. ProjectForge will verify each single entry by comparing each object of the XML file with the imported data-base objects (each single field of every object is compared.) Any inconsistency or difference is shown in the log file.
  6. Now you can login into ProjectForge.

5.6.3 Limitations

The limitation is the web servers memory. It's planned to support very large ProjectForge data-bases using different xml files. Please request this feature e. g. inside the help forum if needed. For migration without changing the data-base vendor the data-base specific dump and restore mechanism are recommended for large data-bases.

Hint

Please note: After an import of a dump file into a new ProjectForge installation all primary keys are changed! ProjectForge ensures the integrity of all data including the history entries.

5.7 Backup

All datasets of ProjectForge® will be stored in the underlaying database (e. g. PostgreSQL).
You should install an Unix cron script making frequently a backup of the database. A dump of containing table entries as SQL statements for PostgreSQL is possible by using:
 pg_dump -D -U projectforge -f pf_dump_`date '+%Y-%m-%d_%H-%M'`.sql

5.8 Restoring a backup

 psql -q -f projectforge_2008-05-12_02-00.sql -U postgres projectforge 2>&1 > log.txt
For further details concerning dropping and creating a new data base, see 3.3.3 .
Don't forget to create indices (see 3.4 )!

Hint

If you want to use productive data in your develepment system for testing, it's recommended to set all e-mail addresses of the users to your developers e-mail. Also all passwords can be easily set to test123 if you user folliwing sql statement in your test database (not productive!):
 update t_pf_user SET password='SHA{BC871652288E56E306CFA093BEFC3FFCD0ED8872}', email='m.developer@acme.com';

5.9 Automatical backup

5.9.1 Backup script

Install crontab entry as user projectforge on your ProjectForge® server starting the following script:
 File: pforgebackup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

PGSQL_DIR=/usr/bin
BACKUPDIR=/home/projectforge/backup
BASENAME=projectforge PASSWD=...

echo Starting backup of ProjectForge ...
BACKUPFILE=$BACKUPDIR/${BASENAME}_`date '+%Y-%m-%d_%H-%M'`.sql

echo Using filename $BACKUPFILE ...
echo Exporting ...
$PGSQL_DIR/pg_dump -D -U projectforge -W $PASSWD -f $BACKUPFILE

echo Zipping backupfile ...
gzip $BACKUPFILE

# For using scp for remote backup:
#scp $BACKUPFILE <user>@backup.mydomain:backup/

echo Deleting backups older than 14 days
find $BACKUPDIR -mtime +14 | xargs rm 

echo Backup of ProjectForge finished.
For allowing pg_dump without prompting password (if set), you can add the following line to:
 File: pg_hba.conf
 local projectforge projectforge ident sameuser

5.9.2 Adding crontab

Adding following entry to the Unix crontab:
1
2
# run every day at 2:00 am
0 2 * * * /home/projectforge/bin/pforgebackup.sh

5.9.3 Remote backup

For remote backup via scp you need to use key authorization:
  1. Generate keys (using empty password) ssh-keygen
  2. Copy your public key, e. g. identity.pub to your backup server.
  3. Add this key on the backup server to the authorized keys.

5.9.4 Polling remote backup

For security reasons it's also possible to get the backup files from the ProjectForge® server with a cronjob starting e. g. one hour later:
 File: pforgePollBackup.sh
1
2
3
4
5
6
7
#!/bin/bash

SERVER=projectforge.mydomain
DIR=/home/projectforge/backup
REMOTE_DIR=backup REMOTE_USER=projectforge

rsync -avz -e "ssh -P" -C $REMOTE_USER@$SERVER:$REMOTE_DIR $DIR
In that case you have to generate ssh key on your backup server and to add it to the authorized keys on your ProjectForge® server.
Add the following entry to your crontab on the backup server: # run every day at 3:00 am 0 3 * * * /home/projectforge/bin/pforgePollBackup.sh

5.10 Monitoring

You may monitor the login page with your monitoring tool (such as Nagios). If ProjectForge® is up and running and is full available the following comment is included in the login page:
 <-- ProjectForge is alive-->
If ProjectForge® isn't full available the following html comment is embedded:
 <-- ProjectForge is not full available (perhaps in maintenance mode or in start-up phase). -->

5.11 Scheduler

5.11.1 Data base search index

The re-index job starts every night at 4 AM (UTC). If an error occurs an e-mail is sent to the admin e-mail addresses configured via web administration. If not configured, no e-mail is sent.

5.12 Spaces

5.12.1 Store

All spaces are stored in the gwiki folder of your ProjectForge home directory. For example: ~/ProjectForge/gwiki/<SPACENAME>/
Spaces are named by their ID representing the database spaces object.

5.12.2 Deletion or historization of spaces

If a spaces is marked for deletion, the corresponding wiki files, stored on filesystem, will not been deleted. You are required to handle the history- and backup management by your own, for example by renaming or moving corresponding spaces. If a deleted space will be recovered by it's history, the space needs his physical wiki files.

5.13 Uninstalling ProjectForge

You only need to delete the Exe-File (or war-file if deployed as war) and the working directory you've chosen / configured. If you're not sure, where ProjectForge's working directory is located, please restart ProjectForge and see for the directory in the log output or configuration tab of the standalone version.

Hint

Please note: If you delete the working directory, all your data base entries are deleted as well!

6 Webserver Tomcat

6.1 server.xml

 File: doc/resources/tomcat/server.xml
1
2
3
4
5
6
7
8
9
10
11
<Server port="8005" shutdown="SHUTDOWN">    
  <Service name="Catalina">
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS"
               keystoreFile="/home/projectforge/apache-tomcat-6.0.14/tomcat-localhost.keystore"
               compression="on" compressionMinSize="2048" noCompressionUserAgents="gozilla, traviata"
               compressableMimeType="text/css,text/html,text/javascript,text/plain,text/xml"
               URIEncoding="UTF-8" />
  </Service>
</Server>

6.2 context.xml

 File: $CATALINA_BASE/conf/[enginename]/[hostname]/ProjectForge.xml
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<Context path="" reloadable="false" debug="0" docBase="webapps" cookies="false">
  <Resource name="ProjectForgeDS" type="javax.sql.DataSource" auth="Container" driverClassName="org.postgresql.Driver"
    url="jdbc:postgresql://localhost:5432/projectforge" maxActive="100" maxIdle="30" maxWait="10000" username="projectforge" password="" />
  <Parameter name="base.dir" value="${user.home}/ProjectForge" override="false" />
  <Parameter name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" override="false" />
  <Parameter name="hibernate.schemaUpdate" value="false" override="false" />
  <Parameter name="development" value="true" override="false" />
</Context>

6.3 Increase memory and environment for Tomcat

 File: apache-tomcat/bin/setenv.sh
 export JAVA_OPTS="-Duser.timezone=UTC -Xmx512m -XX:PermSize=96m -XX:MaxPermSize=192m -Djava.awt.headless=true"

6.4 Generating SSL key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
keytool -genkey -keystore tomcat-localhost.keystore -alias tomcat -keyalg RSA -keysize 1024 -keypass changeit -storepass changeit
Wie lautet Ihr Vor- und Nachname?
 [Unknown]:  localhost
Wie lautet der Name Ihrer organisatorischen Einheit?
 [Unknown]:
Wie lautet der Name Ihrer Organisation?
 [Unknown]:
Wie lautet der Name Ihrer Stadt oder Gemeinde?
 [Unknown]:
Wie lautet der Name Ihres Bundeslandes oder Ihrer Provinz?
 [Unknown]:
Wie lautet der Landescode (zwei Buchstaben) für diese Einheit?
 [Unknown]:
Ist CN=localhost, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown richtig?
 [Nein]:  Ja

6.5 Webapp Lambda-Probe

Sehr nützliches Tool zur Überwachung von Speicher, Connections, Use-age etc. ist www.lambdaprobe.org .
 File: conf/tomcat-users.xml
1
2
3
4
5
6
7
8
9
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="manager"/>
  <role rolename="tomcat"/>
  <role rolename="poweruser"/>
  <role rolename="poweruserplus"/>
  <role rolename="probeuser"/> <!-- Read-only access -->
  <user username="probeuser" password="<password>" roles="probeuser"/>
</tomcat-users>
 File: bin/setenv.sh
1
2
# Needed by probe: -Dcom.sun.management.jmxremote
export JAVA_OPTS="-Duser.timezone=UTC -XX:PermSize=96m -XX:MaxPermSize=192m -Djava.awt.headless=true -Dcom.sun.management.jmxremote"
 File: conf/server.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<Server port="8005" shutdown="SHUTDOWN">    
  <GlobalNamingResources>
    <!-- Used by Manager webapp -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
       description="User database that can be updated and saved"
           factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
          pathname="conf/tomcat-users.xml" />
  </GlobalNamingResources>
  ...
        <Engine name="Catalina" defaultHost="www.projectforge.org">
           <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
             resourceName="UserDatabase" />
             ...
        </Engine>
    </Service>
</Server>

7 Plugins

Some plugins which are part of the ProjectForge web app but not automatically enabled are described here.

7.1 Liquidity planning

7.1.1 Description

This plugins supports the cash flow forecast for a very easy to use liquidity planning. Please refer the UserGuide for further information.

7.1.2 Configuration

Simply activate this plugin in the config.xml:
 File: <app-home>/config.xml
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<config>
  ...
  <pluginMainClasses>
    ...
    org.projectforge.plugins.liquidityplanning.LiquidityPlanningPlugin
  </pluginMainClasses>

7.2 Software license management

7.2.1 Description

In most companies you've to deal with lots of Software and license keys. This plugin allows administrators and users to organize license keys: Planned features are:
Figure 8: A company may manage its software licenses with this ProjectForge plugin.

7.2.2 Configuration

Simply activate this plugin in the config.xml:
 File: <app-home>/config.xml
1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<config>
  ...
  <pluginMainClasses>
    ...
    org.projectforge.plugins.licensemanagement.LicenseManagementPlugin
  </pluginMainClasses>

8 FAQ

8.1 Reset passwords

As an administration user you can reset the user's passwords. If you've lost the administrator's password you can reset the password by updating the database entry like
 update t_pf_user SET password='SHA{2F1E969683DE272AC96D5AA6033E93A8CB2F283F}' where username='admin';
This encrypted passwords represents 'manage'. See the log file for encrypted passwords after login failures, if you want to set another password via sql. For HypersonicSQL shutdown the server and edit the ProjectForgeDB.script file like this:
 INSERT INTO T_PF_USER VALUES(1, ..., 'SHA{2F1E969683DE272AC96D5AA6033E93A8CB2F283F}',...,'admin')

8.2 Hypersonic: Could not insert entries to the data base.

If the user can't add new entries (contracts, Gantt charts, MEB entries etc.) to the data-base Hypersonic, please have a look in your ProjectForgeDB.script file. All create-table-statements should have the following entry for the primary key (pk):
CREATE MEMORY TABLE T_...(PK INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY, ...
If the script doesn't contain GENERATED BY DEFAULT ... , please stop your ProjectForge system and edit the script file and restart ProjectForge.