view website/issues/schema.py @ 7971:fe0348bbe45b

issue2551353 - Add roundup-classhelper for 2.4.0 release Changes to the classic template are not done yet. Still testing. This commit has document updates and changes to rest.py. rest.py: add /rest/data/user/role endpoint to core so the user doesn't have to add the /rest/roles endpoint via interfaces.py. It will only send roles for a user with Admin role and there is no way to override this currently. acknowledgements.txt: Added members of team3 to other contributors. Specified for all other contributes what they worked on. upgrading.txt: added classhelper section and basic template change directions. Linked to admin_guide for full directions. admin_guide.txt: documented install, translation, troubleshooting, config etc. user_guide.txt: added section on using the classhelper. Added reference to section earlier in the doc. Added image for section.
author John Rouillard <rouilj@ieee.org>
date Tue, 21 May 2024 01:17:28 -0400
parents 35a162c8977c
children
line wrap: on
line source


#
# TRACKER SCHEMA
#

# Class automatically gets these properties:
#   creation = Date()
#   activity = Date()
#   creator = Link('user')
#   actor = Link('user')

# Issue Type
issue_type = Class(db, 'issue_type',
                   name=String(),
                   description=String(),
                   order=Number())
issue_type.setkey('name')

# Component
component = Class(db, 'component',
                  name=String(),
                  description=String(),
                  order=Number(),
                  assign_to=Link('user'))
component.setkey('name')

# Version
version = Class(db, 'version',
                name=String(),
                description=String(),
                order=Number())
version.setkey('name')

# Severity
severity = Class(db, 'severity',
                 name=String(),
                 description=String(),
                 order=Number())
severity.setkey('name')

# Priority
priority = Class(db, 'priority',
                 name=String(),
                 description=String(),
                 order=Number())
priority.setkey('name')

# Status
status = Class(db, "status",
               name=String(),
               description=String(),
               order=Number())
status.setkey("name")

# Resolution
resolution = Class(db, "resolution",
                   name=String(),
                   description=String(),
                   order=Number())
resolution.setkey('name')

# Keyword
keyword = Class(db, "keyword",
                name=String(),
                description=String())
keyword.setkey("name")
                

# User-defined saved searches
query = Class(db, "query",
              klass=String(),
              name=String(),
              url=String(),
              private_for=Link('user'))

# add any additional database schema configuration here

user = Class(db, "user",
             username=String(),
             password=Password(),
             address=String(),
             realname=String(),
             organisation=String(),
             alternate_addresses=String(),
             queries=Multilink('query'),
             roles=String(),     # comma-separated string of Role names
             timezone=String())
user.setkey("username")

# FileClass automatically gets this property in addition to the Class ones:
#   content = String()    [saved to disk in <tracker home>/db/files/]
#   type = String()       [MIME type of the content, default 'text/plain']
msg = FileClass(db, "msg",
                author=Link("user", do_journal='no'),
                recipients=Multilink("user", do_journal='no'),
                date=Date(),
                summary=String(),
                files=Multilink("file"),
                messageid=String(),
                inreplyto=String(),
                spambayes_score=Number(),
                spambayes_misclassified=Boolean(),)

file = FileClass(db, "file",
                name=String(),
                description=String(indexme='yes'),
                spambayes_score=Number(),
                spambayes_misclassified=Boolean(),)

# IssueClass automatically gets these properties in addition to the Class ones:
#   title = String()
#   messages = Multilink("msg")
#   files = Multilink("file")
#   nosy = Multilink("user")
#   superseder = Multilink("issue")
issue = IssueClass(db, "issue",
                   type=Link('issue_type'),
                   components=Multilink('component'),
                   versions=Multilink('version'),
                   severity=Link('severity'),
                   priority=Link('priority'),
                   dependencies=Multilink('issue'),
                   assignee=Link('user'),
                   status=Link('status'),
                   resolution=Link('resolution'),
                   superseder=Link('issue'),
                   keywords=Multilink("keyword"))
db.security.addPermission(name='Register', klass='user',
    description='User is allowed to register new user')


#
# TRACKER SECURITY SETTINGS
#
# See the configuration and customisation document for information
# about security setup.

db.security.addRole(name='Developer', description='A developer')
db.security.addRole(name='Coordinator', description='A coordinator')

db.security.addPermission(name="SB: May Classify")
db.security.addPermission(name="SB: May Report Misclassified")

#
# REGULAR USERS
#
# Give the regular users access to the web and email interface
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, 'Web Access')
    db.security.addPermissionToRole(r, 'Email Access')

##########################
# User permissions
##########################

for cl in ('issue_type', 'severity', 'component',
           'version', 'priority', 'status', 'resolution',
           'issue', 'keyword'):
    db.security.addPermissionToRole('User', 'View', cl)
    db.security.addPermissionToRole('Anonymous', 'View', cl)

class may_view_spam:
    def __init__(self, klassname):
        self.klassname = klassname

    def __call__(self, db, userid, itemid):
        cutoff_score = float(db.config.detectors['SPAMBAYES_SPAM_CUTOFF'])
        klass = db.getclass(self.klassname)

        try:
            score = klass.get(itemid, 'spambayes_score')
        except KeyError:
            return True

        if score > cutoff_score:
            return False

        return True

for cl in ('file', 'msg'):
    p = db.security.addPermission(name='View', klass=cl,
                                  description="allowed to see metadata object regardless of spam status",
                                  properties=('id', 'creation', 'activity',
                                              'creator', 'actor',
                                              'name', 'spambayes_score',
                                              'spambayes_misclassified',
                                              'author', 'recipients',
                                              'date', 'files', 'messageid',
                                              'inreplyto', 'type',
                                              'description',
                                              ))

    db.security.addPermissionToRole('Anonymous', p)
    db.security.addPermissionToRole('User', p)

    db.security.addPermissionToRole('User', 'Create', cl)

    p = db.security.addPermission(name='View', klass=cl,
                                  description="Allowed to see content of object regardless of spam status",
                                  properties = ('content', 'summary'))
    
    db.security.addPermissionToRole('User', p)        
    
    #spamcheck = db.security.addPermission(name='View', klass=cl,
    #                                      description="allowed to see content if not spam",
    #                                      properties=('content', 'summary'),
    #                                      check=may_view_spam(cl))

    #db.security.addPermissionToRole('Anonymous', spamcheck)

def may_edit_file(db, userid, itemid):
    return userid == db.file.get(itemid, "creator")
p = db.security.addPermission(name='Edit', klass='file', check=may_edit_file,
    description="User is allowed to remove their own files")
db.security.addPermissionToRole('User', p)

p = db.security.addPermission(name='Create', klass='issue',
                              properties=('title', 'type',
                                          'components', 'versions',
                                          'severity',
                                          'messages', 'files', 'nosy'),
                              description='User can report and discuss issues')
db.security.addPermissionToRole('User', p)

p = db.security.addPermission(name='Edit', klass='issue',
                              properties=('title', 'type',
                                          'components', 'versions',
                                          'severity', 'status',
                                          'messages', 'files', 'nosy'),
                              description='User can report and discuss issues')
db.security.addPermissionToRole('User', p)

#db.security.addPermissionToRole('User', 'SB: May Report Misclassified')



##########################
# Developer permissions
##########################
for cl in ('issue_type', 'severity', 'component',
           'version', 'priority', 'status', 'resolution',
           'issue', 'file', 'msg', 'keyword'):
    db.security.addPermissionToRole('Developer', 'View', cl)

for cl in ('issue', 'file', 'msg', 'keyword'):
    db.security.addPermissionToRole('Developer', 'Edit', cl)
    db.security.addPermissionToRole('Developer', 'Create', cl)


##########################
# Coordinator permissions
##########################
for cl in ('issue_type', 'severity', 'component',
           'version', 'priority', 'status', 'resolution', 'issue', 'file', 'msg'):
    db.security.addPermissionToRole('Coordinator', 'View', cl)
    db.security.addPermissionToRole('Coordinator', 'Edit', cl)
    db.security.addPermissionToRole('Coordinator', 'Create', cl)

db.security.addPermissionToRole('Coordinator', 'SB: May Classify')

# Allow Users and Developers to view most user properties.
p =  db.security.addPermission(name='View', klass='user',
   properties=('id', 'username', 'address', 'realname',
         'organisation', 'alternate_addresses', 'timezone'))
db.security.addPermissionToRole('User', p)
db.security.addPermissionToRole('Developer', p)
# Coordinator may view all user properties.
db.security.addPermissionToRole('Coordinator', 'View', 'user')

# allow "Show Unassigned" link to work for anon
p = db.security.addPermission(name='Search', klass='user')
db.security.addPermissionToRole ('Anonymous', p)

# Allow Coordinator to edit any user, including their roles.
db.security.addPermissionToRole('Coordinator', 'Edit', 'user')
db.security.addPermissionToRole('Coordinator', 'Web Roles')

# Users should be able to edit their own details -- this permission is
# limited to only the situation where the Viewed or Edited item is their own.
def own_record(db, userid, itemid):
    '''Determine whether the userid matches the item being accessed.'''
    return userid == itemid
p = db.security.addPermission(name='View', klass='user', check=own_record,
    description="User is allowed to view their own user details")
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, p)
p = db.security.addPermission(name='Edit', klass='user', check=own_record,
    description="User is allowed to edit their own user details",
    properties=('username', 'password',
                'address', 'realname',
                'organisation',
                'alternate_addresses',
                'queries',
                'timezone')) # Note: 'roles' excluded - users should not be able to edit their own roles. 
for r in 'User', 'Developer':
    db.security.addPermissionToRole(r, p)

# Users should be able to edit and view their own queries. They should also
# be able to view any marked as not private. They should not be able to
# edit others' queries, even if they're not private
def view_query(db, userid, itemid):
    private_for = db.query.get(itemid, 'private_for')
    if not private_for: return True
    return userid == private_for
def edit_query(db, userid, itemid):
    return userid == db.query.get(itemid, 'creator')
p = db.security.addPermission(name='View', klass='query', check=view_query,
    description="User is allowed to view their own and public queries")
s = db.security.addPermission(name='Search', klass='query',
    properties=['creator'],
    description="User is allowed to Search queries for creator")
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, p)
    db.security.addPermissionToRole(r, s)
p = db.security.addPermission(name='Edit', klass='query', check=edit_query,
    description="User is allowed to edit their queries")
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, p)
p = db.security.addPermission(name='Create', klass='query',
    description="User is allowed to create queries")
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, p)
p = db.security.addPermission(name='Retire', klass='query', check=edit_query,
    description="User is allowed to retire their queries")
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, p)
p = db.security.addPermission(name='Restore', klass='query', check=edit_query,
    description="User is allowed to restore their queries")
for r in 'User', 'Developer', 'Coordinator':
    db.security.addPermissionToRole(r, p)


#
# ANONYMOUS USER PERMISSIONS
#
# Let anonymous users access the web interface. Note that almost all
# trackers will need this Permission. The only situation where it's not
# required is in a tracker that uses an HTTP Basic Authenticated front-end.
db.security.addPermissionToRole('Anonymous', 'Web Access')

# Let anonymous users access the email interface (note that this implies
# that they will be registered automatically, hence they will need the
# "Create" user Permission below)
# This is disabled by default to stop spam from auto-registering users on
# public trackers.
#db.security.addPermissionToRole('Anonymous', 'Email Access')

# Assign the appropriate permissions to the anonymous user's Anonymous
# Role. Choices here are:
# - Allow anonymous users to register
db.security.addPermissionToRole('Anonymous', 'Register', 'user')

# Allow anonymous users access to view issues (and the related, linked
# information).

for cl in 'issue', 'severity', 'status', 'resolution', 'msg', 'file':
    db.security.addPermissionToRole('Anonymous', 'View', cl)

# [OPTIONAL]
# Allow anonymous users access to create or edit "issue" items (and the
# related file and message items)
#for cl in 'issue', 'file', 'msg':
#   db.security.addPermissionToRole('Anonymous', 'Create', cl)
#   db.security.addPermissionToRole('Anonymous', 'Edit', cl)


# vim: set filetype=python sts=4 sw=4 et si :


Roundup Issue Tracker: http://roundup-tracker.org/