Projects module
Manages all project-related operations, including creation, editing, viewing, member management, and change logging. Access is session- and role-controlled.
🧭 My Projects View
🔧 Workflow
GET Request (/my-projects
)
Returns all active projects the current user is assigned to.
projects = request.dbsession.query(Project)\
.join(ProjectsUser)\
.filter(ProjectsUser.user_id == request.session.get('user_id'), Project.active == True)\
.all()
➕ Create Project
🔧 Workflow
GET Request (/create-project
)
Renders the project creation form. Restricted to admin users.
POST Request (/create-project
)
Processes form input for project creation. Validates form data, creates the project, assigns the creator as project manager, and logs the creation.
new_project = Project(name=name, description=description, creation_datetime=datetime.now())
request.dbsession.add(new_project)
request.dbsession.flush()
request.dbsession.add(ProjectsUser(project_id=new_project.id, user_id=user_id, role="project_manager"))
📝 Activity Log
ActivityLog(
user_id=request.session['user_id'],
project_id=new_project.id,
action='project_added',
changes=f"{new_project.__repr__()}"
)
📂 Project Detail View
🔧 Workflow
GET Request (/project/{id}
)
Displays a single project view. Includes all tasks grouped by status and the list of members with their roles.
tasks_by_status = {
status: request.dbsession.query(Task)
.filter_by(project_id=project_id, status=status, active=True)
.order_by(Task.due_date)
.all()
for status in ['assigned', 'in_progress', 'under_review', 'completed']
}
Access is validated via the ProjectsUser
relationship.
✏️ Edit Project
🔧 Workflow
POST Request (/edit-project/{id}
)
Admins can update the project’s name and description. Changes are compared against current values and logged individually.
if project.name != new_name:
ActivityLog(action='project_edited_title', changes='old: ... new: ...')
🗑️ Delete Project
🔧 Workflow
GET Request (/delete-project/{id}
)
Performs a soft delete by setting project.active = False
. Only admins can delete. Change is logged.
project.active = False
ActivityLog(action='project_removed', changes='Project: XYZ set to inactive')
👥 Project Members
🔧 Search Users
GET Request (/search-users
)
Performs a username search. If project_id
is passed, filters out users already in the project.
query = query.filter(~User.id.in_(subquery))
➕ Add Member
POST Request (/add-member/{id}
)
Adds a user to the project with role "member". Admin-only. Logs the operation.
ProjectsUser(project_id=..., user_id=..., role="member")
ActivityLog(action='project_added_user', changes='User X added to Project Y')
➖ Remove Member
POST Request (/remove-member/{id}
)
Removes a user from the project. Admin-only. Logs the action.
request.dbsession.delete(relation)
ActivityLog(action='project_removed_user', changes='User removed from Project')
🔄 Update Task Status
🔧 Workflow
POST Request (/update-task-status
)
Expects JSON data. Changes the status of a task. Does not reload the page.
task.status = new_status
🗂️ Kanban Partial
🔧 Workflow
GET Request (/kanban-partial/{id}
)
Returns an HTML fragment with grouped tasks by status. Used for async kanban updates.
tasks_by_status = {
status: request.dbsession.query(Task)
.filter_by(project_id=project_id, status=status)
.order_by(Task.due_date)
.all()
}
✅ Projects Module Validations
1. Authentication & Permissions
Session Validation
All routes require an active, valid session via
@verify_session
.Ensures that only authenticated users can interact with the project system.
Admin Permission Checks
Project creation, deletion, editing, and member management require
"admin"
permission.Enforced via Pyramid’s
@view_config(permission="admin")
.
2. Access Control
Membership Validation
For views like
/project/{id}
, the system checks if the requesting user is a member of the project:project = request.dbsession.query(Project).join(ProjectsUser)...filter(ProjectsUser.user_id == session_user)
Prevents non-members from accessing project details.
3. Project Data Validation
Name and Description Non-Empty Check
On project creation and editing, the form input is validated to ensure:
name
is not empty or whitespace.description
is provided.Usually checked server-side before committing changes.
Edit Check (Change Detection)
Edit operations log only actual changes. Old vs. new values are compared before saving and logging.
4. Project Deletion Protection
Soft Delete
Deletion only sets
project.active = False
.Prevents data loss and allows historical audits.
5. Member Management Validation
Duplicate Member Check
Before adding a user, the system checks that the user is not already assigned to the project:
exists = request.dbsession.query(ProjectsUser)...filter_by(user_id=user_id, project_id=project_id).first()
Valid User ID
When adding or removing users, the user ID is validated:
Must exist.
Must not conflict with existing records or permissions.
6. Task Status Update Validations
Valid Task ID and Project Match
When updating task status:
Ensures that the task exists.
The task belongs to the project the user has access to.
Prevents tampering via direct API calls.
Valid Status Enum
Only allows updates to known statuses:
'assigned'
,'in_progress'
,'under_review'
,'completed'
.Invalid statuses are rejected.
7. User Search Filtering
Duplicate Filter in Search
When using
/search-users?project_id=XYZ
, it excludes users already assigned to the project to prevent duplicates:query = query.filter(~User.id.in_(subquery))
8.All POST requests contain CSRF protection
Last updated