Skip to content

A time-tracker born out of the "we don't know Closure yet" dialog

License

Notifications You must be signed in to change notification settings

terminus-community/ttracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TTracker

A time-tracker born out of the "we don't know Clojure yet" dialog. Idea: have a web server backend so teamleads and users themselves can view time spent on tasks, have a desktop app to do the tracking.

Concept

Essentially, what we'd want is a simple project to learn Clojure.

It'll need:

  • routes to log in and out
  • basic admin panel
  • ability to create and delete projects
  • ability to start tracking time on a project

Server-side

  • Probably microframework-based, and Luminus seems nice on the first sight: what I like is REPL-driven development idea, what I want to know later is modularity of Luminus (replacing a template engine, for instance)
  • JWT auth routes (People in this thread recommend buddy)
  • Admin panel to add and delete users (yes, manually, we can improve it later)
  • Route to start and stop tracking time

Client-side: a GUI app

The application will be browser-based.

Also, it would be sehr cool, if we will be able to implement client-side in ClojureScript, transpilable or in other way compatible with one of popular JS frameworks: Vue.js, React or Angular.

Login:

  • ask user for the server URL, login, password
  • log on a server using supplied login and password
  • open the base view

Main view:

  • show a list of the projects, a button to create one and delete one
  • when a project is picked, enable "start" button
  • track when user has no activity, show a pause notification, pause tracking in 1 minute

DB

Models

Auth (auth table)

Let's stop on a simple email-based authentication, with a possible username.

Columns:

  • id (serial, autoincremented integer type)
  • email (text, discuss what limit we impose on its length)
  • username (text, discuss what limit we imposse on its length)
  • salt (autogenerated password salt for security reasons)
  • salt_num (how many times did iterative hashing happen?)
  • password (salted password checksum)

Scenario: user registers, a hash is concatenated with new password, random number salt_num is picked (2-9), password is hashed with salt salt_num times, so rainbow tables use on a leaked db is much less useful. (Yes, it's a typical modern approach.)

Session

We should store all user sessions somewhere. The fact we'd store them in a DB is awkward, but this app is small.

Columns

  • id (serial, autoincremented integer type)
  • user_id (foreign key to `auth)
  • token (text)
  • token_datetime (datetime type for current DB implementation)

Groups (auth_group)

We need groups, created by users, as an abstraction to unite people: companies are not the best principle to unite, since they can create confusion. RBAC is too complex.

  • id (serial, autoincremented integer type)
  • name (text, name of a group, may have a character length limit or not, up to discussion)
  • description (text, a custom text, describing a group)

Projects

  • id (serial) - autoincremented integer type)
  • group_id (foreign key to auth_group id)
  • name (text) - name of a project, may have a character length limit or not, up to discussion)

Tracking

  • id (serial) - autoincremented integer type)
  • user_id (a foreign key to user->id)
  • project_id (a foreign key to projects)
  • mode (bool) - do we start tracking, or stop tracking
  • datetime - datetime for a tracking events

User-group relations (usergroup)

  • id (serial, autoincremented integer type)
  • user_id (int) - a foreign key to user
  • group_id (int) - a foreign key to a group
  • is_owner (bool) - can add users to groups, remove a group, rename a group, view timings inside a group
  • is_mod (bool) - can view a list of people in a group, view timings for other users

Invites (invite)

  • id (serial, autoincremented integer type)
  • inviter_id - a foreign key to inviting user
  • group_id - a foreign key to group the user is invited into
  • invitee_id - a foreign key to user invited to a group

API

Auth

  • /api/auth/register/ - let's not implement email verification yet, accept email and password, check if there is no such email in use, create an auth table record.
  • /api/auth/login/ - verify a password by iterative hashing, return an error on failure and an auth token on success (JWT routes). Example request: Content-Type: application/json (header), {"username": "Petya", "password":"IAm1st"} or {"email": "[email protected]", "password":"IAm1st"} (body).
  • /api/auth/refresh/ - refresh a token (JWT). Example: Content-Type: application/json (header), {"token":"<JWT>"} (body).
  • /api/auth/verify - we've closed an app and reopened it, we have the token, it did not expire, so we supply it to login instead. Content-Type: application/json (header), {"token":"<EXISTING_TOKEN>"} (body).

Tracking

  • /api/tracking/<project_id>/start - start tracking time for a user on <project_id>

Groups

  • /api/groups/send_invite - receive a user email as a string or user id, invite user to a group
  • /api/groups/check_invites - check for existing invites, needs a regular (1 min) refresh interval and makes me think that tracking events and this part fit into a common WebSocket API, to be honest.
  • /api/groups/accept_invite - accepts an invite notification
  • /api/groups/add - receive a user id, group name, create a new group, return its id
  • /api/groups/remove - receive a group id, user id, session token, check if user can remove group, remove if possible, return an error otherwise
  • /api/groups/rename - receive a group id, user id, session token, check if user has rights to remove a group, return an error otherwise
  • /api/groups/list_users/ - receive a group id, user id, session token, check if user has rights to see the members, list all members in a group
  • /api/groups/view_timings/user_id - view timings for a certain user, maybe will need pagination at some point, but in the beginning it's possible to return all

Projects

  • /api/projects/list/ - supply user id, group id; check user rights, show list of projects in a group
  • /api/projects/add - supply user id, group id, new project name; add project for a group
  • /api/projects/ - remove a project from a group

Tracking

  • /api/tracking/start/ - supply project id, user id, stop all active tracking, start tracking on a project if it's in user's groups
  • /api/tracking/stop - supply project id, user id, stop tracking on a selected project
  • /api/tracking/project/count - supply user id, project id, count all time spent time on a project
  • /api/tracking/count_global - supply user id, count global time on all projects

About

A time-tracker born out of the "we don't know Closure yet" dialog

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published