def notify_now(self, notification_frequency):
        """
        Send notification email to project watchers.

        :param str notification_frequency: The notification frequency, used to fetch
            users which have something on that watchlist.
        """
        store = CQDEWatchlistStore()
        watches = store.get_by_notification(notification_frequency)

        notifylist = {}
        for w in watches:
            if notifylist.get(w.project_id) is None:
                notifylist[w.project_id] = []
            notifylist[w.project_id].append(w.user_id)

        userstore = get_userstore()

        counter = 0
        for project_id in notifylist.keys():
            project = Project.get(id=project_id)

            # Get all events for this project
            events = self._get_project_events(project, notification_frequency)

            # Send one email per user, because everyone may have a different
            # set of permissions (i.e. which events he/she has permission to see)
            for user_id in notifylist[project_id]:
                user = userstore.getUserWhereId(user_id)
                if user:
                    # filter eventlist by user's permissions
                    filtered_events = WatchlistEvents(self.env).filter_events(
                        events, user, project)
                    if filtered_events:
                        addresses = [user.mail]
                        message = self._format_message(user, project,
                                                       filtered_events)
                        title = "Project updated: %s" % project.env_name
                        mail = EmailNotifier(self.env,
                                             subject=title,
                                             data={'body': message})
                        mail.notify_emails(addresses)
                        self.env.log.debug('Sent email notification to: %s' %
                                           user)
                        counter += 1
                    else:
                        if notification_frequency != 'immediate':
                            self.env.log.debug(
                                'No events to sent to %s about %s' %
                                (user, project))
                else:
                    self.env.log.warning(
                        'User %d in notification list was not found in userstore'
                        % user_id)

        # Log the results
        self.env.log.info('Sent %s watchlist notifications (%s)' %
                          (counter, notification_frequency))
Esempio n. 2
0
    def get_project_watchers(self, projects):
        """ Returns a map of project watchers.
            project_id => number of watchers
        """
        w = CQDEWatchlistStore()
        project_watchers = {}

        for project in projects:
            watchlist = w.get_watchers_by_project(project.id)
            project_watchers[project.id] = len(watchlist)

        return project_watchers
Esempio n. 3
0
    def get_project_watchers(self, projects):
        """ Returns a map of project watchers.
            project_id => number of watchers
        """
        w = CQDEWatchlistStore()
        project_watchers = {}

        for project in projects:
            watchlist = w.get_watchers_by_project(project.id)
            project_watchers[project.id] = len(watchlist)

        return project_watchers
Esempio n. 4
0
    def follow_project(self, user_name, group_name):
        """
        Sets user to follow project if group is correct.

        :param list user_name: username for get user object
        :param list group_name: groupname to check correct group
        """
        if self.env is not None:
            if group_name == 'Members' or group_name == 'Owners':
                from multiproject.common.projects.project import Project
                project = Project.get(None, None, _get_trac_project_name(self.env))
                user = conf.getUserStore().getUser(user_name)
                from multiproject.core.watchlist import CQDEWatchlistStore
                watch_store = CQDEWatchlistStore()
                watch_store.watch_project(user.id, project.id)
    def notify_now(self, notification_frequency):
        """
        Send notification email to project watchers.

        :param str notification_frequency: The notification frequency, used to fetch
            users which have something on that watchlist.
        """
        store = CQDEWatchlistStore()
        watches = store.get_by_notification(notification_frequency)

        notifylist = {}
        for w in watches:
            if notifylist.get(w.project_id) is None:
                notifylist[w.project_id] = []
            notifylist[w.project_id].append(w.user_id)

        userstore = get_userstore()

        counter = 0
        for project_id in notifylist.keys():
            project = Project.get(id=project_id)

            # Get all events for this project
            events = self._get_project_events(project, notification_frequency)

            # Send one email per user, because everyone may have a different
            # set of permissions (i.e. which events he/she has permission to see)
            for user_id in notifylist[project_id]:
                user = userstore.getUserWhereId(user_id)
                if user:
                    # filter eventlist by user's permissions
                    filtered_events = WatchlistEvents(self.env).filter_events(events, user, project)
                    if filtered_events:
                        addresses = [user.mail]
                        message = self._format_message(user, project, filtered_events)
                        title = "Project updated: %s" % project.env_name
                        mail = EmailNotifier(self.env, subject=title, data={'body':message})
                        mail.notify_emails(addresses)
                        self.env.log.debug('Sent email notification to: %s' % user)
                        counter += 1
                    else:
                        if notification_frequency != 'immediate':
                            self.env.log.debug('No events to sent to %s about %s' % (user, project))
                else:
                    self.env.log.warning('User %d in notification list was not found in userstore' % user_id)

        # Log the results
        self.env.log.info('Sent %s watchlist notifications (%s)' % (counter, notification_frequency))
Esempio n. 6
0
    def save_watchlist(self, req):
        user = get_userstore().getUser(req.authname)
        if not user:
            return

        w = CQDEWatchlistStore()
        if req.args.get('notification'):
            notifylist = self.__to_list(req.args.get('notification'))
            for item in notifylist:
                project_id, notification = item.split('_')
                w.watch_project(user.id, project_id, notification)

        if req.args.get('remove'):
            removelist = self.__to_list(req.args.get('remove'))
            for project_id in removelist:
                w.unwatch_project(user.id, project_id)
    def test_get_by_notification(self):
        w = CQDEWatchlistStore()
        w.watch_project(32, 23, "immediate")
        w.watch_project(34, 23, "daily")

        watchlist = w.get_by_notification("daily")
        self.assertTrue(len(watchlist) == 1)
        self.assertTrue(watchlist[0].user_id == 34)

        watchlist = w.get_by_notification("weekly")
        self.assertTrue(len(watchlist) == 0)
    def render_preference_panel(self, req, panel):

        if req.authname == 'anonymous':
            raise TracError("Can't change preferences!", "No access!")

        if req.method == 'POST':
            self.save_watchlist(req)

        watchlist = []
        projects = {}
        user = get_userstore().getUser(req.authname)
        w = CQDEWatchlistStore()
        if user:
            watchlist = w.get_projects_by_user(user.id)
            # TODO: inefficient querying
            for watch in watchlist:
                projects[watch.project_id] = Project.get(id=watch.project_id)
        return 'multiproject_user_prefs_watchlist.html', { 'watchlist': watchlist, 'projects' : projects,
            'notification_values': w.notifications }
    def test_watch(self):
        w = CQDEWatchlistStore()
        self.assertTrue(w)
        w.watch_project(32, 23)
        w.watch_project(34, 23, "daily")

        watchlist = w.get_projects_by_user(32)
        self.assertTrue(len(watchlist) == 1)
        self.assertTrue(watchlist[0].user_id == 32)
        self.assertTrue(watchlist[0].project_id == 23)
        self.assertTrue(watchlist[0].notification == "immediate")

        watchlist = w.get_watchers_by_project(23)
        self.assertTrue(len(watchlist) == 2)
        self.assertTrue(w.is_watching(32, 23))
        self.assertTrue(w.is_watching(34, 23))
    def test_get_by_notification(self):
        w = CQDEWatchlistStore()
        w.watch_project(32, 23, "immediate")
        w.watch_project(34, 23, "daily")

        watchlist = w.get_by_notification("daily")
        self.assertTrue(len(watchlist) == 1)
        self.assertTrue(watchlist[0].user_id == 34)

        watchlist = w.get_by_notification("weekly")
        self.assertTrue(len(watchlist) == 0)
Esempio n. 11
0
    def _get_status(self, req, project_id):
        """
        Returns the watching status as a tuple:

        - Number of followers
        - True/False whether current user is already following or not

        :param req: Trac Request
        :return: Status
        :rtype: tuple
        """
        # Load watching info
        userstore = get_userstore()
        user = userstore.getUser(req.authname)
        watchstore = CQDEWatchlistStore()
        is_watching = False

        # NOTE: Some environments may not have special anonymous/authenticated users, thus user can be None
        if user:
            is_watching = watchstore.is_watching(user.id, project_id)
        watchers = len(watchstore.get_watchers_by_project(project_id))

        return watchers, is_watching
    def test_watch(self):
        w = CQDEWatchlistStore()
        self.assertTrue(w)
        w.watch_project(32, 23)
        w.watch_project(34, 23, "daily")

        watchlist = w.get_projects_by_user(32)
        self.assertTrue(len(watchlist) == 1)
        self.assertTrue(watchlist[0].user_id == 32)
        self.assertTrue(watchlist[0].project_id == 23)
        self.assertTrue(watchlist[0].notification == "immediate")

        watchlist = w.get_watchers_by_project(23)
        self.assertTrue(len(watchlist) == 2)
        self.assertTrue(w.is_watching(32, 23))
        self.assertTrue(w.is_watching(34, 23))
Esempio n. 13
0
    def _get_status(self, req, project_id):
        """
        Returns the watching status as a tuple:

        - Number of followers
        - True/False whether current user is already following or not

        :param req: Trac Request
        :return: Status
        :rtype: tuple
        """
        # Load watching info
        userstore = get_userstore()
        user = userstore.getUser(req.authname)
        watchstore = CQDEWatchlistStore()
        is_watching = False

        # NOTE: Some environments may not have special anonymous/authenticated users, thus user can be None
        if user:
            is_watching = watchstore.is_watching(user.id, project_id)
        watchers = len(watchstore.get_watchers_by_project(project_id))

        return watchers, is_watching
Esempio n. 14
0
    def _get_watchlist_events(self, user):
        watchlist = CQDEWatchlistStore().get_projects_by_user(user.id)
        events = []
        event_helper = WatchlistEvents(self.env)

        # TODO: inefficient querying
        for watch in watchlist:
            project = Project.get(id=watch.project_id)
            project_events = event_helper.get_project_events(project, days = 7, minutes = 0)
            # filter eventlist by user's permissions
            project_events = event_helper.filter_events(project_events, user, project)
            if project_events:
                # show only one event per project
                events.append(project_events[0])

        events.sort(lambda x, y: cmp(y[1]['date'], x[1]['date']))
        return events
    def _get_watchlist_events(self, req):
        events = []
        user = get_userstore().getUser(req.authname)
        if not user:
            return None

        watchlist = CQDEWatchlistStore().get_projects_by_user(user.id)
        event_helper = WatchlistEvents(self.env)
        # TODO: inefficient querying
        for watch in watchlist:
            project = Project.get(id=watch.project_id)
            project_events = event_helper.get_project_events(project,
                                                             days=7,
                                                             minutes=0)
            # filter eventlist by user's permissions
            project_events = event_helper.filter_events(
                project_events, user, project)
            if project_events:
                events.extend(project_events)

        events.sort(lambda x, y: cmp(y[1]['date'], x[1]['date']))
        return events
Esempio n. 16
0
    def process_request(self, req):
        """
        Handles the request

        :param req: Request
        :return: json
        """
        if req.method != 'POST':
            raise TracError('Invalid request')

        req.perm.require('TIMELINE_VIEW')

        userstore = get_userstore()
        watchstore = CQDEWatchlistStore()
        action = req.args.get('action')
        project_id = 0

        # Determine project id from URL
        match = REQ_REGEXP.match(req.path_info)
        if match:
            project_id = int(match.group('pid'))

        # Load userinfo
        user = userstore.getUser(req.authname)
        uid = user.id if user else None

        #load project
        project = Project.get(id=project_id)

        # Start following
        if action == 'watch':
            watchstore.watch_project(uid, project_id)

            # Notify listeners.
            for listener in self.project_change_listeners:
                try:
                    listener.project_watchers(project)
                except:
                    pass

        # Stop following
        elif action == 'unwatch':
            watchstore.unwatch_project(uid, project_id)

        goto = req.args.get('goto', req.href(''))
        return req.redirect(goto)
    def save_watchlist(self, req):
        user = get_userstore().getUser(req.authname)
        if not user:
            return

        w = CQDEWatchlistStore()
        if req.args.get('notification'):
            notifylist = self.__to_list(req.args.get('notification'))
            for item in notifylist:
                project_id, notification = item.split('_')
                w.watch_project(user.id, project_id, notification)
                
                # Notify listeners.
                project = Project.get(id=project_id)
                for listener in self.project_change_listeners:
                    listener.project_watchers(project)

        if req.args.get('remove'):
            removelist = self.__to_list(req.args.get('remove'))
            for project_id in removelist:
                w.unwatch_project(user.id, project_id)
    def test_unwatch(self):
        w = CQDEWatchlistStore()
        w.watch_project(32, 23, "immediate")
        w.watch_project(34, 23, "daily")

        w.unwatch_project(32, 23)

        watchlist = w.get_projects_by_user(32)
        self.assertTrue(len(watchlist) == 0)
        watchlist = w.get_projects_by_user(34)
        self.assertTrue(len(watchlist) == 1)

        watchlist = w.get_watchers_by_project(23)
        self.assertTrue(len(watchlist) == 1)
        self.assertFalse(w.is_watching(32, 23))
Esempio n. 19
0
    def create_project(self, req):
        """ Handler for creating project request
        """
        req.perm.require("PROJECT_CREATE")
        if req.method != 'POST':
            return self.create_failure(req, 'POST request needed when creating a new project')
        author = get_context(req)['author']
        # If agreement needed but not getting it, show failure
        if conf.project_requires_agreed_terms and not self._is_active_user(req):
            return self.create_failure(req, 'You need to approve legal text to create a project!')

        # Read and transform some variables
        vcs_type = req.args.get('vcstype')
        vcs_name = req.args.get('vcs_name')
        if not self.validate_repository_name(vcs_name):
            return self.create_failure(req, 'Check repository name.')

        parent_project = None
        if "_project_" in req.args:
            parent_project = Project.get(env_name=req.args.get('_project_'))
            self.__require_permissions_for_cloning(req.authname, parent_project)
            vcs_type = conf.getVersionControlType(parent_project.env_name) # TODO: expensive call, probably needed

        # Read settings
        settings = {}
        if vcs_type:
            settings['vcs_type'] = vcs_type
        if vcs_name:
            settings['vcs_name'] = vcs_name

        identifier = req.args.get('prj_short_name')
        name = req.args.get('prj_long_name')
        project_visibility = 'prj_is_public' in req.args

        public = False
        published = None
        if project_visibility:
            public = True
            published = datetime.now()

        # Create project object
        project = Project(
            id = None,
            env_name = identifier,
            project_name = name,
            description = req.args.get('prj_description'),
            author_id = author.id,
            created = None, # Use default which is now()
            public = public,
            published = published
        )

        # Create project environment
        projects = Projects()
        try:
            projects.create_project(project, settings)
        except ProjectValidationException as exc:
            self.log.warning('Project creation failed due the validation: {0}'.format(exc.value))
            return self.create_failure(req, exc.value)
        except:
            self.log.exception('Project creation failed')
            return self.create_failure(req, _("Creating project failed. Try again later."))

        if public:
            projects.add_public_project_visibility(project.id)

        #Add author to follow project
        watch_store = CQDEWatchlistStore()
        watch_store.watch_project(author.id, project.id)

        #Change project trac.ini to support multiple repositories
        project_env_path = conf.getEnvironmentSysPath(project.env_name)
        repo_env_path = conf.getEnvironmentVcsPath(project.env_name, vcs_type, vcs_name)
        os.rename(project_env_path + '/conf/trac.ini', project_env_path + '/conf/trac.ini.bak')
        oldfile = open(project_env_path + '/conf/trac.ini.bak', 'r')
        newfile = open(project_env_path + '/conf/trac.ini', 'w')
        lines = oldfile.readlines()
        for line in lines:
            newfile.write(line)
            if line.startswith('database ='):
                break
        newfile.write('repository_dir =\nrepository_type = svn\n\n[repositories]\n')
        newfile.write('%s.dir = %s\n' % (vcs_name, repo_env_path))
        newfile.write('%s.type = %s\n' % (vcs_name, vcs_type))
        newfile.close()
        oldfile.close()
        os.remove(project_env_path + '/conf/trac.ini.bak')

        # Notify listeners. The project object still exists, but database does not
        for listener in self.project_change_listeners:
            try:
                listener.project_created(project)
                listener.project_watchers(project)
                if public:
                    listener.project_set_public(project)
            except:
                pass


        return self.create_success(req, project)
    def test_unwatch(self):
        w = CQDEWatchlistStore()
        w.watch_project(32, 23, "immediate")
        w.watch_project(34, 23, "daily")

        w.unwatch_project(32, 23)

        watchlist = w.get_projects_by_user(32)
        self.assertTrue(len(watchlist) == 0)
        watchlist = w.get_projects_by_user(34)
        self.assertTrue(len(watchlist) == 1)

        watchlist = w.get_watchers_by_project(23)
        self.assertTrue(len(watchlist) == 1)
        self.assertFalse(w.is_watching(32, 23))
Esempio n. 21
0
    def create_project(self, req):
        """ Handler for creating project request
        """
        req.perm.require("PROJECT_CREATE")
        if req.method != 'POST':
            return self.create_failure(
                req, 'POST request needed when creating a new project')
        author = get_context(req)['author']
        # If agreement needed but not getting it, show failure
        if conf.project_requires_agreed_terms and not self._is_active_user(
                req):
            return self.create_failure(
                req, 'You need to approve legal text to create a project!')

        # Read and transform some variables
        vcs_type = req.args.get('vcstype')
        vcs_name = req.args.get('vcs_name')
        if not self.validate_repository_name(vcs_name):
            return self.create_failure(req, 'Check repository name.')

        parent_project = None
        if "_project_" in req.args:
            parent_project = Project.get(env_name=req.args.get('_project_'))
            self.__require_permissions_for_cloning(req.authname,
                                                   parent_project)
            vcs_type = conf.getVersionControlType(
                parent_project.env_name
            )  # TODO: expensive call, probably needed

        # Read settings
        settings = {}
        if vcs_type:
            settings['vcs_type'] = vcs_type
        if vcs_name:
            settings['vcs_name'] = vcs_name

        identifier = req.args.get('prj_short_name')
        name = req.args.get('prj_long_name')
        project_visibility = 'prj_is_public' in req.args

        public = False
        published = None
        if project_visibility:
            public = True
            published = datetime.now()

        # Create project object
        project = Project(
            id=None,
            env_name=identifier,
            project_name=name,
            description=req.args.get('prj_description'),
            author_id=author.id,
            created=None,  # Use default which is now()
            public=public,
            published=published)

        # Create project environment
        projects = Projects()
        try:
            projects.create_project(project, settings)
        except ProjectValidationException as exc:
            self.log.warning(
                'Project creation failed due the validation: {0}'.format(
                    exc.value))
            return self.create_failure(req, exc.value)
        except:
            self.log.exception('Project creation failed')
            return self.create_failure(
                req, _("Creating project failed. Try again later."))

        if public:
            projects.add_public_project_visibility(project.id)

        #Add author to follow project
        watch_store = CQDEWatchlistStore()
        watch_store.watch_project(author.id, project.id)

        #Change project trac.ini to support multiple repositories
        project_env_path = conf.getEnvironmentSysPath(project.env_name)
        repo_env_path = conf.getEnvironmentVcsPath(project.env_name, vcs_type,
                                                   vcs_name)
        os.rename(project_env_path + '/conf/trac.ini',
                  project_env_path + '/conf/trac.ini.bak')
        oldfile = open(project_env_path + '/conf/trac.ini.bak', 'r')
        newfile = open(project_env_path + '/conf/trac.ini', 'w')
        lines = oldfile.readlines()
        for line in lines:
            newfile.write(line)
            if line.startswith('database ='):
                break
        newfile.write(
            'repository_dir =\nrepository_type = svn\n\n[repositories]\n')
        newfile.write('%s.dir = %s\n' % (vcs_name, repo_env_path))
        newfile.write('%s.type = %s\n' % (vcs_name, vcs_type))
        newfile.close()
        oldfile.close()
        os.remove(project_env_path + '/conf/trac.ini.bak')

        # Notify listeners. The project object still exists, but database does not
        for listener in self.project_change_listeners:
            try:
                listener.project_created(project)
                listener.project_watchers(project)
                if public:
                    listener.project_set_public(project)
            except:
                pass

        return self.create_success(req, project)