Ejemplo n.º 1
0
def profile_password( account_id ):
  from models.account import Account
  
  account_id = urllib.unquote_plus(account_id)
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    abort(404)
  elif not app.access('profile', action='update', account=account):
    abort(403)
  title = g._t('profile')+' | '+g._t('profile password set')
  breadcrumbs = (
    (((not app.access('authenticated', account=account)) and g._t('employees') or ''), url_for('profile_employees')),
    ((app.access('authenticated', account=account) and g._t('me') or account.__str__()), url_for('profile_view', account_id=account_id)),
    (title, "#")
  )
  
  errors = []
  
  if request.method == 'POST':
    if account.passwordIsSet() and not request.form.get('current_password'):
      errors.append(('current password', 'required'))
    elif account.passwordIsSet() and not account.validatePassword( request.form.get('current_password')):
      errors.append(('current password', 'incorrect'))
    if not request.form.get('password'):
      errors.append(('new password', 'required'))
    elif not request.form.get('confirm_password'):
      errors.append(('confirm new password', 'required'))
    elif not request.form.get('password') == request.form.get('confirm_password'):
      errors.append(('new password', 'does not match'))
    if not len(errors):
      account.password = request.form.get('password')
      account.save()
      flash(g._t('profile password set success'))
      return redirect(url_for('profile_view', account_id=urllib.quote_plus(account_id)))
  return render_template('profile/password.html', account=account, title=title, breadcrumbs=breadcrumbs, errors=errors)
Ejemplo n.º 2
0
def project_index(account_id=None):
  from models.account import Account
  from models.project import Project
  from helpers.project import ProjectHelper
  
  title = g._t('projects')
  
  if account_id:
    account_id = urllib.unquote_plus(account_id)
    account = Account.query.filter_by(id=account_id).first()
    if not account:
      abort(404)
    elif not app.access('membership', account=account):
      abort(403)
    
    projectList = ProjectHelper.listProjectsForMember(account)
  else:
    account = g.account
    
    if app.access('project', action='administer'):
      projectList = ProjectHelper.listProjects()
    elif app.access('project', action='list'):
      projectList = ProjectHelper.listActiveProjects()
    elif app.access('membership', account=account):
      projectList = ProjectHelper.listProjectsForMember(account)
    else:
      abort(403)
  
  return render_template('project/index.html', title=title, projectList=projectList, account=account)
Ejemplo n.º 3
0
 def getChineseCookie(cls):
   from models.variable import Variable
   import datetime
   import time
   import random
   from application import app
   
   if not app.access('authenticated'):
     # cookie will be shown to the authenticated users only
     return None
   
   if app.access('is_masquerade'):
     # cookie is not shown for the masquerade sessions
     return None
   
   if not cls.getPreference('show_chinese_cookie'):
     # chinese cookie disbled for the user
     return None
   
   language = cls.getPreference('language')
   if not language:
     # no language defined
     return None
   
   variable = Variable.query.filter_by(scope='common', name='chinese_cookie_data').first()
   if not variable or not type(variable.value) == dict:
     # no chinese cookie defined
     return None
   if not variable.value.has_key(language):
     # no chinese cookie for a given language
     return None
   value = variable.value[language]
   
   nowDate = datetime.datetime.now()
   midnightDate = datetime.datetime( year=nowDate.year, month=nowDate.month, day=nowDate.day )
   midnightDateString = midnightDate.strftime( '%Y-%m-%d' )
   
   chinese_cookie_date_shown = cls.getPreference('chinese_cookie_date_shown') or '0'
   if chinese_cookie_date_shown >= midnightDateString:
     # the chinese cookie has been already shown today
     return None
   
   chinese_cookie_list_shown = cls.getPreference('chinese_cookie_list_shown') or []
   available_chinese_cookie_list = []
   for cc in value:
     if not cc in chinese_cookie_list_shown:
       # add a chinese cookie to the list of available ones if it's never shown to the user
       available_chinese_cookie_list.append(cc)
   
   if len(available_chinese_cookie_list) == 0:
     # all chinese cookies for a given language have been shown to the user already
     return None
   
   new_chineese_cookie = available_chinese_cookie_list[random.randint(0, len(available_chinese_cookie_list)-1)]
   cls.setPreference('chinese_cookie_date_shown', midnightDateString)
   chinese_cookie_list_shown.append(new_chineese_cookie)
   cls.setPreference('chinese_cookie_list_shown', chinese_cookie_list_shown)
   
   return new_chineese_cookie
Ejemplo n.º 4
0
def session_signout():
  if app.access('authenticated'):
    if app.access('is_masquerade'):
      success_message = g._t('masquerade stop success')
    else:
      success_message = g._t('signout success')
    session_forget()
    flash(success_message, 'success')
  return redirect(url_for(app.config['HOME_PAGE']))
Ejemplo n.º 5
0
def project_edit(project_id=None):
  from models.account import Account
  from models.project import Project, Label
  
  project = None
  if not project_id:
    project = Project()
    project.status = Project.STATUS_ACTIVE
    if not app.access('project', action='create'):
      abort(403)
  else:
    project_id = urllib.unquote_plus(project_id)
    project = Project.query.filter_by(id=project_id).first()
    if not project:
      abort(404)
    elif not app.access('project', action='update', project=project):
      abort(403)
  
  validationErrors = []
  if request.method == 'POST' and request.form.get('csrf_token', None):
    project.alias = request.form.get('project_alias', project.alias).strip()
    project.title = request.form.get('project_title', project.title).strip()
    project.info = request.form.get('project_info', project.info).strip()
    project.status = int(request.form.get('project_status', project.status).strip())
    
    validationErrors.extend(project.validate())
    if not validationErrors:
      project.save()
      
      if not Label.query.filter_by(project_id=project.id, title=Label.LABEL_DEFAULT).first():
        label = Label()
        label.project_id = project.id
        label.title = Label.LABEL_DEFAULT
        label.save()
      
      flash(g._t('project submit success'))
      return redirect(url_for('project_view', project_id=urllib.quote_plus(str(project.id))))
  
  if project_id:
    title = g._t('edit project')
  else:
    title = g._t('add project')
  
  if project_id:
    breadcrumbs = (
      (g._t('projects'), url_for('project_index')),
      (project.__str__(), url_for('project_view', project_id=urllib.quote_plus(str(project_id)))),
      (title, "#")
    )
  else:
    breadcrumbs = (
      (g._t('projects'), url_for('project_index')),
      (title, "#")
    )
  
  return render_template('project/edit.html', project_id=project_id, project=project, errors=validationErrors, title=title, breadcrumbs=breadcrumbs)
Ejemplo n.º 6
0
def test_permissions_custom_word():
  title = 'Testing custom permission, the word should be "yep"'
  data = {
    "app.access('test_permission_word')": app.access('test_permission_word'),
    "app.access('test_permission_word', word='qwer')": app.access('test_permission_word', word='qwer'),
    "app.access('test_permission_word', word='yep')": app.access('test_permission_word', word='yep')
  }
  data = Markup('<br/>').join(["%s: %s" % (k,v) for k,v in data.items()])
  
  return render_template( 'test/index.html', title=title, data=data )
Ejemplo n.º 7
0
def profile_preferences(account_id):
  from models.account import Account, Preference
  from helpers.account import AccountHelper
  
  account_id = urllib.unquote_plus(account_id)
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    abort(404)
  elif not app.access('profile', action='update', account=account):
    abort(403)
  
  preferences = {
    'language': None,
    'floats_format': None,
    'report_time_format': None,
    'show_deleted_reports': None,
    'datepicker_multiple_days': None,
    'show_chinese_cookie': None
  }
  
  for key in preferences.keys():
    preference = Preference.query.filter_by(account_id=account.id, name=key).first()
    if not preference:
      preference = Preference()
      preference.account_id = account.id
      preference.name = key
      preference.value = AccountHelper.getPreference(key)
    preferences[key] = preference
  
  title = g._t('profile preferences')
  
  breadcrumbs = (
    (((not app.access('authenticated', account=account)) and g._t('employees') or ''), url_for('profile_employees')),
    ((app.access('authenticated', account=account) and g._t('me') or account.__str__()), url_for('profile_view', account_id=account_id)),
    (title, "#")
  )
  
  validationErrors = []
  
  if request.method == 'POST' and request.form.get('csrf_token'):
    for key, preference in preferences.items():
      preference.raw_value = request.form.get('preference_'+key, None)
      errors = preference.validate()
      validationErrors.extend(errors)
      if not errors:
        preference.save()
    
    if not validationErrors:
      flash( g._t('preference update success'))
    else:
      flash( g._t('preference update error'), 'error')
    return redirect(url_for('profile_preferences', account_id=urllib.quote_plus(account_id)))
  
  return render_template('profile/preferences.html', account_id=account_id, account=account, preferences=preferences, title=title, breadcrumbs=breadcrumbs, errors=validationErrors)
Ejemplo n.º 8
0
def permission_activity(account=None):
  from helpers.project import ProjectHelper
  
  """Accounts' membership check for signed in account. 
  @description Check if a signed in account is permitted to see the given account's membership activity or totals. 
  @param <Account>account (optional) 
  @return bool 
  @example Call as app.access('membership', account=ACCOUNT)"""
  if not account:
    return app.access('profile', action='list') and app.access('report', action='list')# and app.access('project', action='list')
  else:
    return ProjectHelper.profileHasSubordinate(g.account, account) or app.access('membership', account=account)
Ejemplo n.º 9
0
def permission_membership(account=None):
  """Accounts' membership check for signed in account. 
  @description Check if a signed in account is permitted to see the given account's membership projects. 
  @param <Account>account 
  @return bool 
  @example Call as app.access('membership', account=ACCOUNT)"""
  if not account:
    raise Exception('Membership permission: account missing')
  
  if account.id == g.account.id:
    return app.access('profile', action='read', account=account)
  else:
    return app.access('profile', action='read', account=account) and app.access('project', action='list')
Ejemplo n.º 10
0
def profile_employees():
  from models.account import Account
  from helpers.account import AccountHelper
  
  title = g._t('employees')
  if app.access('profile', action='administer'):
    employees = AccountHelper.listAccounts()
  elif app.access('profile', action='list'):
    employees = AccountHelper.listActiveAccounts()
  else:
    employees = [g.account]
    return redirect(url_for('profile_view', account_id=urllib.quote_plus(str(g.account.id))))
    
  return render_template('profile/employees.html', employees=employees, title=title)
Ejemplo n.º 11
0
def permission_project(action=None, project=None, account=None):
  """Project CRUD check for signed in account. 
  @description Check if a signed in account has a specified action for a given project. 
  @param <str>action, valid values ["list", "administer", "create", "read", "update", "delete"]
  @param <Project>project (optional) 
  @return bool 
  @example Call as app.access('project', action='update', project=PROJECT)"""
  from models.project import Project
  from helpers.project import ProjectHelper
  
  if not action:
    raise Exception('Project CRUD permission: action missing')
  
  if not account or not account.id:
    account=g.account
  
  if not project and not action in ['list', 'administer', 'create']:
    raise Exception('Project CRUD permission: project required for action "'+action+'"')
  
  if action == 'list':
    return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
  if action == 'administer':
    return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
  elif action == 'create':
    return app.access('group', account=account, group_alias=['administrator', 'privileged_manager', 'manager'])
  elif action == 'read':
    if project.status & project.STATUS_DELETED:
      return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
    elif ProjectHelper.projectHasActiveMember(project=project, account=account):
      return True
    else:
      return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
  elif action == 'update':
    if project.status & project.STATUS_DELETED:
      return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
    elif ProjectHelper.projectHasManager(project=project, account=account):
      return True
    else:
      return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
  elif action == 'delete':
    return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
  elif action == 'role':
    if project.status & project.STATUS_DELETED:
      return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
    else:
      return app.access('group', account=account, group_alias=['administrator', 'privileged_manager'])
  else:
    raise Exception('Project CRUD permission: incorrect action "'+action+'", must be ["list", "administer", "create", "read", "update", "delete"]')
Ejemplo n.º 12
0
def test_permissions_all_accounts_groups():
  from models.account import Account
  
  title = 'Testing | Permissions | Listed per-account-role permissions'
  
  data = '<table class="table" width="100%">'
  employees = [employee for employee in Account.all()]
  roles = g._var(name='roles', scope='permissions', default={}).keys()
  data = data + '<tr>'
  data = data + '<th>&nbsp;</th>'
  for role in roles:
    data = data + '<th>'+role+'</th>'
  data = data + '</tr>'
  
  for employee in employees:
    data = data + '<tr>'
    data = data + '<th>'+employee+'</th>'
    for role in roles:
      is_permitted = app.access('role', account=employee, role_id=role)
      data = data + (is_permitted and '<td class="alert alert-success">yes</td>' or '<td class="alert alert-danger">no</td>')
    data = data + '</tr>'
  
  data = data + '</table>'
  data = Markup(data)
  
  return render_template( 'test/index.html', title=title, data=data )
Ejemplo n.º 13
0
def report_index(account_id):
  from models.account import Account
  from models.report import Report
  
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    abort(404)
  elif not app.access('activity', account=account):
    abort(403)
  
  header = _activityHeader(employees=[account])
  
  filters = {}
  filters['project'] = [component.id for component in header['projects']]
  filters['employee'] = [account.id for account in header['employees']]
  filters['start_date'] = header['start_date']
  filters['end_date'] = header['end_date']
  
  title = g._t( 'reports' )
  if account.id == g.account.id:
    title = g._t('reports')
  else:
    title = g._t('reports') + ' - ' + str(account)
  
  breadcrumbs = (
    (title, "#"),
    (g._t('efforts'), url_for('effort_index', account_id=account.id))
  )
  
  return render_template('report/report.index.html', account=account, title=title, breadcrumbs=breadcrumbs, header=header)
Ejemplo n.º 14
0
def project_components(project_id):
  from models.project import Project, Component
  
  project_id = urllib.unquote_plus(project_id)
  project = Project.query.filter_by(id=project_id).first()
  if not project:
    abort(404)
  elif not app.access('project', action='update', project=project):
    abort(403)
  
  title = g._t('project components')
  
  breadcrumbs = (
    (g._t('projects'), url_for('project_index')),
    (project.__str__(), url_for('project_view', project_id=urllib.quote_plus(str(project_id)))),
    (title, "#")
  )
  
  if (request.form.get('method') == 'PUT' or request.method == 'PUT') and request.form.get('csrf_token'):
    submittedComponent = Component.query.filter_by(id=request.form.get('component_id')).first()
    if submittedComponent:
      submittedComponent.alias = request.form.get('component_alias', '')
      submittedComponent.title = request.form.get('component_title', '')
      submittedComponent.info = request.form.get('component_info', '')
    
      if not submittedComponent.validate():
        submittedComponent.save()
        
        flash( g._t('component update success'))
        return redirect(url_for('project_components', project_id=urllib.quote_plus(str(project_id))))
    else:
      flash( g._t('component not found'), 'error')
    
  elif (request.form.get('method') == 'DELETE' or request.method == 'DELETE') and request.form.get('csrf_token'):
    submittedComponent = Component.query.filter_by(id=request.form.get('component_id')).first()
    if submittedComponent:
      submittedComponent.delete()
    
      flash( g._t('component delete success'))
      return redirect(url_for('project_components', project_id=urllib.quote_plus(str(project_id))))
    else:
      flash( g._t('component not found'), 'error')
    
  elif (request.form.get('method') == 'POST' or request.method == 'POST') and request.form.get('csrf_token'):
    submittedComponent = Component()
    submittedComponent.project_id = project.id
    submittedComponent.alias = request.form.get('component_alias', '')
    submittedComponent.title = request.form.get('component_title', '')
    submittedComponent.info = request.form.get('component_info', '')
    
    if not submittedComponent.validate():
      submittedComponent.save()
      
      flash( g._t('component create success'))
      return redirect(url_for('project_components', project_id=urllib.quote_plus(str(project_id))))
    
  else:
    submittedComponent = Component()
  
  return render_template('project/components.html', project_id=project_id, project=project, submittedComponent=submittedComponent, title=title, breadcrumbs=breadcrumbs)
Ejemplo n.º 15
0
def effort_summary():
  if not app.access('activity'):
    abort( 403 )
  
  header = _activityHeader()
  
  title = g._t('effort summary')
  return render_template('report/effort.summary.html', account=g.account, title=title, header=header)
Ejemplo n.º 16
0
def session_masquerade(account_id):
  from models.account import Account
  
  account_id = urllib.unquote_plus(account_id)
  account = Account.query.filter_by(id=account_id).first()
  
  if app.access('is_masquerade'):
    flash(g._t('already masquerade'), 'error')
    return redirect(url_for(app.config['HOME_PAGE']))
  if not account:
    abort(404)
  elif not app.access('masquerade', account=account):
    abort(403)
  
  session_authenticate_masquerade(account.id)
  
  flash(g._t('masquerade success'), 'success')
  return redirect(url_for(app.config['HOME_PAGE']))
Ejemplo n.º 17
0
def profile_view(account_id):
  from models.account import Account
  
  account_id = urllib.unquote_plus(account_id)
  account = Account.query.filter_by(id=account_id).first()
  
  if not account:
    abort(404)
  elif not app.access('profile', action='read', account=account):
    abort(403)
  
  title = (app.access('authenticated', account=account)) and g._t('me') or account.__str__()
  breadcrumbs = (
    ((app.access('authenticated', account=account) and g._t( 'employees' ) or ''), url_for('profile_employees')),
    (title, "#"),
  )
  
  return render_template('profile/view.html', account=account, title=title, breadcrumbs=breadcrumbs)
Ejemplo n.º 18
0
def test_data_projects():
  from models.account import Account
  from models.project import Project
  
  title = 'Testing | Data | Listed per-account-project membership'
  
  employees = [account for account in Account.all() if account.id.startswith('test.')]
  projects = [project for project in Project.all() if project.id.startswith('TEST/')]
  
  data = _test_data_menu()
  data = data + '<table class="table" width="100%">'
  roles = g._var(name='roles', scope='permissions', default={}).keys()
  
  data = data + '<tr>'
  data = data + '<th>&nbsp;</th>'
  for project in projects:
    data = data + '<th>'+project.id+'</th>'
  data = data + '</tr>'
  
  for employee in employees:
    data = data + '<tr>'
    data = data + '<th>'+employee.id+'</th>'
    for project in projects:
      #data = data + (project.hasMember(employee.id) and '<td class="alert alert-success">'+project.members.get(employee.id, '---')+'</td>' or '<td class="alert alert-danger">no</td>')
      details = {}
      details['class'] = project.hasMember(employee.id) and 'success' or 'danger'
      details['label'] = project.hasMember(employee.id) and project.members.get(employee.id, '?') or '-'
      details['label'] = details['label'] + '<div class="pull-right">'
      
      details['label'] = details['label'] + (app.access('project', action='read', project=project, account=employee) and '<i class="icon icon-eye-open text-info"></i> | ' or '<i style="opacity:0.2" class="icon icon-eye-open muted"></i> | ')
      details['label'] = details['label'] + (app.access('project', action='update', project=project, account=employee) and '<i class="icon icon-edit text-info"></i> | ' or '<i style="opacity:0.2" class="icon icon-edit muted"></i> | ')
      details['label'] = details['label'] + (app.access('project', action='delete', project=project, account=employee) and '<i class="icon icon-trash text-info"></i>' or '<i style="opacity:0.2" class="icon icon-trash muted"></i>')
      
      details['label'] = details['label'] + '</div>'
      
      data = data + '<td class="alert alert-'+details['class']+'">'+details['label']+'</td>'
    data = data + '</tr>'
  
  data = data + '</table>'
  data = Markup(data)
  
  return render_template('test/index.html', title=title, data=data)
Ejemplo n.º 19
0
def permission_masquerade(account=None):
  """Permission to re-login as another account. 
  @description Check if a signed in account is permitted to re-login as another account. 
  @param <Account>account 
  @return bool 
  @example Call as app.access('masquerade', account=ACCOUNT)"""
  if not account:
    raise Exception('Masquerade permission: account missing')
  
  if account.id == g.account.id:
    return False
  else:
    return app.access('group', group_alias=['administrator', 'privileged_manager']) and app.access('profile', action='update', account=account)
Ejemplo n.º 20
0
def profile_delete(account_id):
  from models.account import Account
  
  account_id = urllib.unquote_plus(account_id)
  account = Account.query.filter_by(id=account_id).first()
  
  if not account:
    abort(404)
  elif not app.access('profile', action='update', account=account):
    abort(403)
  
  if request.method == 'POST' and request.form.get('csrf_token', None):
    if request.form.get('action') == 'profile_action_remove_permanently':
      if not app.access('profile', action='delete', account=account):
        abort(403)
      else:
        account.delete()
        success_message = g._t('profile remove permanently success')
        
    elif request.form.get('action') == 'profile_action_delete':
      account.status = account.status | account.STATUS_DELETED
      account.save()
      success_message = g._t('profile delete success')
    
    flash(success_message)
    return redirect(url_for('profile_employees'))
  
  errors = []
  
  title = g._t('delete profile?')
  breadcrumbs = (
    (((not app.access('authenticated', account=account)) and g._t('employees') or ''), url_for('profile_employees')),
    ((app.access('authenticated', account=account) and g._t('me') or account.__str__()), url_for('profile_view', account_id=account_id)),
    (title, "#")
  )
  
  return render_template('profile/delete.html', account=account, title=title, breadcrumbs=breadcrumbs, errors=errors)
Ejemplo n.º 21
0
def project_delete(project_id):
  from models.project import Project
  
  project_id = urllib.unquote_plus(project_id)
  project = Project.query.filter_by(id=project_id).first()
  
  if not project:
    abort(404)
  elif not app.access('project', action='update', project=project):
    abort(403)
  
  if request.method == 'POST' and request.form.get('csrf_token', None):
    if request.form.get('action') == 'project_action_remove_permanently':
      if not app.access('project', action='delete', project=project):
        abort(403)
      else:
        project.delete()
        success_message = g._t('project remove permanently success')
    elif request.form.get('action') == 'project_action_delete':
      project.status = project.status | project.STATUS_DELETED
      project.save()
      success_message = g._t('project delete success')
    
    flash(success_message)
    return redirect(url_for('project_index'))
  
  errors = []
  
  title = g._t('project delete')
  breadcrumbs = (
    (g._t('projects'), url_for('project_index')),
    (project.__str__(), url_for('project_view', project_id=urllib.quote_plus(str(project.id)))),
    (title, "#")
  )
  
  return render_template( 'project/delete.html', project=project, title=title, breadcrumbs=breadcrumbs, errors=errors )
Ejemplo n.º 22
0
def project_view(project_id):
  from models.project import Project
  
  project_id = urllib.unquote_plus(project_id)
  project = Project.query.filter_by(id=project_id).first()
  if not project:
    abort(404)
  elif not app.access('project', action='read', project=project):
    abort(403)
  
  title = project.__str__()
  
  breadcrumbs = (
    (g._t('projects'), url_for('project_index')),
    (title, "#")
  )
  
  return render_template('project/view.html', project=project, title=title, breadcrumbs=breadcrumbs)
Ejemplo n.º 23
0
def _activityHeader(**kwargs):
  from models.account import Account
  from models.project import Project, Component, Membership, Label
  from helpers.account import AccountHelper
  from helpers.project import ProjectHelper
  
  header = {}
  
  if kwargs.has_key('start_date'):
    header['start_date'] = kwargs['start_date']
  else:
    header['start_date'] = request.values.get('start_date', g._constant()['DATE']['MONTH'])
  #start_date = datetime.datetime.strptime(start_datestring, '%Y-%m-%d')
  #start_ts = start_date.strftime('%s')
  
  if kwargs.has_key('end_date'):
    header['end_date'] = kwargs['end_date']
  else:
    header['end_date'] = request.values.get('end_date', g._constant()['DATE']['TODAY'])
  #end_date = datetime.datetime.strptime(end_datestring, '%Y-%m-%d')
  #end_ts = end_date.strftime('%s')
  
  header['employees'] = []
  if kwargs.has_key('employees'):
    header['employees'] = kwargs['employees']
  elif app.access('profile', action='administer'):
    header['employees'] = AccountHelper.listAccounts()
  elif app.access('profile', action='list'):
    header['employees'] = AccountHelper.listActiveAccounts()
  elif app.access('profile', action='read', account=g.account):
    header['employees'] = [g.account]
  else:
    header['employees'] = []
  
  header['skip_projects'] = ProjectHelper.listVacationProjects()
  
  header['projects'] = []
  if kwargs.has_key('projects'):
    header['projects'] = kwargs['projects']
  elif app.access('project', action='administer'):
    header['projects'] = ProjectHelper.listAllComponents()
  elif app.access('project', action='list'):
    header['projects'] = ProjectHelper.listAllActiveComponents()
  elif app.access('membership', account=g.account):
    header['projects'] = ProjectHelper.listAllComponentsForMember(account=g.account)
  else:
    header['projects'] = []
  
  return header
Ejemplo n.º 24
0
def effort_index(account_id):
  from models.account import Account
  
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    abort(404)
  elif not app.access('activity', account=account):
    abort(403)
  
  header = _activityHeader(employees=[account])
  
  if account.id == g.account.id:
    title = g._t('efforts')
  else:
    title = g._t('efforts') + ' | ' + str(account)
  
  breadcrumbs = (
    (g._t('reports'), url_for('report_index', account_id=account.id)),
    (title, "#")
  )
  
  return render_template('report/effort.index.html', account=account, title=title, breadcrumbs=breadcrumbs, header=header)
Ejemplo n.º 25
0
def permission_profile(action=None, account=None):
  """Profile CRUD check for signed in account. 
  @description Check if a signed in account has a specified action for a given account. 
  @param <str>action, valid values ["list", "administer", "create", "read", "update", "delete"]
  @param <Account>account (optional) 
  @return bool 
  @example Call as app.access('profile', action='update', account=ACCOUNT)"""
  from models.account import Account
  
  if not action:
    raise Exception('Profile CRUD permission: action missing')
  
  if not account and not action in ['list', 'administer', 'create']:
    raise Exception('Profile CRUD permission: account required for action "'+action+'"')
  
  if action == 'list':
    return app.access('group', group_alias=['administrator', 'privileged_manager', 'manager', 'privileged_member'])
  if action == 'administer':
    return app.access('group', group_alias=['administrator', 'privileged_manager'])
  elif action == 'create':
    return app.access('group', group_alias=['administrator', 'privileged_manager', 'manager'])
  elif action == 'read':
    if account.status & account.STATUS_DELETED:
      return app.access('group', group_alias=['administrator', 'privileged_manager'])
    else:
      return True
  elif action == 'update':
    if account.status & account.STATUS_DELETED:
      return app.access('group', group_alias=['administrator', 'privileged_manager'])
    elif account.id == g.account.id:
      return True
    else:
      return app.access('group', group_alias=['administrator', 'privileged_manager', 'manager'])
  elif action == 'delete':
    if account.id == g.account.id:
      return False
    else:
      return app.access('group', group_alias=['administrator', 'privileged_manager'])
  else:
    raise Exception('Profile CRUD permission: incorrect action "'+action+'", must be ["list", "administer", "create", "read", "update", "delete"]')
Ejemplo n.º 26
0
def report_delete_multiple(account_id):
  from models.account import Account
  from models.report import Report
  
  account_id = urllib.unquote_plus(account_id)
  account = Account.query.filter_by(id=account_id).first()
  
  if not account:
    if request.is_ajax:
      return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['user not found']}), mimetype='application/json')
    else:
      abort(404)
  elif not app.access('activity', account=account):
    if request.is_ajax:
      return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
    else:
      abort(403)
  
  reportIdList = request.values.getlist('report[id]')
  reportList = Report.query.filter(Report.id.in_(reportIdList)).all()
  
  for report in reportList:
    if not report:
      if request.is_ajax:
        return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['report not found']}), mimetype='application/json')
      else:
        abort(404)
    elif not app.access('report', action='update', report=report):
      if request.is_ajax:
        return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
      else:
        abort(403)
  
  title = g._t('report delete') + ' ('+str(len(reportList))+')'
  errors = []
  
  if request.method == 'POST' and request.values.get('csrf_token', None):
    if request.form.get('action') == 'report_action_remove_permanently':
      if not app.access('report', action='delete'):
        if request.is_ajax:
          return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
        else:
          abort(403)
    
    if request.form.get('action') == 'report_action_remove_permanently':
      for report in reportList:
        report.delete()
      success_title = g._t('report remove permanently success')
      success_message= g._t('report remove permanently success message') + ' ('+str(len(reportList))+')'
    elif request.form.get('action') == 'report_action_delete':
      for report in reportList:
        report.status = report.status | report.STATUS_DELETED
        report.save()
      success_title = g._t('report delete success')
      success_message= g._t('report delete success message') + ' ('+str(len(reportList))+')'
    status = 200
    description = 'OK'
    
    if request.is_ajax:
      return Response(json.dumps({
        'html':render_template('_popup.html', title=success_title, message=success_message, javascript="""setTimeout(function(){$('form[name=statistics-form]').submit(); $('form[name=statistics-form]').submit(); $('form[name=filter-form]').submit();;}, 300);"""),
        'status':status,
        'description':description,
        'errors':errors
      }), mimetype='application/json')
    else:
      flash(success_message)
      return redirect(url_for('report_index', account_id=account_id))
  
  status = 200
  description = 'OK'
  if request.is_ajax:
    htmlContent = render_template('report/report.delete_multiple-popup.html', account=account, title=title, reportList=reportList, errors=errors)
    return  Response(json.dumps({'html':htmlContent, 'status':status, 'description':description, 'errors':errors}), mimetype='application/json')
  else:
    htmlContent = render_template('report/report.delete_multiple.html', account=account, title=title, reportList=reportList, errors=errors)
    return htmlContent
Ejemplo n.º 27
0
def report_edit(account_id, report_id=None):
  from models.account import Account
  from models.project import Project, Component
  from models.report import Report
  
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    if request.is_ajax:
      return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['user not found']}), mimetype='application/json')
    else:
      abort(404)
  
  report = None
  if not report_id:
    report = Report()
    report.status = Report.STATUS_ACTIVE
    report.due_date = datetime.datetime.now().strftime('%Y-%m-%d')
    if not app.access('report', action='create'):
      if request.is_ajax:
        return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
      else:
        abort(403)
  else:
    report_id = urllib.unquote_plus(report_id)
    report = Report.query.filter_by(id=report_id).first()
    if not report:
      if request.is_ajax:
        return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['report not found']}), mimetype='application/json')
      else:
        abort(404)
    elif not app.access('report', action='update', report=report):
      if request.is_ajax:
        return Response(json.dumps({'status':403, 'description':'Forbidden', 'errors':['forbidden']}), mimetype='application/json')
      else:
        abort(403)
  
  title = g._t('report submit')
  
  report_due_date_list = []
  validationErrors = []
  if (request.method == 'POST' and request.values.get('csrf_token', None)) or request.values.get('no_validate', None):
    report.reporter_id = g.account.id
    
    component_id = request.values.get('report_component_id', None)
    if component_id:
      component = Component.query.filter_by(id=component_id).first()
      if component:
        report.component_id = component.id
        report.project_id = component.project_id
    
    
    report_due_date_list = request.values.get('report_due_date', report.due_date).strip().split(',')
    report.due_date = report_due_date_list.pop(0)
    
    hours = request.values.get('report_hours', str(report.hours)).strip() or 0
    if not hours or not str(hours).isdigit():
      hours = 0.0
    minutes = request.values.get('report_minutes', str(report.minutes)).strip() or 0
    if not minutes or not str(minutes).isdigit():
      minutes = 0.0
    report.duration = float(hours) + (float(minutes) / 60)
    
    report.summary = request.values.get('report_summary', report.summary).strip()
    report.status = int(request.form.get('report_status', report.status).strip())
    report.account_id = account.id
    validationErrors = report.validate()
    if request.values.get('no_validate', None):
      status = 200
      description = 'OK'
    elif not validationErrors:
      report.save()
      
      for report_clone_due_date in report_due_date_list:
        if report_clone_due_date == report.due_date:
          continue
        reportClone = Report()
        reportClone.reporter_id = report.reporter_id
        reportClone.project_id = report.project_id
        reportClone.component_id = report.component_id
        reportClone.summary = report.summary
        reportClone.status = report.status
        reportClone.duration = report.duration
        reportClone.account_id = report.account_id
        reportClone.due_date = report_clone_due_date
        reportCloneValidationErrors = reportClone.validate()
        if not reportCloneValidationErrors:
          reportClone.save()
          print 'reportClone: saved'
      
      status = 200
      description = 'OK'
      if request.is_ajax:
        return Response(json.dumps({
          'html':render_template('_popup.html', title=g._t( 'report submit success' ), message=g._t( 'report submit success message' ), javascript="""setTimeout(function(){$('form[name=statistics-form]').submit(); $('form[name=filter-form]').submit();}, 300);"""),
          'status':status,
          'description':description,
          'errors':validationErrors
        }), mimetype='application/json')
      else:
        flash( g._t( 'report submit success' ) )
        return redirect( url_for( 'report_index', account_id=account_id ) )
    else:
      status = 400
      description = 'Bad request'
  else:
    status = 200
    description = 'OK'
    validationErrors = []
  
  if report.due_date:
    report_due_date_list.insert(0, report.due_date)
    
  report.due_date = ','.join(report_due_date_list)
  
  """
  If the report exists, but the account is no longer a member of the project, 
  we avoid an ability to change the project by keeping the only project option available
  """
  header = _activityHeader(employees=[account])
  projectList = header['projects']
  if report.id and report.component and not report.component in projectList:
    projectList = [report.component]
  
  if request.is_ajax:
    htmlContent = render_template('report/report.edit-popup.html', account=account, title=title, report=report, errors=validationErrors, projectList=projectList)
    return  Response(json.dumps({'html':htmlContent, 'status':status, 'description':description, 'errors':validationErrors}), mimetype='application/json')
  else:
    htmlContent = render_template('report/report.edit.html', account=account, title=title, report=report, errors=validationErrors, projectList=projectList)
    return htmlContent
Ejemplo n.º 28
0
def activity_statistics(account_id=None):
  from models.account import Account
  from models.report import Report
  from helpers.report import ReportHelper
  
  account = Account.query.filter_by(id=account_id).first()
  if not account:
    return Response(json.dumps({'status':404, 'description':'Not found', 'errors':['not found']}), mimetype='application/json')
  elif not app.access('activity', account=account):
    return Response(json.dumps({'status':403, 'description':'Not authorized', 'errors':['not authorized']}), mimetype='application/json')
  
  header = _activityHeader(employees=[account])
  
  filters = {}
  #filters['project'] = header['projects']
  # to allow the users ses all their reports
  filters['project'] = None
  filters['employee'] = [account.id for account in header['employees']]
  filters['start_date'] = header['start_date']
  filters['end_date'] = header['end_date']
  
  dataReports = []
  if app.access('report', action='administer'):
    dataReports = ReportHelper.listReports(
      start_date=filters['start_date'],
      end_date=filters['end_date'],
      accounts=filters['employee'],
      components=filters['project']
    )
  elif app.access('report', action='list'):
    dataReports = ReportHelper.listActiveReports(
      start_date=filters['start_date'],
      end_date=filters['end_date'],
      accounts=filters['employee'],
      components=filters['project']
    )
  else:
    return Response(json.dumps({'status':403, 'description':'Not authorized', 'errors':['not authorized']}), mimetype='application/json')
  
  statistics = {
    'hrs_day': 0.0,
    'hrs_week': 0.0,
    'hrs_month': 0.0,
    'tasks_day': 0,
    'tasks_week': 0,
    'tasks_month': 0,
    'projects_day': {},
    'projects_week': {},
    'projects_month': {}
  }
  
  for report in dataReports:
    if report.due_date == g._constant()['DATE']['TODAY']:
      statistics['hrs_day'] += report.duration
      statistics['tasks_day'] += 1
      if not statistics['projects_day'].has_key(report.path):
        statistics['projects_day'][report.path] = 0.0
      statistics['projects_day'][report.path] += report.duration
    if report.due_date >= g._constant()['DATE']['WEEK']:
      statistics['hrs_week'] += report.duration
      statistics['tasks_week'] += 1
      if not statistics['projects_week'].has_key(report.path):
        statistics['projects_week'][report.path] = 0.0
      statistics['projects_week'][report.path] += report.duration
    if report.due_date >= g._constant()['DATE']['MONTH']:
      statistics['hrs_month'] += report.duration
      statistics['tasks_month'] += 1
      if not statistics['projects_month'].has_key(report.path):
        statistics['projects_month'][report.path] = 0.0
      statistics['projects_month'][report.path] += report.duration
  
  html = render_template('report/dashboard.html', statistics=statistics, filters=filters)
  
  return Response(json.dumps({'status':200, 'description':'OK', 'data':statistics, 'html':html, 'filters':filters, 'errors':[]}), mimetype='application/json')
Ejemplo n.º 29
0
def activity_data():
  from models.account import Account
  from models.project import Project
  from models.report import Report
  from helpers.report import ReportHelper
  import time
  
  if not app.access('activity', account=g.account):
    return Response(json.dumps({'status':403, 'description':'Not authorized', 'errors':['not authorized']}), mimetype='application/json')
  
  header = _activityHeader()
  
  filters = {}
  filters['project'] = request.values.getlist('filter[project]') or [project.id for project in header['projects']]
  # uncomment this line if you need to make sure that the employees would see all reports, whether they are members or not
  #filters['project'] = request.values.getlist('filter[project]') or None
  filters['employee'] = request.values.getlist('filter[employee]') or [account.id for account in header['employees']]
  filters['start_date'] = header['start_date']
  filters['end_date'] = header['end_date']
  
  header['reports'] = []
  if app.access('report', action='administer'):
    header['reports'] = ReportHelper.listReports(
      start_date=filters['start_date'],
      end_date=filters['end_date'],
      accounts=filters['employee'],
      components=filters['project']
    )
  elif app.access('report', action='list'):
    header['reports'] = ReportHelper.listActiveReports(
      start_date=filters['start_date'],
      end_date=filters['end_date'],
      accounts=filters['employee'],
      components=filters['project']
    )
  else:
    header['reports'] = []
  
  for reportIndex in range(len(header['reports'])):
    reportDict = {
      'id': header['reports'][reportIndex].id,
      'offline': header['reports'][reportIndex].offline,
      'due_date': header['reports'][reportIndex].due_date,
      'duration': header['reports'][reportIndex].duration,
      'summary': header['reports'][reportIndex].summary,
      'project_id': header['reports'][reportIndex].project_id,
      'component_id': header['reports'][reportIndex].component_id,
      'account_id': header['reports'][reportIndex].account_id,
      'reporter_id': header['reports'][reportIndex].reporter_id,
      'created': header['reports'][reportIndex].created,
      'modified': header['reports'][reportIndex].modified,
      'status': header['reports'][reportIndex].status,
      'deleted': (header['reports'][reportIndex].status & Report.STATUS_DELETED > 0)
    }
    reportDict['labels'] = {
      'date': header['reports'][reportIndex].due_date,
      'path': header['reports'][reportIndex].path,
      'account': header['reports'][reportIndex].account.__str__(),
      'project': header['reports'][reportIndex].project.__str__(),
      'component': header['reports'][reportIndex].component.__str__()
    }
    reportDict['links'] = {
      'edit': url_for('report_edit', account_id=urllib.quote_plus(str(header['reports'][reportIndex].account_id)), report_id=urllib.quote_plus(str(header['reports'][reportIndex].id))),
      'delete': url_for('report_delete', account_id=urllib.quote_plus(str(header['reports'][reportIndex].account_id)), report_id=urllib.quote_plus(str(header['reports'][reportIndex].id))),
      'account': url_for('profile_view', account_id=urllib.quote_plus(str(header['reports'][reportIndex].account_id))),
      'project': url_for('project_view', project_id=urllib.quote_plus(str(header['reports'][reportIndex].project_id))),
      'component': url_for('project_view', project_id=urllib.quote_plus(str(header['reports'][reportIndex].project_id)))
    }
    
    header['reports'][reportIndex] = reportDict
  
  header['employees'] = [account.alias for account in header['employees']]
  header['projects'] = [component.path for component in header['projects']]
  header['skip_projects'] = [component.path for component in header['skip_projects']]
  
  return Response(json.dumps({'status':200, 'description':'OK', 'data':header, 'filters':filters, 'errors':[]}), mimetype='application/json')
Ejemplo n.º 30
0
def project_labels(project_id):
  from models.project import Project, Label
  
  project_id = urllib.unquote_plus(project_id)
  project = Project.query.filter_by(id=project_id).first()
  if not project:
    abort(404)
  elif not app.access('project', action='update', project=project):
    abort(403)
  
  title = g._t('project labels')
  
  breadcrumbs = (
    (g._t('projects'), url_for('project_index')),
    (project.__str__(), url_for('project_view', project_id=urllib.quote_plus(str(project_id)))),
    (title, "#")
  )
  
  if (request.form.get('method') == 'PUT' or request.method == 'PUT') and request.form.get('csrf_token'):
    submittedLabel = Label.query.filter_by(project=project, id=request.form.get('label_id')).first()
    if submittedLabel:
      submittedLabel.title = request.form.get('label_title', '')
    
      if not submittedLabel.validate():
        submittedLabel.save()
        
        flash( g._t('label update success'))
        return redirect(url_for('project_labels', project_id=urllib.quote_plus(str(project_id))))
    else:
      flash( g._t('label not found'), 'error')
    
  elif (request.form.get('method') == 'DELETE' or request.method == 'DELETE') and request.form.get('csrf_token'):
    submittedLabel = Label.query.filter_by(project=project, id=request.form.get('label_id')).first()
    if submittedLabel:
      submittedLabel.delete()
      
      # project may not have zero labels, default one will be set
      if not Label.query.filter_by(project_id=project.id, title=Label.LABEL_DEFAULT).first():
        label = Label()
        label.project_id = project.id
        label.title = Label.LABEL_DEFAULT
        label.save()
      
      flash( g._t('label delete success'))
      return redirect(url_for('project_labels', project_id=urllib.quote_plus(str(project_id))))
    else:
      flash( g._t('label not found'), 'error')
    
  elif (request.form.get('method') == 'POST' or request.method == 'POST') and request.form.get('csrf_token'):
    submittedLabel = Label()
    submittedLabel.project_id = project_id
    submittedLabel.title = request.form.get('label_title', '')
    
    if not submittedLabel.validate():
      submittedLabel.save()
      
      flash( g._t('label create success'))
      return redirect(url_for('project_labels', project_id=urllib.quote_plus(str(project_id))))
    
  else:
    submittedLabel = Label()
  
  return render_template('project/labels.html', project_id=project_id, project=project, submittedLabel=submittedLabel, title=title, breadcrumbs=breadcrumbs)