summaryrefslogtreecommitdiffstats
path: root/israwhidebroken/controllers.py
blob: da593672d93d2decba8d2889776225cc4bcd1993 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import turbogears as tg
import fedora
from turbogears import controllers, expose, flash
from israwhidebroken.model import Test, Tree, TestResult, hub
from turbogears import identity, redirect
from cherrypy import request, response
from tw.forms import Form, SingleSelectField, HiddenField
from tw.api import WidgetsList
# from israwhidebroken import json
# import logging
# log = logging.getLogger("israwhidebroken.controllers")

# Simple select widget for submitting test results
# TODO: ajaxify
class ResultForm(Form):
    show_errors = True
    class fields(WidgetsList):
        result = SingleSelectField(options=['none','pass','fail'],
                                   suppress_label=True)
        testid = HiddenField()
        treeid = HiddenField()

fdict = {'none': None, 'pass': 1, 'fail': 0}
def to_int(fstr):
    '''Returns fstr converted to int, or None if fstr is None'''
    if fstr in fdict:
        return fdict[fstr]
    return fstr and int(float(fstr))

archval = {'i386':'0', 'x86_64':'1', 'ppc':'2', 'ppc64':'3'}
def archsort(a,b):
    return cmp(archval.get(a,a), archval.get(b,b))

class Root(controllers.RootController):
    # Main index page
    @expose(template="israwhidebroken.templates.index")
    def index(self, c=None, *args, **kw):
        if not c:
            c = Tree.select().max('compose_id')
            next = None
        else:
            c = to_int(c)
            next = Tree.select(Tree.q.compose_id > c).min('compose_id')
        prev = Tree.select(Tree.q.compose_id < c).max('compose_id')

        treesort = lambda a,b: archsort(a.arch, b.arch)
        trees = sorted(Tree.selectBy(compose_id=c), treesort)
        tests = Test.select(Test.q.id <= 14)
        results = {}
        for tree in trees:
            rdict = dict([(t.id, None) for t in tests])
            for r in tree.results:
                rdict[r.testID] = r
            results[tree.id] = rdict

        result_form = ResultForm('resultform', action=tg.url('/add_result', kw))
        return dict(c=c, prev=prev, next=next,
                    result_form=result_form,
                    in_qa='qa' in identity.current.groups,
                    admin='qa-admin' in identity.current.groups,
                    tests=tests, trees=trees, results=results)

    # JSON RPC calls
    @expose(allow_json=True)
    def get_tests(self):
        tests = Test.select()
        return dict(tests=list(tests))

    @expose(allow_json=True)
    def get_trees(self, *args, **kw):
        tree_results = Tree.selectBy(**kw)
        return dict(trees=list(tree_results))

    @expose(allow_json=True)
    def get_results(self, *args, **kw):
        results_results = TestResults.selectBy(**kw)
        return dict(results=list(results_results))

    # JSON calls that require authentication
    @identity.require(identity.in_group("qa"))
    @expose(allow_json=True)
    def add_tree(self, arch, compose_id, tree_time=None, repodata_time=None):
        # check to see if tree already exists
        tree_result = Tree.selectBy(arch=arch, compose_id=compose_id,
                           tree_time=tree_time, repodata_time=repodata_time)
        if tree_result.count():
            return dict(exc='ValueError', tg_flash='Tree exists')
        t = Tree(arch=arch,
                 compose_id=to_int(compose_id),
                 tree_time=to_int(tree_time),
                 repodata_time=to_int(repodata_time))
        hub.commit()
        return dict(tree=t)

    @identity.require(identity.in_group("qa"))
    @expose(allow_json=True)
    def update_tree(self, treeid, arch=None, compose_id=None, tree_time=None, repodata_time=None):
        tr = list(Tree.selectBy(id=treeid))
        if len(tr) == 0:
            return dict(exc='ValueError', tg_flash='Tree %u not found' % treeid)
        tree = tr[0]
        if arch:
            tree.arch = arch
        if tree_time:
            tree.tree_time = to_int(tree_time)
        if repodata_time:
            tree.repodata_time = to_int(repodata_time)
        if compose_id:
            tree.compose_id = to_int(compose_id)
        hub.commit()
        return dict(tree=tree)

    @identity.require(identity.in_group("qa"))
    @expose(allow_json=True)
    def add_result(self, treeid, testid, result, overwrite=False, *args, **kw):
        if not overwrite:
            # TODO return an exception if there's already a result here
            pass
        tr = TestResult(tree=to_int(treeid),
                        test=to_int(testid),
                        result=to_int(result),
                        userid=identity.current.user.id,
                        bug_id=None)
        hub.commit() # XXX necessary?
        if 'json' in fedora.tg.util.request_format():
            return dict(id=tr.id)
        redirect(tg.url("/", kw))

    @identity.require(identity.in_group("qa"))
    @expose(allow_json=True)
    def delete_result(self, id, *args, **kw):
        tr = TestResult.get(id)
        tr.destroySelf()
        if 'json' in fedora.tg.util.request_format():
            return dict(deleted=id)
        redirect(tg.url("/", kw))

    # XXX: delete_tree()? (would require qa-admin)

    # Identity stuff (login/logout)
    @expose(template="israwhidebroken.templates.login")
    @expose(allow_json=True)
    def login(self, forward_url=None, *args, **kw):

        if forward_url:
            if isinstance(forward_url, list):
                forward_url = forward_url.pop(0)
            else:
                del request.params['forward_url']

        # If the login was successful...
        if not identity.current.anonymous and identity.was_login_attempted() \
                and not identity.get_identity_errors():
            if 'json' == fedora.tg.util.request_format():
                return dict(user=identity.current.user)
            flash("Welcome, %s" % identity.current.user_name)
            redirect(tg.url(forward_url or '/', kw))

        if identity.was_login_attempted():
            msg = _("The credentials you supplied were not correct or "
                   "did not grant access to this resource.")
        elif identity.get_identity_errors():
            msg = _("You must provide your credentials before accessing "
                   "this resource.")
        else:
            msg = _("Please log in.")
            if not forward_url:
                forward_url = request.headers.get("Referer", "/")

        response.status = 401
        return dict(logging_in=True, message=msg,
            forward_url=forward_url, previous_url=request.path_info,
            original_parameters=request.params)

    @expose(allow_json=True)
    def logout(self):
        identity.current.logout()
        if 'json' in fedora.tg.util.request_format():
            return dict()
        redirect("/")