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)
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)
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
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']))
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)
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 )
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)
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)
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')
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)
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"]')
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> </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 )
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)
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)
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)
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']))
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)
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> </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)
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)
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)
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 )
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)
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
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)
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"]')
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
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
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')
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')
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)