mirror of
https://github.com/ae-utbm/sith.git
synced 2025-07-09 19:40:19 +00:00
Merge branch 'master' into stock
This commit is contained in:
@ -0,0 +1,24 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.contrib import admin
|
||||
from ajax_select import make_ajax_form
|
||||
from core.models import User, Page, RealGroup, SithFile
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from ajax_select import register, LookupChannel
|
||||
|
||||
@ -14,7 +38,7 @@ def check_token(request):
|
||||
|
||||
class RightManagedLookupChannel(LookupChannel):
|
||||
def check_auth(self, request):
|
||||
if not request.user.subscribed and not check_token(request):
|
||||
if not request.user.was_subscribed and not check_token(request):
|
||||
raise PermissionDenied
|
||||
|
||||
@register('users')
|
||||
|
@ -0,0 +1,24 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import os
|
||||
from datetime import date, datetime
|
||||
from io import StringIO, BytesIO
|
||||
@ -16,8 +40,9 @@ from core.utils import resize_image
|
||||
from club.models import Club, Membership
|
||||
from subscription.models import Subscription
|
||||
from counter.models import Customer, ProductType, Product, Counter
|
||||
from com.models import Sith
|
||||
from com.models import Sith, Weekmail
|
||||
from election.models import Election, Role, Candidature, ElectionList
|
||||
from forum.models import Forum, ForumMessage, ForumTopic
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
@ -37,7 +62,9 @@ class Command(BaseCommand):
|
||||
Site(id=4000, domain=settings.SITH_URL, name=settings.SITH_NAME).save()
|
||||
root_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||||
Group(name="Root").save()
|
||||
Group(name="Not registered users").save()
|
||||
Group(name="Public").save()
|
||||
Group(name="Subscribers").save()
|
||||
Group(name="Old subscribers").save()
|
||||
Group(name="Accounting admin").save()
|
||||
Group(name="Communication admin").save()
|
||||
Group(name="Counter admin").save()
|
||||
@ -45,6 +72,7 @@ class Command(BaseCommand):
|
||||
Group(name="Banned from counters").save()
|
||||
Group(name="Banned to subscribe").save()
|
||||
Group(name="SAS admin").save()
|
||||
Group(name="Forum admin").save()
|
||||
self.reset_index("core", "auth")
|
||||
root = User(id=0, username='root', last_name="", first_name="Bibou",
|
||||
email="ae.info@utbm.fr",
|
||||
@ -86,7 +114,8 @@ class Command(BaseCommand):
|
||||
home_root.save()
|
||||
club_root.save()
|
||||
|
||||
Sith().save()
|
||||
Sith(weekmail_destinations="etudiants@git.an personnel@git.an").save()
|
||||
Weekmail().save()
|
||||
|
||||
p = Page(name='Index')
|
||||
p.set_lock(root)
|
||||
@ -428,3 +457,15 @@ Welcome to the wiki page!
|
||||
cand = Candidature(role=pres, user=sli, election_list=listeT, program="En fait j'aime pas l'info, je voulais faire GMC")
|
||||
cand.save()
|
||||
|
||||
# Forum
|
||||
room = Forum(name="Salon de discussions", description="Pour causer de tout", is_category=True)
|
||||
room.save()
|
||||
Forum(name="AE", description="Réservé au bureau AE", parent=room).save()
|
||||
Forum(name="BdF", description="Réservé au bureau BdF", parent=room).save()
|
||||
hall = Forum(name="Hall de discussions", description="Pour toutes les discussions", parent=room)
|
||||
hall.save()
|
||||
various = Forum(name="Divers", description="Pour causer de rien", is_category=True)
|
||||
various.save()
|
||||
Forum(name="Promos", description="Réservé aux Promos", parent=various).save()
|
||||
ForumTopic(forum=hall)
|
||||
|
||||
|
33
core/management/commands/setup.py
Executable file → Normal file
33
core/management/commands/setup.py
Executable file → Normal file
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import os
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.core.management import call_command
|
||||
@ -14,9 +38,14 @@ class Command(BaseCommand):
|
||||
root_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
|
||||
try:
|
||||
os.mkdir(os.path.join(root_path)+'/data')
|
||||
print("Data dir created")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
call_command('flush')
|
||||
repr(e)
|
||||
try:
|
||||
os.remove(os.path.join(root_path, 'db.sqlite3'))
|
||||
print("db.sqlite3 deleted")
|
||||
except Exception as e:
|
||||
repr(e)
|
||||
call_command('migrate')
|
||||
if options['prod']:
|
||||
call_command('populate', '--prod')
|
||||
|
183
core/markdown.py
183
core/markdown.py
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import re
|
||||
from mistune import Renderer, InlineGrammar, InlineLexer, Markdown
|
||||
from django.core.urlresolvers import reverse_lazy, reverse
|
||||
@ -7,9 +31,102 @@ class SithRenderer(Renderer):
|
||||
def file_link(self, id, suffix):
|
||||
return reverse('core:file_detail', kwargs={'file_id': id}) + suffix
|
||||
|
||||
def exposant(self, text):
|
||||
return """<sup>%s</sup>""" % text
|
||||
|
||||
def indice(self, text):
|
||||
return """<sub>%s</sub>""" % text
|
||||
|
||||
def underline(self, text):
|
||||
return """<span class="underline">%s</span>""" % text
|
||||
|
||||
class SithInlineGrammar(InlineGrammar):
|
||||
double_emphasis = re.compile(
|
||||
r'^\*{2}([\s\S]+?)\*{2}(?!\*)' # **word**
|
||||
)
|
||||
emphasis = re.compile(
|
||||
r'^\*((?:\*\*|[^\*])+?)\*(?!\*)' # *word*
|
||||
)
|
||||
underline = re.compile(
|
||||
r'^_{2}([\s\S]+?)_{2}(?!_)' # __word__
|
||||
)
|
||||
exposant = re.compile( # FIXME Does not work for now
|
||||
r'^\^([\s\S]+?)\^' # ^text^
|
||||
# r'|' # FIXME doesn't properly works like this
|
||||
# r'^\^(\S+)' # ^word
|
||||
)
|
||||
indice = re.compile(
|
||||
r'^_([\s\S]+?)_' # _text_ (^` hack, because no other solution were found :/ this sadly prevent code in indices)
|
||||
# r'|' # FIXME doesn't properly works like this
|
||||
# r'^_(\S+)' # _word
|
||||
)
|
||||
|
||||
class SithInlineLexer(InlineLexer):
|
||||
grammar_class = SithInlineGrammar
|
||||
|
||||
default_rules = [
|
||||
'escape',
|
||||
'inline_html',
|
||||
'autolink',
|
||||
'url',
|
||||
'footnote',
|
||||
'link',
|
||||
'reflink',
|
||||
'nolink',
|
||||
'exposant',
|
||||
'double_emphasis',
|
||||
'emphasis',
|
||||
'underline',
|
||||
'indice',
|
||||
'code',
|
||||
'linebreak',
|
||||
'strikethrough',
|
||||
'text',
|
||||
]
|
||||
inline_html_rules = [
|
||||
'escape',
|
||||
'autolink',
|
||||
'url',
|
||||
'link',
|
||||
'reflink',
|
||||
'nolink',
|
||||
'exposant',
|
||||
'double_emphasis',
|
||||
'emphasis',
|
||||
'underline',
|
||||
'indice',
|
||||
'code',
|
||||
'linebreak',
|
||||
'strikethrough',
|
||||
'text',
|
||||
]
|
||||
|
||||
def output_underline(self, m):
|
||||
text = m.group(1)
|
||||
return self.renderer.underline(text)
|
||||
|
||||
def output_exposant(self, m):
|
||||
text = m.group(1)
|
||||
return self.renderer.exposant(text)
|
||||
|
||||
def output_indice(self, m):
|
||||
text = m.group(1)
|
||||
return self.renderer.indice(text)
|
||||
|
||||
# Double emphasis rule changed
|
||||
def output_double_emphasis(self, m):
|
||||
text = m.group(1)
|
||||
text = self.output(text)
|
||||
return self.renderer.double_emphasis(text)
|
||||
|
||||
# Emphasis rule changed
|
||||
def output_emphasis(self, m):
|
||||
text = m.group(1)
|
||||
text = self.output(text)
|
||||
return self.renderer.emphasis(text)
|
||||
|
||||
def _process_link(self, m, link, title=None):
|
||||
try:
|
||||
try: # Add page:// support for links
|
||||
page = re.compile(
|
||||
r'^page://(\S*)' # page://nom_de_ma_page
|
||||
)
|
||||
@ -17,7 +134,7 @@ class SithInlineLexer(InlineLexer):
|
||||
page = match.group(1) or ""
|
||||
link = reverse('core:page', kwargs={'page_name': page})
|
||||
except: pass
|
||||
try:
|
||||
try: # Add file:// support for links
|
||||
file_link = re.compile(
|
||||
r'^file://(\d*)/?(\S*)?' # file://4000/download
|
||||
)
|
||||
@ -28,30 +145,48 @@ class SithInlineLexer(InlineLexer):
|
||||
except: pass
|
||||
return super(SithInlineLexer, self)._process_link(m, link, title)
|
||||
|
||||
# def enable_file_link(self):
|
||||
# # add file_link rules
|
||||
# self.rules.file_link = re.compile(
|
||||
# r'dfile://(\d*)/?(\S*)?' # dfile://4000/download
|
||||
# )
|
||||
# # Add file_link parser to default rules
|
||||
# # you can insert it some place you like
|
||||
# # but place matters, maybe 2 is not good
|
||||
# self.default_rules.insert(0, 'file_link')
|
||||
|
||||
# def output_file_link(self, m):
|
||||
# id = m.group(1)
|
||||
# suffix = m.group(2) or ""
|
||||
# # you can create an custom render
|
||||
# # you can also return the html if you like
|
||||
# # return directly html like this:
|
||||
# # return reverse('core:file_detail', kwargs={'file_id': id}) + suffix
|
||||
# return self.renderer.file_link(id, suffix)
|
||||
|
||||
renderer = SithRenderer()
|
||||
renderer = SithRenderer(escape=True)
|
||||
inline = SithInlineLexer(renderer)
|
||||
|
||||
# enable the features
|
||||
# inline.enable_file_link()
|
||||
markdown = Markdown(renderer, inline=inline)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(markdown.inline.default_rules)
|
||||
print(markdown.inline.inline_html_rules)
|
||||
text = """
|
||||
## Basique
|
||||
|
||||
* Mettre le texte en **gras** : `**texte**`
|
||||
|
||||
* Mettre le texte en *italique* : `*texte*`
|
||||
|
||||
* __Souligner__ le texte : `__texte__`
|
||||
|
||||
* ~~Barrer du texte~~ : `~~texte~~`
|
||||
|
||||
* Mettre ^du texte^ en ^exposant^ : `^mot` ou `^texte^`
|
||||
|
||||
* _Mettre du texte_ en _indice_ : `_mot` ou `_texte_`
|
||||
|
||||
* Pied de page [^en pied de page]
|
||||
|
||||
## Blocs de citations
|
||||
|
||||
Un bloc de citation se crée ainsi :
|
||||
```
|
||||
> Ceci est
|
||||
> un bloc de
|
||||
> citation
|
||||
```
|
||||
|
||||
> Ceci est
|
||||
> un bloc de
|
||||
> citation
|
||||
|
||||
Il est possible d'intégrer de la syntaxe Markdown-AE dans un tel bloc.
|
||||
|
||||
Petit *test* _sur_ ^une^ **seule** ^ligne pour voir^
|
||||
|
||||
"""
|
||||
print(markdown(text))
|
||||
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import importlib
|
||||
from django.conf import settings
|
||||
from django.utils.functional import SimpleLazyObject
|
||||
|
19
core/migrations/0019_preferences_receive_weekmail.py
Normal file
19
core/migrations/0019_preferences_receive_weekmail.py
Normal file
@ -0,0 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0018_auto_20161224_0211'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='preferences',
|
||||
name='receive_weekmail',
|
||||
field=models.BooleanField(default=False, verbose_name='do you want to receive the weekmail'),
|
||||
),
|
||||
]
|
24
core/migrations/0020_auto_20170324_0917.py
Normal file
24
core/migrations/0020_auto_20170324_0917.py
Normal file
@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.core.validators
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0019_preferences_receive_weekmail'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='group',
|
||||
options={'ordering': ['name']},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='page',
|
||||
name='name',
|
||||
field=models.CharField(validators=[django.core.validators.RegexValidator('^[A-z.+-]+$', 'Enter a valid page name. This value may contain only unaccented letters, numbers and ./+/-/_ characters.')], max_length=30, verbose_name='page unix name'),
|
||||
),
|
||||
]
|
112
core/models.py
112
core/models.py
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.db import models
|
||||
from django.core.mail import send_mail
|
||||
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager, Group as AuthGroup, GroupManager as AuthGroupManager, AnonymousUser as AuthAnonymousUser
|
||||
@ -10,6 +34,10 @@ from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||
from django.utils.html import escape
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
import os
|
||||
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
|
||||
from datetime import datetime, timedelta, date
|
||||
@ -31,6 +59,10 @@ class Group(AuthGroup):
|
||||
help_text=_('Whether a group is a meta group or not'),
|
||||
)
|
||||
description = models.CharField(_('description'), max_length=60)
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
|
||||
def get_absolute_url(self):
|
||||
"""
|
||||
This is needed for black magic powered UpdateView's children
|
||||
@ -182,9 +214,11 @@ class User(AbstractBaseUser):
|
||||
def to_dict(self):
|
||||
return self.__dict__
|
||||
|
||||
@cached_property
|
||||
def was_subscribed(self):
|
||||
return self.subscriptions.exists()
|
||||
|
||||
@cached_property
|
||||
def is_subscribed(self):
|
||||
s = self.subscriptions.last()
|
||||
return s.is_valid_now() if s is not None else False
|
||||
@ -204,8 +238,12 @@ class User(AbstractBaseUser):
|
||||
return False
|
||||
if group_id == settings.SITH_GROUP_PUBLIC_ID:
|
||||
return True
|
||||
if group_id == settings.SITH_GROUP_SUBSCRIBERS_ID:
|
||||
return self.is_subscribed
|
||||
if group_id == settings.SITH_GROUP_OLD_SUBSCRIBERS_ID:
|
||||
return self.was_subscribed
|
||||
if group_name == settings.SITH_MAIN_MEMBERS_GROUP: # We check the subscription if asked
|
||||
return self.is_subscribed()
|
||||
return self.is_subscribed
|
||||
if group_name[-len(settings.SITH_BOARD_SUFFIX):] == settings.SITH_BOARD_SUFFIX:
|
||||
from club.models import Club
|
||||
name = group_name[:-len(settings.SITH_BOARD_SUFFIX)]
|
||||
@ -226,25 +264,25 @@ class User(AbstractBaseUser):
|
||||
return True
|
||||
return self.groups.filter(name=group_name).exists()
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def is_root(self):
|
||||
return self.is_superuser or self.groups.filter(id=settings.SITH_GROUP_ROOT_ID).exists()
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def is_board_member(self):
|
||||
from club.models import Club
|
||||
return Club.objects.filter(unix_name=settings.SITH_MAIN_CLUB['unix_name']).first().get_membership_for(self)
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def is_launderette_manager(self):
|
||||
from club.models import Club
|
||||
return Club.objects.filter(unix_name=settings.SITH_LAUNDERETTE_MANAGER['unix_name']).first().get_membership_for(self)
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def is_banned_alcohol(self):
|
||||
return self.is_in_group(settings.SITH_GROUP_BANNED_ALCOHOL_ID)
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def is_banned_counter(self):
|
||||
return self.is_in_group(settings.SITH_GROUP_BANNED_COUNTER_ID)
|
||||
|
||||
@ -402,7 +440,7 @@ class User(AbstractBaseUser):
|
||||
return user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user.is_root
|
||||
|
||||
def can_be_viewed_by(self, user):
|
||||
return (user.is_in_group(settings.SITH_MAIN_MEMBERS_GROUP) and self.is_subscriber_viewable) or user.is_root
|
||||
return (user.was_subscribed and self.is_subscriber_viewable) or user.is_root
|
||||
|
||||
def get_mini_item(self):
|
||||
return """
|
||||
@ -418,14 +456,25 @@ class User(AbstractBaseUser):
|
||||
escape(self.get_display_name()),
|
||||
)
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def subscribed(self):
|
||||
return self.is_in_group(settings.SITH_MAIN_MEMBERS_GROUP)
|
||||
|
||||
@cached_property
|
||||
def forum_infos(self):
|
||||
try:
|
||||
return self._forum_infos
|
||||
except:
|
||||
from forum.models import ForumUserInfo
|
||||
infos = ForumUserInfo(user=self)
|
||||
infos.save()
|
||||
return infos
|
||||
|
||||
class AnonymousUser(AuthAnonymousUser):
|
||||
def __init__(self, request):
|
||||
super(AnonymousUser, self).__init__()
|
||||
|
||||
@property
|
||||
def was_subscribed(self):
|
||||
return False
|
||||
|
||||
@ -487,12 +536,23 @@ class AnonymousUser(AuthAnonymousUser):
|
||||
|
||||
class Preferences(models.Model):
|
||||
user = models.OneToOneField(User, related_name="preferences")
|
||||
receive_weekmail = models.BooleanField(
|
||||
_('do you want to receive the weekmail'),
|
||||
default=False,
|
||||
# help_text=_('Do you want to receive the weekmail?'),
|
||||
)
|
||||
show_my_stats = models.BooleanField(
|
||||
_('define if we show a users stats'),
|
||||
default=False,
|
||||
help_text=_('Show your account statistics to others'),
|
||||
)
|
||||
|
||||
def get_display_name(self):
|
||||
return self.user.get_display_name()
|
||||
|
||||
def get_absolute_url(self):
|
||||
return self.user.get_absolute_url()
|
||||
|
||||
def get_directory(instance, filename):
|
||||
return '.{0}/{1}'.format(instance.get_parent_path(), filename)
|
||||
|
||||
@ -630,10 +690,10 @@ class SithFile(models.Model):
|
||||
if self.is_folder:
|
||||
for c in self.children.all():
|
||||
c.move_to(self)
|
||||
shutil.rmtree(settings.MEDIA_ROOT + old_file_name)
|
||||
shutil.rmtree(os.path.join(settings.MEDIA_ROOT, old_file_name))
|
||||
else:
|
||||
self.file.save(name=self.name, content=self.file)
|
||||
os.remove(settings.MEDIA_ROOT + old_file_name)
|
||||
os.remove(os.path.join(settings.MEDIA_ROOT, old_file_name))
|
||||
|
||||
def __getattribute__(self, attr):
|
||||
if attr == "is_file":
|
||||
@ -641,12 +701,12 @@ class SithFile(models.Model):
|
||||
else:
|
||||
return super(SithFile, self).__getattribute__(attr)
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def as_picture(self):
|
||||
from sas.models import Picture
|
||||
return Picture.objects.filter(id=self.id).first()
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def as_album(self):
|
||||
from sas.models import Album
|
||||
return Album.objects.filter(id=self.id).first()
|
||||
@ -703,7 +763,15 @@ class Page(models.Model):
|
||||
Be careful with the _full_name attribute: this field may not be valid until you call save(). It's made for fast
|
||||
query, but don't rely on it when playing with a Page object, use get_full_name() instead!
|
||||
"""
|
||||
name = models.CharField(_('page name'), max_length=30, blank=False)
|
||||
name = models.CharField(_('page unix name'), max_length=30,
|
||||
validators=[
|
||||
validators.RegexValidator(
|
||||
r'^[A-z.+-]+$',
|
||||
_('Enter a valid page name. This value may contain only '
|
||||
'unaccented letters, numbers ' 'and ./+/-/_ characters.')
|
||||
),
|
||||
],
|
||||
blank=False)
|
||||
parent = models.ForeignKey('self', related_name="children", verbose_name=_("parent"), null=True, blank=True, on_delete=models.SET_NULL)
|
||||
# Attention: this field may not be valid until you call save(). It's made for fast query, but don't rely on it when
|
||||
# playing with a Page object, use get_full_name() instead!
|
||||
@ -808,6 +876,14 @@ class Page(models.Model):
|
||||
p.set_lock_recursive(user)
|
||||
self.set_lock(user)
|
||||
|
||||
def unset_lock_recursive(self):
|
||||
"""
|
||||
Unlocks recursively all the child pages
|
||||
"""
|
||||
for p in self.children.all():
|
||||
p.unset_lock_recursive()
|
||||
self.unset_lock()
|
||||
|
||||
def unset_lock(self):
|
||||
"""Always try to unlock, even if there is no lock"""
|
||||
self.lock_user = None
|
||||
@ -848,6 +924,16 @@ class Page(models.Model):
|
||||
except:
|
||||
return self.name
|
||||
|
||||
def delete(self):
|
||||
self.unset_lock_recursive()
|
||||
self.set_lock_recursive(User.objects.get(id=0))
|
||||
for child in self.children.all():
|
||||
child.parent = self.parent
|
||||
child.save()
|
||||
child.unset_lock_recursive()
|
||||
super(Page, self).delete()
|
||||
|
||||
|
||||
class PageRev(models.Model):
|
||||
"""
|
||||
This is the true content of the page.
|
||||
|
@ -1,4 +1,30 @@
|
||||
from haystack import indexes
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.db import models
|
||||
|
||||
from haystack import indexes, signals
|
||||
|
||||
from core.models import User
|
||||
|
||||
@ -15,3 +41,15 @@ class UserIndex(indexes.SearchIndex, indexes.Indexable):
|
||||
|
||||
def get_updated_field(self):
|
||||
return "last_update"
|
||||
|
||||
|
||||
class UserOnlySignalProcessor(signals.BaseSignalProcessor):
|
||||
def setup(self):
|
||||
# Listen only to the ``User`` model.
|
||||
models.signals.post_save.connect(self.handle_save, sender=User)
|
||||
models.signals.post_delete.connect(self.handle_delete, sender=User)
|
||||
|
||||
def teardown(self):
|
||||
# Disconnect only for the ``User`` model.
|
||||
models.signals.post_save.disconnect(self.handle_save, sender=User)
|
||||
models.signals.post_delete.disconnect(self.handle_delete, sender=User)
|
||||
|
BIN
core/static/core/img/partners.png
Normal file
BIN
core/static/core/img/partners.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
@ -35,6 +35,9 @@ $( function() {
|
||||
popup.html('<iframe src="/file/popup" width="100%" height="95%"></iframe><div id="file_id" value="null" />');
|
||||
popup.dialog({title: $(this).text()}).dialog( "open" );
|
||||
});
|
||||
$("#quick_notif li").click(function () {
|
||||
$(this).hide();
|
||||
})
|
||||
} );
|
||||
|
||||
function display_notif() {
|
||||
|
@ -11,6 +11,20 @@ a {
|
||||
}
|
||||
a:hover { color: #7FDBFF; }
|
||||
a:active { color: #007BE6; }
|
||||
.ib {
|
||||
display: inline-block;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.w_big {
|
||||
width: 75%;
|
||||
}
|
||||
.w_medium {
|
||||
width: 45%;
|
||||
}
|
||||
.w_small {
|
||||
width: 20%;
|
||||
}
|
||||
/*--------------------------------HEADER-------------------------------*/
|
||||
#logo {
|
||||
margin-left: 5%;
|
||||
@ -122,6 +136,15 @@ nav a:hover {
|
||||
}
|
||||
|
||||
/*--------------------------------CONTENT------------------------------*/
|
||||
#quick_notif {
|
||||
width: 90%;
|
||||
margin: 0px auto;
|
||||
list-style-type: none;
|
||||
background: lightblue;
|
||||
}
|
||||
#quick_notif li {
|
||||
padding: 10px;
|
||||
}
|
||||
#content {
|
||||
width: 88%;
|
||||
margin: 0px auto;
|
||||
@ -180,7 +203,11 @@ ul, ol {
|
||||
code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 10px;
|
||||
padding: 5px;
|
||||
border: solid 1px black;
|
||||
}
|
||||
.edit-bar {
|
||||
display: block;
|
||||
margin: 4px;
|
||||
@ -220,10 +247,16 @@ tbody>tr:hover {
|
||||
background: darkgrey;
|
||||
width: 100%;
|
||||
}
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
.highlight {
|
||||
background: orange;
|
||||
font-weight: bold;
|
||||
}
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.tool-bar {
|
||||
overflow: auto;
|
||||
padding: 4px;
|
||||
@ -363,6 +396,80 @@ textarea {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/*------------------------------FORUM----------------------------------*/
|
||||
.topic a, .forum a, .category a {
|
||||
color: black;
|
||||
}
|
||||
.topic a:hover, .forum a:hover, .category a:hover {
|
||||
color: #424242;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.topic {
|
||||
border: solid skyblue 1px;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.forum {
|
||||
background: lightblue;
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.category {
|
||||
background: skyblue;
|
||||
}
|
||||
.message {
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
background: #eff7ff;
|
||||
}
|
||||
.message:nth-child(odd) {
|
||||
background: #fff;
|
||||
}
|
||||
.message h5 {
|
||||
font-size: 100%;
|
||||
}
|
||||
.message.unread {
|
||||
background: #d8e7f3;
|
||||
}
|
||||
.msg_author.deleted {
|
||||
background: #ffcfcf;
|
||||
}
|
||||
.msg_content.deleted {
|
||||
background: #ffefef;
|
||||
}
|
||||
.msg_content {
|
||||
display: inline-block;
|
||||
width: 80%;
|
||||
vertical-align: top;
|
||||
}
|
||||
.msg_author {
|
||||
display: inline-block;
|
||||
width: 19%;
|
||||
text-align: center;
|
||||
background: #d8e7f3;
|
||||
}
|
||||
.msg_author img {
|
||||
max-width: 70%;
|
||||
margin: 0px auto;
|
||||
}
|
||||
.msg_meta {
|
||||
font-size: small;
|
||||
list-style-type: none;
|
||||
}
|
||||
.msg_meta li {
|
||||
padding: 2px;
|
||||
margin: 2px;
|
||||
}
|
||||
.forum_signature {
|
||||
color: #C0C0C0;
|
||||
border-top: 1px solid #C0C0C0;
|
||||
}
|
||||
.forum_signature a {
|
||||
color: #C0C0C0;
|
||||
}
|
||||
.forum_signature a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/*------------------------------SAS------------------------------------*/
|
||||
.album {
|
||||
display: inline-block;
|
||||
|
@ -54,8 +54,8 @@
|
||||
<ul id="notif">
|
||||
{% for n in user.notifications.filter(viewed=False).order_by('-id') %}
|
||||
<li><a href="{{ url("core:notification", notif_id=n.id) }}">
|
||||
<span style="font-size: small; ">{{ n.date|date(DATE_FORMAT) }} {{
|
||||
n.date|time(DATETIME_FORMAT) }}</span><br>
|
||||
<span style="font-size: small; ">{{ n.date|localtime|date(DATE_FORMAT) }} {{
|
||||
n.date|localtime|time(DATETIME_FORMAT) }}</span><br>
|
||||
{{ n }}</a></li>
|
||||
{% endfor %}
|
||||
<li><a href="{{ url('core:notification_list') }}">{% trans %}View more{% endtrans %}</a>
|
||||
@ -91,7 +91,7 @@
|
||||
<a href="https://ae.utbm.fr/matmatronch/">{% trans %}Matmatronch{% endtrans %}</a>
|
||||
<a href="{{ url('core:page', page_name="Index") }}">{% trans %}Wiki{% endtrans %}</a>
|
||||
<a href="{{ url('sas:main') }}">{% trans %}SAS{% endtrans %}</a>
|
||||
<a href="https://ae.utbm.fr/forum2/">{% trans %}Forum{% endtrans %}</a>
|
||||
<a href="{{ url('forum:main') }}">{% trans %}Forum{% endtrans %}</a>
|
||||
<a href="{{ url('core:page', "services") }}">{% trans %}Services{% endtrans %}</a>
|
||||
<a href="{{ url('core:file_list') }}">{% trans %}Files{% endtrans %}</a>
|
||||
<a href="https://ae.utbm.fr/article.php?name=liens">{% trans %}Sponsors{% endtrans %}</a>
|
||||
@ -100,6 +100,12 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
<ul id="quick_notif">
|
||||
{% for n in quick_notifs %}
|
||||
<li>{{ n }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<div id="content">
|
||||
{% if list_of_tabs %}
|
||||
<div class="tool-bar">
|
||||
|
@ -14,8 +14,8 @@
|
||||
<li style="background: lightgrey;">
|
||||
{% endif %}
|
||||
<a href="{{ url("core:notification", notif_id=n.id) }}">
|
||||
<span style="font-size: small; ">{{ n.date|date(DATE_FORMAT) }} {{
|
||||
n.date|time(DATETIME_FORMAT) }}</span><br>
|
||||
<span style="font-size: small; ">{{ n.date|localtime|date(DATE_FORMAT) }} {{
|
||||
n.date|localtime|time(DATETIME_FORMAT) }}</span><br>
|
||||
{{ n }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<h3>{% trans %}Page list{% endtrans %}</h3>
|
||||
<ul>
|
||||
{% for p in page_list %}
|
||||
<li><a href="{{ url('core:page', page_name=p.get_full_name()) }}">{{ p.get_display_name() }}</a></li>
|
||||
<li><a href="{{ p.get_absolute_url() }}">{{ p.get_display_name() }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
|
@ -4,10 +4,12 @@
|
||||
{{ super() }}
|
||||
<script>
|
||||
function make_preview() {
|
||||
text = $("#id_content").val();
|
||||
console.log("Rendering text: " + text);
|
||||
$.ajax({
|
||||
url: "{{ url('api:api_markdown') }}",
|
||||
method: "GET",
|
||||
data: { text: $("#id_content").val() }
|
||||
method: "POST",
|
||||
data: { text: text, csrfmiddlewaretoken: "{{ csrf_token }}"}
|
||||
}).done(function (msg) {
|
||||
$("#preview").html(msg);
|
||||
});
|
||||
@ -23,6 +25,7 @@ function make_preview() {
|
||||
<p><input type="button" value="{% trans %}Preview{% endtrans %}" onclick="javascript:make_preview();" /></p>
|
||||
<p><input type="submit" value="{% trans %}Save{% endtrans %}" /></p>
|
||||
</form>
|
||||
<a href="{{ url('core:page_delete', page_id=page.id)}}">{% trans %}Delete{% endtrans %}</a>
|
||||
<div id="preview">
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -54,7 +54,7 @@
|
||||
{% if user.memberships.filter(end_date=None).exists() or user.is_in_group(settings.SITH_MAIN_BOARD_GROUP) or user == profile %}
|
||||
{# if the user is member of a club, he can view the subscription state #}
|
||||
<p>
|
||||
{% if profile.is_subscribed() %}
|
||||
{% if profile.is_subscribed %}
|
||||
{% if user == profile or user.is_root or user.is_board_member %}
|
||||
{{ user_subscription(profile) }}
|
||||
{% endif %}
|
||||
|
@ -5,27 +5,19 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% set album = None %}
|
||||
{% set new_album = True %}
|
||||
{% for r in profile.pictures.exclude(picture=None).order_by('-picture__parent__id', 'id') -%}
|
||||
{%- if album != r.picture.parent %}
|
||||
{%- if album %}
|
||||
</div>
|
||||
{% endif -%}
|
||||
{% set new_album = True %}
|
||||
{% set album = r.picture.parent %}
|
||||
{% set picture_qs = profile.pictures.exclude(picture=None).order_by('-picture__parent__id', 'id').select_related('picture__parent__parent__name') %}
|
||||
{% for a in picture_qs.distinct('picture__parent') %}
|
||||
<div style="padding: 10px">
|
||||
<h4>{{ album.name }}</h4>
|
||||
<h4>{{ a.picture.parent.name }}</h4>
|
||||
<hr>
|
||||
{% else %}
|
||||
{% set new_album = False %}
|
||||
{%- endif %}
|
||||
{% for r in picture_qs.filter(picture__parent=a.picture.parent) -%}
|
||||
<div class="picture">
|
||||
<a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict">
|
||||
<img src="{{ r.picture.get_download_thumb_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/>
|
||||
</a>
|
||||
</div>
|
||||
{%- endfor %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -75,6 +75,10 @@
|
||||
<h4>{% trans %}Communication{% endtrans %}</h4>
|
||||
<ul>
|
||||
{% if user.is_in_group(settings.SITH_GROUP_COM_ADMIN_ID) or user.is_root %}
|
||||
<li><a href="{{ url('com:weekmail_article') }}">{% trans %}Create weekmail article{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('com:weekmail') }}">{% trans %}Weekmail{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('com:weekmail_destinations') }}">{% trans %}Weekmail destinations{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('com:news_new') }}">{% trans %}Create news{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('com:news_admin_list') }}">{% trans %}Moderate news{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('com:index_edit') }}">{% trans %}Edit index page{% endtrans %}</a></li>
|
||||
<li><a href="{{ url('com:alert_edit') }}">{% trans %}Edit alert message{% endtrans %}</a></li>
|
||||
@ -98,7 +102,7 @@
|
||||
<h4>{% trans %}Elections{% endtrans %}</h4>
|
||||
<ul>
|
||||
<li><a href="{{ url('election:list') }}">{% trans %}See available elections{% endtrans %}</a></li>
|
||||
{%- if user.is_subscribed() -%}
|
||||
{%- if user.is_subscribed -%}
|
||||
<li><a href="{{ url('election:create') }}">{% trans %}Create a new election{% endtrans %}</a></li>
|
||||
{%- endif -%}
|
||||
</ul>
|
||||
|
@ -0,0 +1,24 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.safestring import mark_safe
|
||||
@ -10,7 +34,7 @@ register = template.Library()
|
||||
@register.filter(is_safe=False)
|
||||
@stringfilter
|
||||
def markdown(text):
|
||||
return mark_safe(md(escape(text)))
|
||||
return mark_safe(md(text))
|
||||
|
||||
@register.filter()
|
||||
@stringfilter
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.test import Client, TestCase
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib.auth.models import Group
|
||||
@ -253,8 +277,8 @@ http://git.an
|
||||
response = self.client.get(reverse('core:page', kwargs={'page_name': 'guy'}))
|
||||
self.assertTrue(response.status_code == 200)
|
||||
self.assertTrue('<p>Guy <em>bibou</em></p>\\n<p><a href="http://git.an">http://git.an</a></p>\\n' +
|
||||
'<h1>Swag</h1>\\n<p><guy>Bibou</guy></p>\\n' +
|
||||
'<p><script>alert('Guy');</script></p>' in str(response.content))
|
||||
'<h1>Swag</h1>\\n<guy>Bibou</guy>' +
|
||||
"<script>alert(\\'Guy\\');</script>" in str(response.content))
|
||||
|
||||
#TODO: many tests on the pages:
|
||||
# - renaming a page
|
||||
|
26
core/urls.py
26
core/urls.py
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.conf.urls import url, include
|
||||
|
||||
from core.views import *
|
||||
@ -40,6 +64,7 @@ urlpatterns = [
|
||||
url(r'^user/(?P<user_id>[0-9]+)/edit$', UserUpdateProfileView.as_view(), name='user_edit'),
|
||||
url(r'^user/(?P<user_id>[0-9]+)/profile_upload$', UserUploadProfilePictView.as_view(), name='user_profile_upload'),
|
||||
url(r'^user/(?P<user_id>[0-9]+)/clubs$', UserClubView.as_view(), name='user_clubs'),
|
||||
url(r'^user/(?P<user_id>[0-9]+)/prefs$', UserPreferencesView.as_view(), name='user_prefs'),
|
||||
url(r'^user/(?P<user_id>[0-9]+)/groups$', UserUpdateGroupView.as_view(), name='user_groups'),
|
||||
url(r'^user/tools/$', UserToolsView.as_view(), name='user_tools'),
|
||||
url(r'^user/(?P<user_id>[0-9]+)/account$', UserAccountView.as_view(), name='user_account'),
|
||||
@ -60,6 +85,7 @@ urlpatterns = [
|
||||
# Page views
|
||||
url(r'^page/$', PageListView.as_view(), name='page_list'),
|
||||
url(r'^page/create$', PageCreateView.as_view(), name='page_new'),
|
||||
url(r'^page/(?P<page_id>[0-9]*)/delete$', PageDeleteView.as_view(), name='page_delete'),
|
||||
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/edit$', PageEditView.as_view(), name='page_edit'),
|
||||
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/prop$', PagePropView.as_view(), name='page_prop'),
|
||||
url(r'^page/(?P<page_name>[a-z0-9/-_]*)/hist$', PageHistView.as_view(), name='page_hist'),
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
# Image utils
|
||||
|
||||
from io import BytesIO
|
||||
|
@ -1,9 +1,34 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
import types
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.http import HttpResponseForbidden, HttpResponseNotFound
|
||||
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist, ImproperlyConfigured
|
||||
from django.views.generic.base import View
|
||||
from django.db.models import Count
|
||||
|
||||
from core.models import Group
|
||||
from core.views.forms import LoginForm
|
||||
@ -66,7 +91,7 @@ class CanEditPropMixin(View):
|
||||
except: pass
|
||||
# If we get here, it's a ListView
|
||||
l_id = [o.id for o in self.get_queryset() if can_edit_prop(o, request.user)]
|
||||
if not l_id:
|
||||
if not l_id and self.get_queryset().count() != 0:
|
||||
raise PermissionDenied
|
||||
self._get_queryset = self.get_queryset
|
||||
def get_qs(self2):
|
||||
@ -88,7 +113,7 @@ class CanEditMixin(View):
|
||||
except: pass
|
||||
# If we get here, it's a ListView
|
||||
l_id = [o.id for o in self.get_queryset() if can_edit(o, request.user)]
|
||||
if not l_id:
|
||||
if not l_id and self.get_queryset().count() != 0:
|
||||
raise PermissionDenied
|
||||
self._get_queryset = self.get_queryset
|
||||
def get_qs(self2):
|
||||
@ -110,7 +135,7 @@ class CanViewMixin(View):
|
||||
except: pass
|
||||
# If we get here, it's a ListView
|
||||
l_id = [o.id for o in self.get_queryset() if can_view(o, request.user)]
|
||||
if not l_id:
|
||||
if not l_id and self.get_queryset().count() != 0:
|
||||
raise PermissionDenied
|
||||
self._get_queryset = self.get_queryset
|
||||
def get_qs(self2):
|
||||
@ -147,6 +172,36 @@ class TabedViewMixin(View):
|
||||
kwargs['list_of_tabs'] = self.get_list_of_tabs()
|
||||
return kwargs
|
||||
|
||||
class QuickNotifMixin:
|
||||
quick_notif_list = []
|
||||
|
||||
def dispatch(self, request, *arg, **kwargs):
|
||||
self.quick_notif_list = [] # In some cases, the class can stay instanciated, so we need to reset the list
|
||||
return super(QuickNotifMixin, self).dispatch(request, *arg, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
ret = super(QuickNotifMixin, self).get_success_url()
|
||||
try:
|
||||
if '?' in ret:
|
||||
ret += '&' + self.quick_notif_url_arg
|
||||
else:
|
||||
ret += '?' + self.quick_notif_url_arg
|
||||
except: pass
|
||||
return ret
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Add quick notifications to context"""
|
||||
kwargs = super(QuickNotifMixin, self).get_context_data(**kwargs)
|
||||
kwargs['quick_notifs'] = []
|
||||
for n in self.quick_notif_list:
|
||||
kwargs['quick_notifs'].append(settings.SITH_QUICK_NOTIF[n])
|
||||
for k,v in settings.SITH_QUICK_NOTIF.items():
|
||||
for gk in self.request.GET.keys():
|
||||
if k == gk:
|
||||
kwargs['quick_notifs'].append(v)
|
||||
return kwargs
|
||||
|
||||
|
||||
from .user import *
|
||||
from .page import *
|
||||
from .files import *
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
# This file contains all the views that concern the page model
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.views.generic import ListView, DetailView, TemplateView
|
||||
@ -7,7 +31,7 @@ from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.forms.models import modelform_factory
|
||||
from django.forms import CheckboxSelectMultiple
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.http import HttpResponse
|
||||
from django.core.servers.basehttp import FileWrapper
|
||||
from django.core.urlresolvers import reverse
|
||||
@ -38,10 +62,11 @@ def send_file(request, file_id, file_class=SithFile, file_attr="file"):
|
||||
):
|
||||
raise PermissionDenied
|
||||
name = f.__getattribute__(file_attr).name
|
||||
with open((settings.MEDIA_ROOT + name).encode('utf-8'), 'rb') as filename:
|
||||
filepath = os.path.join(settings.MEDIA_ROOT, name)
|
||||
with open(filepath.encode('utf-8'), 'rb') as filename:
|
||||
wrapper = FileWrapper(filename)
|
||||
response = HttpResponse(wrapper, content_type=f.mime_type)
|
||||
response['Content-Length'] = os.path.getsize((settings.MEDIA_ROOT + name).encode('utf-8'))
|
||||
response['Content-Length'] = os.path.getsize(filepath.encode('utf-8'))
|
||||
response['Content-Disposition'] = ('inline; filename="%s"' % f.name).encode('utf-8')
|
||||
return response
|
||||
|
||||
@ -118,9 +143,9 @@ class FileEditPropForm(forms.ModelForm):
|
||||
model = SithFile
|
||||
fields = ['parent', 'owner', 'edit_groups', 'view_groups']
|
||||
parent = make_ajax_field(SithFile, 'parent', 'files', help_text="")
|
||||
edit_groups = make_ajax_field(SithFile, 'edit_groups', 'groups', help_text="")
|
||||
view_groups = make_ajax_field(SithFile, 'view_groups', 'groups', help_text="")
|
||||
|
||||
edit_groups = make_ajax_field(SithFile, 'edit_groups', 'groups', help_text="", label=_("edit group"))
|
||||
view_groups = make_ajax_field(SithFile, 'view_groups', 'groups', help_text="", label=_("view group"))
|
||||
recursive = forms.BooleanField(label=_("Apply rights recursively"), required=False)
|
||||
|
||||
class FileEditPropView(CanEditPropMixin, UpdateView):
|
||||
model = SithFile
|
||||
@ -134,6 +159,12 @@ class FileEditPropView(CanEditPropMixin, UpdateView):
|
||||
form.fields['parent'].queryset = SithFile.objects.filter(is_folder=True)
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
ret = super(FileEditPropView, self).form_valid(form)
|
||||
if form.cleaned_data['recursive']:
|
||||
self.object.apply_rights_recursively()
|
||||
return ret
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('core:file_detail', kwargs={'file_id': self.object.id, 'popup': self.kwargs['popup'] or ""})
|
||||
|
||||
|
@ -1,10 +1,35 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, UserChangeForm
|
||||
from django import forms
|
||||
from django.db import transaction
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.contrib.auth import logout, login, authenticate
|
||||
from django.forms import CheckboxSelectMultiple, Select, DateInput, TextInput, DateTimeInput
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget
|
||||
from ajax_select.fields import AutoCompleteSelectField
|
||||
|
||||
@ -59,7 +84,7 @@ class SelectFile(TextInput):
|
||||
'title': _("Choose file"),
|
||||
'name': name,
|
||||
}
|
||||
output += '<span name="' + name + '" class="choose_file_button">' + _("Choose file") + '</span>'
|
||||
output += '<span name="' + name + '" class="choose_file_button">' + ugettext("Choose file") + '</span>'
|
||||
return output
|
||||
|
||||
class SelectUser(TextInput):
|
||||
@ -73,7 +98,7 @@ class SelectUser(TextInput):
|
||||
'title': _("Choose user"),
|
||||
'name': name,
|
||||
}
|
||||
output += '<span name="' + name + '" class="choose_user_button">' + _("Choose user") + '</span>'
|
||||
output += '<span name="' + name + '" class="choose_user_button">' + ugettext("Choose user") + '</span>'
|
||||
return output
|
||||
|
||||
# Forms
|
||||
@ -167,7 +192,8 @@ class UserProfileForm(forms.ModelForm):
|
||||
im = Image.open(BytesIO(f.read()))
|
||||
new_file = SithFile(parent=parent, name=self.generate_name(field, f),
|
||||
file=resize_image(im, 400, f.content_type.split('/')[-1]),
|
||||
owner=self.instance, is_folder=False, mime_type=f.content_type, size=f._size)
|
||||
owner=self.instance, is_folder=False, mime_type=f.content_type, size=f._size,
|
||||
moderator=self.instance, is_moderated=True)
|
||||
new_file.file.name = new_file.name
|
||||
old = SithFile.objects.filter(parent=parent, name=new_file.name).first()
|
||||
if old:
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.views.generic.edit import UpdateView, CreateView, DeleteView
|
||||
from django.views.generic import ListView
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
|
@ -1,7 +1,32 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
# This file contains all the views that concern the page model
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django.views.generic import ListView, DetailView
|
||||
from django.views.generic.edit import UpdateView, CreateView
|
||||
from django.views.generic.edit import UpdateView, CreateView, DeleteView
|
||||
from django.contrib.auth.decorators import login_required, permission_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.forms.models import modelform_factory
|
||||
@ -159,3 +184,11 @@ class PageEditView(CanEditMixin, UpdateView):
|
||||
form.instance = new_rev
|
||||
return super(PageEditView, self).form_valid(form)
|
||||
|
||||
|
||||
class PageDeleteView(CanEditPropMixin, DeleteView):
|
||||
model = Page
|
||||
template_name = 'core/delete_confirm.jinja'
|
||||
pk_url_kwarg = 'page_id'
|
||||
|
||||
def get_success_url(self, **kwargs):
|
||||
return reverse_lazy('core:page_list')
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.db import models
|
||||
from django.http import JsonResponse
|
||||
|
@ -1,3 +1,27 @@
|
||||
# -*- coding:utf-8 -*
|
||||
#
|
||||
# Copyright 2016,2017
|
||||
# - Skia <skia@libskia.so>
|
||||
#
|
||||
# Ce fichier fait partie du site de l'Association des Étudiants de l'UTBM,
|
||||
# http://ae.utbm.fr.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License a published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program; if not, write to the Free Sofware Foundation, Inc., 59 Temple
|
||||
# Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
|
||||
# This file contains all the views that concern the user model
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.contrib.auth import logout as auth_logout, views
|
||||
@ -17,9 +41,9 @@ from django.utils import timezone
|
||||
from datetime import timedelta, datetime, date
|
||||
import logging
|
||||
|
||||
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin
|
||||
from core.views import CanViewMixin, CanEditMixin, CanEditPropMixin, TabedViewMixin, QuickNotifMixin
|
||||
from core.views.forms import RegisteringForm, UserPropForm, UserProfileForm, LoginForm, UserGodfathersForm
|
||||
from core.models import User, SithFile
|
||||
from core.models import User, SithFile, Preferences
|
||||
from club.models import Club
|
||||
from subscription.models import Subscription
|
||||
|
||||
@ -151,6 +175,11 @@ class UserTabsMixin(TabedViewMixin):
|
||||
'slug': 'edit',
|
||||
'name': _("Edit"),
|
||||
})
|
||||
tab_list.append({
|
||||
'url': reverse('core:user_prefs', kwargs={'user_id': self.object.id}),
|
||||
'slug': 'prefs',
|
||||
'name': _("Preferences"),
|
||||
})
|
||||
if self.request.user.can_view(self.object):
|
||||
tab_list.append({
|
||||
'url': reverse('core:user_clubs', kwargs={'user_id': self.object.id}),
|
||||
@ -257,6 +286,20 @@ class UserStatsView(UserTabsMixin, CanViewMixin, DetailView):
|
||||
template_name = "core/user_stats.jinja"
|
||||
current_tab = 'stats'
|
||||
|
||||
def dispatch(self, request, *arg, **kwargs):
|
||||
profile = self.get_object()
|
||||
|
||||
if not hasattr(profile, "customer"):
|
||||
raise Http404
|
||||
|
||||
if not (profile == request.user
|
||||
or request.user.is_in_group(settings.SITH_GROUP_ACCOUNTING_ADMIN_ID)
|
||||
or request.user.is_in_group(settings.SITH_BAR_MANAGER['unix_name']+settings.SITH_BOARD_SUFFIX)
|
||||
or request.user.is_root):
|
||||
raise PermissionDenied
|
||||
|
||||
return super(UserStatsView, self).dispatch(request, *arg, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs = super(UserStatsView, self).get_context_data(**kwargs)
|
||||
from counter.models import Counter, Product, Selling
|
||||
@ -378,6 +421,31 @@ class UserClubView(UserTabsMixin, CanViewMixin, DetailView):
|
||||
template_name = "core/user_clubs.jinja"
|
||||
current_tab = "clubs"
|
||||
|
||||
class UserPreferencesView(UserTabsMixin, CanEditMixin, UpdateView):
|
||||
"""
|
||||
Edit a user's preferences
|
||||
"""
|
||||
model = User
|
||||
pk_url_kwarg = "user_id"
|
||||
template_name = "core/edit.jinja"
|
||||
form_class = modelform_factory(Preferences, fields=['receive_weekmail'])
|
||||
context_object_name = "profile"
|
||||
current_tab = "prefs"
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
user = get_object_or_404(User, pk=self.kwargs['user_id'])
|
||||
return user
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super(UserPreferencesView, self).get_form_kwargs()
|
||||
try:
|
||||
pref = self.object.preferences
|
||||
except:
|
||||
pref = Preferences(user=self.object)
|
||||
pref.save()
|
||||
kwargs.update({'instance': pref})
|
||||
return kwargs
|
||||
|
||||
class UserUpdateGroupView(UserTabsMixin, CanEditPropMixin, UpdateView):
|
||||
"""
|
||||
Edit a user's groups
|
||||
@ -390,7 +458,7 @@ class UserUpdateGroupView(UserTabsMixin, CanEditPropMixin, UpdateView):
|
||||
context_object_name = "profile"
|
||||
current_tab = "groups"
|
||||
|
||||
class UserToolsView(UserTabsMixin, TemplateView):
|
||||
class UserToolsView(QuickNotifMixin, UserTabsMixin, TemplateView):
|
||||
"""
|
||||
Displays the logged user's tools
|
||||
"""
|
||||
@ -472,8 +540,8 @@ class UserAccountView(UserAccountBase):
|
||||
(lambda q: q.amount)
|
||||
)
|
||||
kwargs['etickets'] = self.object.customer.buyings.exclude(product__eticket=None).all()
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
return kwargs
|
||||
|
||||
class UserAccountDetailView(UserAccountBase, YearMixin, MonthMixin):
|
||||
|
Reference in New Issue
Block a user