def render_admin_panel(self, req, cat, page, path_info): if req.method == 'POST': if req.args.get('projname'): trac_env = req.environ.get('trac.env_parent_dir') + "/" + req.args.get('projname') svn_env = "" if self.repository_dir != "": head, tail = os.path.split(self.repository_dir) svn_env = head + "\\" + req.args.get('projname') repos.svn_repos_create(svn_env, None,None,None,None) if self.inherit_config != None: run([trac_env.encode('ascii'),"initenv", '--inherit=' + self.inherit_config ,req.args.get('projname'),"sqlite:db/trac.db", "svn", svn_env]) run([trac_env.encode('ascii'),"upgrade"]) else: run([trac_env.encode('ascii'),"initenv", req.args.get('projname'),"sqlite:db/trac.db", "svn", svn_env]) run([trac_env.encode('ascii'),"permission", "add", req.authname , "TRAC_ADMIN"]) return 'tram_admin.html',{'projname': req.args.get('projname')}
def execute_setup_action(self, action, args, data, log_cb): from trac.admin.console import run from trac.env import open_environment if '%s' not in args: args = os.path.join(args, '%s') path = args%data['name'] rv = run([path, 'initenv', data['full_name'], 'sqlite:db/trac.db', data.get('repo_type', ''), data.get('repo_dir', ''), ]) data['env'] = open_environment(path, use_cache=True) return rv == 0
def execute_setup_action(self, action, args, data, log_cb): from trac.admin.console import run from trac.env import open_environment if '%s' not in args: args = os.path.join(args, '%s') path = args % data['name'] rv = run([ path, 'initenv', data['full_name'], 'sqlite:db/trac.db', data.get('repo_type', ''), data.get('repo_dir', ''), ]) data['env'] = open_environment(path, use_cache=True) return rv == 0
def add_svn_to_project(application): from penelope.core.models.dashboard import Project project = DBSession.query(Project).get(application.project_id) settings = get_current_registry().settings svnenvs = settings.get('penelope.svn.envs') tracenvs = settings.get('penelope.trac.envs') trac_admin = os.path.abspath('%s/../../bin/trac-admin' % tracenvs) if not os.path.exists(svnenvs): os.mkdir(svnenvs) svnname = application.svn_name if svnname: svn_path = '%s/%s' % (svnenvs, svnname) if not os.path.exists(svn_path): raise OSError, 'The path %s doesn\'t exists!' % svn_path else: idx = '' while (not svnname): svnname = idnormalizer.normalize("%s%s" % (project.id, idx)) svn_path = '%s/%s' % (svnenvs, svnname) if os.path.exists(svn_path): idx = idx and (idx+1) or 1 svnname = None _execute(['svnadmin', '--config-dir', '/etc/subversion', 'create', svn_path]) for trac in project.tracs: tracname = str(trac.trac_name) trac_path = '%s/%s' % (tracenvs, tracname) run([trac_path, 'repository add %s %s' % (svnname, svn_path)]) run([trac_path, 'repository resync %s' % (svnname)]) run([trac_path, 'config set trac repository_sync_per_request ""']) hook_filename = '%s/hooks/post-commit' % svn_path with open(hook_filename, 'w') as hook: opts = {'trac_path': trac_path, 'trac_admin': trac_admin} hook.write(POST_COMMIT_HOOK % opts) st = os.stat(hook_filename) os.chmod(hook_filename, st.st_mode | stat.S_IEXEC) application.api_uri = 'svn://%s' % svnname application.svn_name = svnname
def run_trac_admin(): pkg_resources.require('Trac==%s' % VERSION) sys.exit(run())
def add_trac_to_project(application, smtp_enabled=True, privatecomments=True, sensitivetickets=True, batchmod=True, autocompleteusers=True, customfieldadmin=True, qafields=True, privatetickets=False, tracwysiwyg=True, attachment_max_size=10485760, milestones=[], tickets=[], project_name=u'', ): from penelope.core.models.dashboard import Project project = DBSession.query(Project).get(application.project_id) settings = get_current_registry().settings or application.settings tracenvs = settings.get('penelope.trac.envs') if not os.path.exists(tracenvs): # TODO: logging bootstrap os.mkdir(tracenvs) tracname = None idx = '' while (not tracname): tracname = idnormalizer.normalize("%s%s" % (project.id, idx)) trac_path = '%s/%s' % (tracenvs, tracname) if os.path.exists(trac_path): idx = idx and (idx+1) or 1 tracname = None trac_perm = { 'administrator': ['TRAC_ADMIN', 'EXTRA_TIMEENTRY'], 'customer': ['TICKET_CREATE', 'TICKET_MODIFY', 'TICKET_VIEW', 'WIKI_VIEW', 'XML_RPC', 'CHANGESET_VIEW', 'FILE_VIEW', 'LOG_VIEW', 'MILESTONE_VIEW', 'REPORT_VIEW', 'REPORT_SQL_VIEW', 'ROADMAP_VIEW', 'SEARCH_VIEW', 'TIMELINE_VIEW'], 'developer': ['TICKET_CREATE', 'TICKET_MODIFY', 'TICKET_VIEW', 'WIKI_VIEW', 'XML_RPC', 'WIKI_CREATE', 'WIKI_MODIFY', 'CHANGESET_VIEW', 'FILE_VIEW', 'LOG_VIEW', 'MILESTONE_VIEW', 'REPORT_VIEW', 'REPORT_SQL_VIEW', 'ROADMAP_VIEW', 'SEARCH_VIEW', 'TIMELINE_VIEW', 'REPORT_ADMIN'], 'internal_developer': ['developer', 'TRAC_ADMIN', 'TIME_ENTRY_ADD'], 'external_developer': ['developer'], 'project_manager': ['administrator', 'TIME_ENTRY_ADD'], } pordb = str(DBSession.bind.url) run([trac_path, 'initenv "%s" "%s?schema=trac_%s"' % ( tracname, pordb.replace('postgresql://', 'postgres://'), tracname)]) tracenv = Environment(trac_path) # REPORTS cnx = tracenv.get_db_cnx().cnx cursor = cnx.cursor() cursor.executemany(\ "INSERT INTO report (title, description, query) VALUES (%s, %s, %s)", get_reports(project_id=project.id)) cursor.close() cnx.commit() # remove report 2 cursor = cnx.cursor() cursor.execute("DELETE FROM report where id=2;") cursor.close() cnx.commit() # update reports cursor = cnx.cursor() cursor.execute("""UPDATE report set query=' SELECT p.value AS __color__, t.id AS ticket, summary, t.type AS type, cr.name AS CR, owner, status, time AS created, changetime AS _changetime, t.description AS _description, reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority'' LEFT JOIN ticket_custom tc ON t.id = tc.ticket LEFT JOIN public.customer_requests cr ON tc.value = cr.id WHERE status <> ''closed'' AND tc.name = ''customerrequest'' ORDER BY CAST(p.value AS int), milestone, t.type, time' where id=1;""") cursor.execute("""UPDATE report set query=' SELECT p.value AS __color__, ''Milestone ''||milestone AS __group__, t.id AS ticket, summary, t.type AS type, cr.name AS CR, owner, status, time AS created, changetime AS _changetime, t.description AS _description, reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority'' LEFT JOIN ticket_custom tc ON t.id = tc.ticket LEFT JOIN public.customer_requests cr ON tc.value = cr.id WHERE status <> ''closed'' AND tc.name = ''customerrequest'' ORDER BY (milestone IS NULL),milestone, CAST(p.value AS int), t.type, time' where id=3;""") cursor.execute("""UPDATE report set query=' SELECT p.value AS __color__, owner AS __group__, t.id AS ticket, summary, milestone, cr.name AS CR, t.type AS type, time AS created, changetime AS _changetime, t.description AS _description, reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority'' LEFT JOIN ticket_custom tc ON t.id = tc.ticket LEFT JOIN public.customer_requests cr ON tc.value = cr.id WHERE status = ''accepted'' AND tc.name = ''customerrequest'' ORDER BY owner, CAST(p.value AS int), t.type, time' where id=4;""") cursor.execute("""UPDATE report set query=' SELECT p.value AS __color__, owner AS __group__, t.id AS ticket, summary, milestone, t.type AS type, cr.name AS CR, time AS created, t.description AS _description_, changetime AS _changetime, reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority'' LEFT JOIN ticket_custom tc ON t.id = tc.ticket LEFT JOIN public.customer_requests cr ON tc.value = cr.id WHERE status = ''accepted'' AND tc.name = ''customerrequest'' ORDER BY owner, CAST(p.value AS int), t.type, time' where id=5;""") cursor.execute("""UPDATE report set query=' SELECT p.value AS __color__, (CASE status WHEN ''accepted'' THEN ''Accepted'' ELSE ''Owned'' END) AS __group__, t.id AS ticket, summary, milestone, cr.name AS CR, t.type AS type, priority, time AS created, changetime AS _changetime, t.description AS _description, reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority'' LEFT JOIN ticket_custom tc ON t.id = tc.ticket LEFT JOIN public.customer_requests cr ON tc.value = cr.id WHERE t.status <> ''closed'' AND owner = $USER AND tc.name = ''customerrequest'' ORDER BY (status = ''accepted'') DESC, CAST(p.value AS int), milestone, t.type, time' where id=7;""") cursor.execute("""UPDATE report set query=' SELECT p.value AS __color__, (CASE owner WHEN $USER THEN ''My Tickets'' ELSE ''Active Tickets'' END) AS __group__, t.id AS ticket, summary, milestone, t.type AS type, cr.name AS CR, owner, status, time AS created, changetime AS _changetime, t.description AS _description, reporter AS _reporter FROM ticket t LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority'' LEFT JOIN ticket_custom tc ON t.id = tc.ticket LEFT JOIN public.customer_requests cr ON tc.value = cr.id WHERE status <> ''closed'' AND tc.name = ''customerrequest'' ORDER BY (COALESCE(owner, '''') = $USER) DESC, CAST(p.value AS int), milestone, t.type, time' where id=8;""") cursor.close() cnx.commit() # remove default trac's milestones, components, versions cursor = cnx.cursor() cursor.execute("DELETE FROM milestone;") cursor.close() cnx.commit() cursor = cnx.cursor() cursor.execute("DELETE FROM component;") cursor.close() cnx.commit() cursor = cnx.cursor() cursor.execute("DELETE FROM version;") cursor.close() cnx.commit() # TODO: attualmente il riferimento dal trac al progetto dashboard è il project_id, # considerando un'instalalzzione che condicide lo stesso stack wsgi, # valutare se deve essere una uri (jsnorpc, xmlrpx, ...) # o un dsn che punti al db, o ... tracenv.config.set('por-dashboard', 'project-id', application.project_id) # custom templates templates = settings.get('penelope.trac.templates') masterconfig = settings.get('penelope.trac.masterconfig') if templates: tracenv.config.set('inherit', 'templates_dir', templates) # master config if masterconfig: tracenv.config.set('inherit', 'file', masterconfig) # set name and description tracenv.config.set('project', 'name', project_name) tracenv.config.set('project', 'descr', application.name) tracenv.config.set('notification', 'smtp_enabled', smtp_enabled and 'true' or 'false') tracenv.config.set('notification', 'always_notify_owner', 'true') tracenv.config.set('notification', 'always_notify_reporter', 'true') manager_email = project.manager.email or '' tracenv.config.set('notification', 'smtp_always_cc', manager_email) # manager should always receiv CC tracenv.config.set('attachment', 'max_size', attachment_max_size) tracenv.config.set('components', 'penelope.trac.*', 'enabled') tracenv.config.set('components', 'themeengine.admin.*', 'enabled') tracenv.config.set('components', 'themeengine.api.*', 'enabled') tracenv.config.set('components', 'themeengine.web_ui.*', 'enabled') tracenv.config.set('components', 'ticketrelations.*', 'enabled') tracenv.config.set('components', 'tracopt.perm.config_perm_provider.extrapermissionsprovider', 'enabled') # All the custom permission names are converted to uppercase. # It is not possible to have lowercase and distinguish them from the standard permissions. tracenv.config.set('extra-permissions', 'extra_timeentry', 'TIME_ENTRY_ADD') tracenv.config.set('theme','theme', 'por') # ticket-custom tracenv.config.set('ticket-custom', 'customerrequest', 'select') tracenv.config.set('ticket-custom', 'customerrequest.label', 'Customer Request') tracenv.config.set('ticket-custom', 'blocking', 'text') tracenv.config.set('ticket-custom', 'blocking.label', 'Blocking') tracenv.config.set('ticket-custom', 'blockedby', 'text') tracenv.config.set('ticket-custom', 'blockedby.label', 'Blocked By') # BBB: ii valori di customerrequest vengono caricati ondemand tracenv.config.set('ticket-custom', 'customerrequest.options', '') # see ticket:80 if qafields: tracenv.config.set('ticket-custom', 'issuetype', 'select') tracenv.config.set('ticket-custom', 'issuetype.label', 'Natura del problema') tracenv.config.set('ticket-custom', 'issuetype.options', '|'.join([u"", u"sistemistica", u"funzionalità", u"design (grafica, layout...)", u"prestazioni", u"mi aspettavo che..."])) tracenv.config.set('ticket-custom', 'esogeno', 'checkbox') tracenv.config.set('ticket-custom', 'esogeno.label', 'Ticket aperto dal Cliente') tracenv.config.set('ticket-custom', 'esogeno.value', 'false') tracenv.config.set('ticket-custom', 'stats_exclude', 'checkbox') tracenv.config.set('ticket-custom', 'stats_exclude.label', 'Exclude from report stats') tracenv.config.set('ticket-custom', 'stats_exclude.value', 'false') tracenv.config.set('ticket-custom', 'fasesviluppo', 'select') tracenv.config.set('ticket-custom', 'fasesviluppo.label', 'Fase sviluppo') tracenv.config.set('ticket-custom', 'fasesviluppo.options', '|'.join([u"", u"In lavorazione", u"Per lo staging", u"In staging", u"Per la produzione", u"In produzione"])) tracenv.config.set('ticket', 'restrict_owner', 'true') tracenv.config.set('ticket-custom', 'milestone.invalid_if', '') # WORKFLOW tracenv.config.set('ticket-workflow', 'accept', 'new,reviewing -> assigned') tracenv.config.set('ticket-workflow', 'accept.operations', 'set_owner_to_self') tracenv.config.set('ticket-workflow', 'accept.permissions', 'TICKET_MODIFY') tracenv.config.set('ticket-workflow', 'leave', '* -> *') tracenv.config.set('ticket-workflow', 'leave.default', '1') tracenv.config.set('ticket-workflow', 'leave.operations', 'leave_status') tracenv.config.set('ticket-workflow', 'reassign', 'new,assigned,accepted,reopened -> assigned') tracenv.config.set('ticket-workflow', 'reassign.operations', 'set_owner') tracenv.config.set('ticket-workflow', 'reassign.permissions', 'TICKET_MODIFY') tracenv.config.set('ticket-workflow', 'reassign_reviewing', 'reviewing -> *') tracenv.config.set('ticket-workflow', 'reassign_reviewing.name', 'reassign review') tracenv.config.set('ticket-workflow', 'reassign_reviewing.operations', 'set_owner') tracenv.config.set('ticket-workflow', 'reassign_reviewing.permissions', 'TICKET_MODIFY') tracenv.config.set('ticket-workflow', 'reopen', 'closed -> reopened') tracenv.config.set('ticket-workflow', 'reopen.operations', 'del_resolution') tracenv.config.set('ticket-workflow', 'reopen.permissions', 'TRAC_ADMIN') tracenv.config.set('ticket-workflow', 'resolve', 'new,assigned,reopened,reviewing -> closed') tracenv.config.set('ticket-workflow', 'resolve.operations', 'set_resolution') tracenv.config.set('ticket-workflow', 'resolve.permissions', 'TICKET_MODIFY') tracenv.config.set('ticket-workflow', 'review', 'new,assigned,reopened -> reviewing') tracenv.config.set('ticket-workflow', 'review.operations', 'set_owner') tracenv.config.set('ticket-workflow', 'review.permissions', 'TICKET_MODIFY') tracenv.config.set('milestone-groups', 'closed', 'closed') tracenv.config.set('milestone-groups', 'closed.order', '0') tracenv.config.set('milestone-groups', 'closed.query_args', 'group=resolution') tracenv.config.set('milestone-groups', 'closed.overall_completion', 'true') tracenv.config.set('milestone-groups', 'active', '*') tracenv.config.set('milestone-groups', 'active.order', '1') tracenv.config.set('milestone-groups', 'active.css_class', 'open') tracenv.config.set('milestone-groups', 'new', 'new,reopened') tracenv.config.set('milestone-groups', 'new.order', '2') # navigation tracenv.config.set('metanav', 'logout', 'disabled') # permissions tracenv.config.set('components', 'penelope.trac.users.*', 'enabled') tracenv.config.set('trac', 'permission_store', 'PorPermissionStore') tracenv.config.set('trac', 'show_email_addresses', 'true') # xmlrpc plugin tracenv.config.set('components', 'tracrpc.api.xmlrpcsystem', 'enabled') tracenv.config.set('components', 'tracrpc.xml_rpc.xmlrpcprotocol', 'enabled') tracenv.config.set('components', 'tracrpc.web_ui.rpcweb', 'enabled') tracenv.config.set('components', 'tracrpc.ticket.*', 'enabled') # DynamicFields Plugin tracenv.config.set('components', 'dynfields.rules.*','enabled') tracenv.config.set('components', 'dynfields.web_ui.*','enabled') # User & Roles (ReadOnly !!!) # tracenv.config.set('user_manager', 'user_store', 'PorUserStore') # tracenv.config.set('user_manager', 'attribute_provider', 'PorAttributeProvider') # BatchModifyPlugin if batchmod: tracenv.config.set('components', 'batchmod.web_ui.*', 'enabled') # Traccustomfieldadmin if customfieldadmin: tracenv.config.set('components', 'customfieldadmin.*', 'enabled') # PrivateCommentsPlugin if privatecomments: tracenv.config.set('components', 'privatecomments.privatecomments.*', 'enabled') # PrivateTicketPlugin if privatetickets: tracenv.config.set('components', 'privatetickets.policy.*', 'enabled') tracenv.config.set('trac', 'permission_policies', 'PrivateTicketsPolicy, %s' % tracenv.config.get('trac', 'permission_policies')) trac_perm['customer'].append('TICKET_VIEW_SELF') # SensitiveTicketsPlugin if sensitivetickets: tracenv.config.set('components', 'sensitivetickets.*', 'enabled') tracenv.config.set('trac', 'permission_policies', 'SensitiveTicketsPolicy, %s' % tracenv.config.get('trac', 'permission_policies')) tracenv.config.set('ticket-custom', 'sensitive.show_if_group', 'administrator|developer') # utilizzato se il default e' 1, se il default e' 0 non serve # tracenv.config.set('ticket-custom', 'sensitive.clear_on_hide', 'false') # tracenv.config.set('ticket-custom', 'sensitive.has_permission', 'SENSITIVE_VIEW') tracenv.config.set('ticket-custom', 'sensitive.value', '0') trac_perm['developer'].append('SENSITIVE_VIEW') # tracwysiwyg if tracwysiwyg: tracenv.config.set('components', 'tracwysiwyg.wysiwygmodule', 'enabled') # AutoCompleteUsers if autocompleteusers: tracenv.config.set('components', 'autocompleteusers.autocompleteusers', 'enabled') tracenv.config.set('wiki', 'max_size', 1048576) tracenv.config.set('logging', 'log_file', 'trac.log') tracenv.config.set('logging', 'log_level', 'INFO') tracenv.config.set('logging', 'log_type', 'file') tracenv.config.save() # let's remove notification config - it is set by the global config tracenv.config.remove('notification', 'smtp_from') tracenv.config.remove('notification', 'smtp_from_name') tracenv.config.remove('notification', 'replyto') tracenv.config.remove('notification', 'smtp_replyto') tracenv.config.remove('notification', 'email_sender') tracenv.config.remove('notification', 'smtp_enabled') tracenv.config.remove('notification', 'smtp_host') tracenv.config.remove('notification', 'smtp_port') tracenv.config.remove('notification', 'smtp_password') tracenv.config.remove('notification', 'smtp_username') tracenv.config.remove('trac', 'repository_sync_per_request') tracenv.config.save() run([trac_path, 'upgrade --no-backup']) run([trac_path, 'permission remove anonymous *']) run([trac_path, 'permission remove authenticated *']) for role, perms in trac_perm.items(): for perm in perms: run([trac_path, "permission add %s %s" % (role, perm)]) run([trac_path, "ticket_type add verification"]) # hack to minimize config size run([trac_path, 'config set browser color_scale True']) # add properly milestones milestones.append({'title': 'Backlog', 'due_date': date.today().replace(year=date.today().year+1)}) for milestone in milestones: due = milestone['due_date'] if due: due = milestone['due_date'].strftime('%Y-%m-%d') run([trac_path, 'milestone add "%s" %s' % (milestone['title'], due)]) else: run([trac_path, 'milestone add "%s"' % milestone['title']]) tracenv = Environment(trac_path) for ticket in tickets: # in this moment the customer request has a proper id ticket['status'] = 'new' t = Ticket(tracenv) t.populate(ticket) t.insert() application.api_uri = 'trac://%s' % tracname application.trac_name = tracname