Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
38 changes: 38 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# TimeTrackerAPI — environment configuration template.
#
# Copy to `.env` and fill in real values for local development. In production,
# set these via your process manager (systemd, pm2) or container runtime —
# do not commit a populated `.env`.
#
# `.env` is gitignored; this `.env.example` file is the canonical reference.

# ---- HTTP server ----

# Port the API listens on. Use a non-privileged port (>1024) so the process
# can run as a non-root user. Front the service with nginx/Caddy if you
# need to terminate on :443.
PORT=3000

# Address to bind. 0.0.0.0 listens on all interfaces (container default).
# Use 127.0.0.1 to restrict to localhost.
HOST=0.0.0.0

# Comma-separated list of allowed CORS origins. Leave unset to disable
# cross-origin requests entirely (recommended unless your frontend lives
# on a different host).
#
# Examples:
# CORS_ORIGIN=http://localhost:4200
# CORS_ORIGIN=https://app.example.com,https://admin.example.com
CORS_ORIGIN=

# ---- PostgreSQL ----

DB_HOST=localhost
DB_PORT=5432
DB_NAME=timetracker
DB_USER=timetracker

# Set a real password here. The configured database user must have access
# to the `dbo` schema. Do NOT commit a populated `.env`.
DB_PASSWORD=changeme
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Dependencies
node_modules/

# Logs
npm-debug.log
yarn-debug.log
yarn-error.log
*.log

# Environment files (secrets live here — do not commit)
.env
.env.*
!.env.example

# Build / coverage artifacts
dist/
build/
coverage/
.nyc_output/

# Editor / OS noise
.DS_Store
.idea/
.vscode/
*.swp
*.swo
150 changes: 150 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

This License applies to any work or other work whose creator
has received a notification (which may be in the form of any
written or electronic communication) from the Licensor
designating the work as licensed under this License.

GRANT OF COPYRIGHT LICENSE

Subject to the terms and conditions of this License, each
Licensor hereby grants to you a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare derivative works of,
publicly display, publicly perform, sublicense, and distribute
the Work and such derivative works in Source or Object form.

GRANT OF PATENT LICENSE

Subject to the terms and conditions of this License, each
Licensor hereby grants to you a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable
(except as set forth in this Section) patent license to make,
have made, use, offer to sell, sell, import, and otherwise
transfer the Work, where such license applies only to those
patent claims licensable by such Licensor that are necessarily
infringed by the Work alone or by combination of the Work
with one or more other works to which such License applies.

REDISTRIBUTION

You may reproduce and distribute copies of the Work or
derivative works thereof in Source or Object form, with or
without modifications, provided that you meet the following
conditions:

You must give any other recipients of the Work or
derivative works thereof a copy of this License; and

You must cause any modified files to be prominent so that
recipients know that they have been modified; and

You must retain, in the Source form of any file that you
distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the User Modifications.

If the Work (or a derivative work thereof) incorporates a
"NOTICE" text file as part of its distribution, then any
NOTICE text file distributed as part of the Work or
derivative works thereof must contain one or more copies of
the NOTICE text file received from the Work or derivative
works thereof, excluding those notices that do not pertain
to any part of the User Modifications, and if the Work
was not received in an Object form, any such NOTICE text
file must be preserved in the Object form of the Work or
derivative works thereof.

You may add your own copyright statement to your modifications
and provide additional or different attribution notices with
any of your modifications, provided that you do not
modify, remove, or replace any of the attribution notices
of the Work in the Source form of any file that you
distribute, and you do not perform any

Submission of contributions unless you explicitly state
otherwise, any contribution intentionally submitted for
inclusion in the Work by you to the Licensor shall be
under the terms and conditions of this License, and any
contributions submitted under this Section shall
govern the use of the Work by all recipients of the
Work.

SUBMISSION OF CONTRIBUTIONS

Unless you explicitly state otherwise, any contribution
intentionally submitted for inclusion in the Work by you
to the Licensor shall be under the terms and conditions of
this License, and any contributions submitted under this
Section shall govern the use of the Work by all recipients
of the Work.

TERMINATION

This License and the rights granted by this License shall
terminate automatically if you fail to comply with any
of the terms and conditions of this License, and
continue to use the Work or any of its derivative works
as specified in this Section.

PATENTS

Licensors make no warranty as to the validity of the
patent claims being granted under this License. The
provided license is for the patent claims licensable by
such Licensor that are necessarily infringed by the Work
alone or by combination of the Work with one or more other
works to which such License applies.

LIMITATION OF LIABILITY

In no event and under no legal theory, whether in
tort (including negligence), contract, or otherwise,
shall any Licensor be liable to you for damages,
including any direct, indirect, special, incidental,
or consequential damages of any character arising
as a result of any Warranty or any claim under any
of the Warranty Sections, or any liability arising
from any event or action pursuant to any of the
Warranty Sections, unless such damage or liability
is required by law and agreed to in writing.

ACCEPTING WARRANTY OR HELP

If you decide to accept warranty or help, it will be
done only in accordance with the terms and conditions
of the writer of such warranty or help.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file language. We also recommend that
a file or class name, and, if used for a source code file, the
name of the interface or class that is equivalent to a
"interface" in languages like C#, etc., is made known to
the bundle. The applicable Apache License template is
available online at http://www.apache.org/licenses/LICENSE-2.0.txt.

Copyright 2026 Aaron K. Clark

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions
and limitations under the License.
97 changes: 74 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,96 @@
# TimeTrackerAPI

OpenSource re-write of Atbash Services' TimeTrackerAPI on NodeJS / PostgreSQL
Open-source rewrite of Atbash Services' TimeTrackerAPI on **Node.js + PostgreSQL**.

Working example at [http://node.timetrackerapi.com](http://node.timetrackerapi.com)
Working example at [node.timetrackerapi.com](http://node.timetrackerapi.com).

Endpoints Completed
* GET /v1/customer/#
* GET /v1/customer/bycompany/#
## Endpoints

- `GET /v1/customer/:id`
- `GET /v1/customer/bycompany/:id`

Every request must include the API key in the `authKey` HTTP header.

**Make sure to use the http header 'authKey' with the ApiKey**
![example image](https://github.com/CryptoJones/TimeTrackerAPI/blob/master/setup/postman_example.PNG?raw=true)
(authKey example using PostMan)

#
*(authKey example using Postman)*

---

## Requirements

- **Node.js 18+** (tested on 20 and 22)
- **PostgreSQL 14+**
- A modern Linux distribution (any currently supported LTS — Ubuntu 22.04 / 24.04, Debian 12, RHEL 9, etc.)

---

## Quick start

```bash
# 1. Clone
git clone https://github.com/CryptoJones/TimeTrackerAPI.git
cd TimeTrackerAPI

# 2. Install dependencies (no sudo)
npm install

# 3. Provision the database
sudo -u postgres psql <<'SQL'
CREATE USER timetracker WITH PASSWORD 'change-me-strong-password';
CREATE DATABASE timetracker WITH OWNER timetracker;
SQL
sudo -u postgres psql -d timetracker -f setup/TimeTracker.sql

# QuickStart (Ubuntu 20.04 LTS)
# 4. Configure environment
cp .env.example .env
$EDITOR .env # set DB_PASSWORD, optionally PORT / CORS_ORIGIN

ubuntu@localhost:~$ `git clone https://github.com/CryptoJones/TimeTrackerAPI.git`
# 5. Run
npm start
```

ubuntu@localhost:~$ `sudo apt-get update`
The server listens on `http://0.0.0.0:3000` by default. No root required.

ubuntu@localhost:~$ `sudo apt-get install npm postgresql postgresql-client-common -y`
---

ubuntu@localhost:~$ `sudo npm install --save express cors body-parser pg pg-hstore sequelize`
## Environment variables

ubuntu@localhost:~$ `sudo su - postgres`
All configuration lives in environment variables (loaded from `.env`
locally via `dotenv`, or set directly by your process manager in
production). See `.env.example` for the canonical reference.

postgres@localhost:~$ `psql`
| Variable | Default | Purpose |
|---|---|---|
| `PORT` | `3000` | HTTP listen port. Use a non-privileged port (>1024). |
| `HOST` | `0.0.0.0` | Bind address. `127.0.0.1` for localhost-only. |
| `CORS_ORIGIN` | (unset → disabled) | Comma-separated list of allowed origins, e.g. `https://app.example.com,https://admin.example.com`. Leave unset to disable cross-origin requests entirely. |
| `DB_HOST` | `localhost` | PostgreSQL host. |
| `DB_PORT` | `5432` | PostgreSQL port. |
| `DB_NAME` | `timetracker` | Database name. |
| `DB_USER` | `timetracker` | Database user (must have access to the `dbo` schema). |
| `DB_PASSWORD` | (empty) | Database password. **Required.** Setting it empty will cause connection failures and a startup warning. |

postgres=# `CREATE USER timetracker SUPERUSER;`
`.env` is gitignored. Never commit a populated `.env`.

postgres=# `CREATE DATABASE TimeTracker WITH OWNER timetracker;`
---

postgres=# `ALTER USER timetracker WITH PASSWORD 'Password1';`
## Security notes

postgres=# `\q`
- **Do not run this service as root.** The default port (`3000`) is
non-privileged on purpose. If you need to expose the API on `:443`,
put nginx, Caddy, or another reverse proxy in front and terminate TLS
there.
- **Rotate the `authKey` regularly** and limit which users have access
to the `apikey` / `apimaster` tables.
- **Use a strong, unique `DB_PASSWORD`** and restrict the database user
to the minimum required privileges — `SUPERUSER` is convenient for
local development but should not be the production grant.

postgres@localhost:~$ `psql -f /home/ubuntu/TimeTrackerAPI/setup/TimeTracker.sql -d timetracker`
---

postgres@localhost:~$ `exit`
## License

ubuntu@localhost:~$ `cd TimeTrackerAPI`
Apache License 2.0. See [LICENSE](LICENSE).

ubuntu@localhost:~/TimeTrackerAPI$ `sudo node server.js`
Proudly Made in Nebraska. Go Big Red! 🌽 https://xkcd.com/2347/
23 changes: 14 additions & 9 deletions app/config/db.config.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 Aaron K. Clark

const env = require('./env.js');
const Sequelize = require('sequelize');

const sequelize = new Sequelize(env.database, env.username, env.password, {
host: env.host,
dialect: 'postgres',
define:{
schema: 'dbo',
timestamps: false
}
host: env.host,
port: env.port,
dialect: 'postgres',
define: {
schema: 'dbo',
timestamps: false,
},
});

const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.Customer = require('../models/customer.model.js')(sequelize, Sequelize);
db.ApiMaster = require('../models/apimaster.model.js')(sequelize, Sequelize);
db.ApiKey = require('../models/apikey.model.js')(sequelize, Sequelize);
module.exports = db;

module.exports = db;
Loading