# -*- coding: utf-8
# $Id$
#
#
# Copyright 2001, 2002 by IVA Team and contributors
#
# This file is part of IVA.
#
# IVA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# IVA 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 IVA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Contains class UserInfo, which contains the FLE specific details
of registered users."""
__version__ = "$Revision$"[11:-2]
import time, datetime, string, types, datetime
import os.path
try:
from PIL import Image
PIL_imported = 1
except ImportError:
PIL_imported = 0
import cStringIO
import Globals
import OFS
from Globals import Persistent, Acquisition
import AccessControl
from AccessControl import ClassSecurityInfo, getSecurityManager
from zope.interface import implements
from interfaces import IStatistics, ICourseManager, IFLE, IUserInfo
import TraversableWrapper
from Cruft import Cruft
from Webtop import Webtop
from CourseManager import IDManager
from common import get_url, styles_path, \
make_action, get_roles, get_local_roles, translate
#from common import user_timeout_delay
#from TempObjectManager import TempObjectManager
from input_checks import render, is_valid_title, is_valid_url, normal_entry_tags
from common import perm_view, perm_edit, perm_manage, perm_add_lo
from Globals import PersistentMapping
import re
try:
from Products.ZWiki.ZWikiPage import ZWikiPage
USE_ZWIKI = 1
except:
USE_ZWIKI = 0
import Kirjakast
import Kalender
import Blog
from Products.ZCatalog.CatalogPathAwareness import CatalogAware
from Errors import FleError
from zope.component import getUtility
bg_stuff = {
'bgcolor_rd': ('rd', 'cc3333'),
'wt_bg_bl': ('bl','3f82b5'),
'wt_bg_gray1': ('gray', 'c0c0c0'),
'wt_bg_gray2': ('gray', '99af73'),
'wt_bg_tq': ('tq', '93bdb6'),
'wt_bg_yl': ('yl', 'c2c32e'),
}
# An instance of this class holds all user specific information
# with the exception of access control, which is handled by the
# standard Zope objects in acl_users. IVA no longer has global
# roles, but rather local roles attached to the FLE root object.
#
# Some acl information is handled here (like password changing),
# but those functions transfer to Zope internals as fast as possible.
class UserInfo(
OFS.Folder.Folder,
Persistent,
TraversableWrapper.TraversableWrapper,
Cruft,
AccessControl.Role.RoleManager,
OFS.SimpleItem.Item,
IDManager,
CatalogAware,
):
"""FLE user information."""
meta_type = 'UserInfo'
security = ClassSecurityInfo()
security.declareObjectPublic()
implements(IUserInfo)
def __init__(self, id_, uniq_id=''):
"""Construct UserInfo object."""
security = ClassSecurityInfo()
self.id = id_
#self.title = title
self.title = ''
self.uname = id_
self.id=id_
self.jooksev_kursus=0;
self.__last_active = {}
self.__frozen = 0
self.email_hinded=0
self.email_kirjad=0
self.email_raamat=0
self.email_teadm=0
self.email_meedia=0
self.eventLimit = 1 # in weeks! 1 = one week
self.setUniqId(uniq_id)
self.__edit_tbl = PersistentMapping()
IDManager.__init__(self)
self.default_catalog = 'userinfo_zcatalog'
# Set permissions:
# We iterate first over all set_* methods in this class, and protect them
# with the Edit permission (see manage_afterAdd), and then we set the
# View permissions for all get_* methods.
for prefix in ['set_', 'get_']:
for func in filter(lambda x,p=prefix:x[:len(p)] == p, dir(self)):
if prefix == 'set_':
security.declareProtected('Edit', func)
elif prefix == 'get_':
security.declareProtected('View', func)
#self.set_first_name(first_name)
#self.set_last_name(last_name)
#self.set_email(email)
#self.set_language(language)
## NOTE: Wrong. Stuff like this should have their own container classes.
#self.set_photo(photo) # This is picture binary data
self.set_group('')
self.set_address1('')
self.set_address2('')
self.set_city('')
self.set_country('Estonia')
self.set_homepage('')
self.set_phone('')
self.set_gsm('')
self.set_quote('')
self.set_background('')
self.set_personal_interests('')
self.set_professional_interests('')
self.set_language('et') # Dirty hack ..
self.longLinks = []
self.longLinkQueue = []
self.eventLimit = 1 # in weeks! 1 = one week
# try:
# self.set_language(self.get_default_language())
# except:
# pass
self.set_organization('')
security.declarePrivate('manage_afterAdd')
def manage_afterAdd(self, item, container):
"""Set default permissions for roles."""
# wt = Webtop().__of__(self)
wt=Webtop()
wt.id='webtop'
self._setObject('webtop', wt)
# add blog
blog = Blog.Blog()
self._setObject(blog.id, blog)
# add mailbox
self._setObject('kirjad', Kirjakast.Kirjakast())
# add events container
em = Kalender.KalendriSyndmusteKataloog()
self._setObject(em.id, em)
sm = getattr(self, em.id)
self.set_language(self.get_default_language())
for obj in (self, self.get_child('webtop')):
obj.manage_delLocalRoles([t[0] for t in obj.get_local_roles()])
obj.manage_setLocalRoles(self.get_uname(), ('Owner',))
from common import roles_admin, roles_staff, roles_user
self.index_object()
security.declareProtected(perm_view, 'get_photo_tag')
# Our (simple) version of the tag() method of Zope's Image class.
def get_photo_tag(self, **args):
"""Return HTML img tag for user's photo."""
fle_root = self.fle_root()
fle_url = fle_root.absolute_url()
fle_url = self.fle_url()
tag = ""
imgp = getattr(self.fle_root().images, 'users_imgs')
img = getattr(imgp, 'user_'+self.get_uname()+'_image', None)
if img is not None:
# user has image
if args.has_key('width') and not args.has_key('height'):
mod = float(args['width'])/float(img.width)
args['height'] = int(img.height*mod)
elif args.has_key('height') and not args.has_key('width'):
mod = float(args['height'])/float(img.height)
args['width'] = int(img.width*mod)
tag = apply(img.tag, [], args)
else:
# user don't have image
args['width']='32'
args['height']='32'
uimg = self.unrestrictedTraverse('++resource++images/user.gif')
#imgs_path = getattr(self.fle_root(), self.getSkinsFolderName()).images
#tag = apply(getattr(imgs_path, 'user.gif').tag, [], args)
tag = ''
tag = tag.replace(fle_url+'/', '')
return tag
def get_photo_url(self):
""" url where photo is """
imgp = getattr(self.fle_root().images, 'users_imgs')
img = getattr(imgp, 'user_'+self.get_uname()+'_image', None)
if img is not None:
return img.absolute_url()
return ""
def get_photo_obj(self):
""" return photo object """
imgp = getattr(self.fle_root().images, 'users_imgs')
img = getattr(imgp, 'user_'+self.get_uname()+'_image', None)
return img
security.declareProtected(perm_view, 'has_photo')
def has_photo(self):
"""Return whether user has photo."""
path = getattr(self.fle_root().images, 'users_imgs')
img = getattr(path, 'user_'+self.get_uname()+'_image', 0)
if not img:
return 0
else:
return 1
security.declareProtected(perm_view, 'get_webtop')
def get_webtop(self):
"""Return the webtop of the user."""
return self.get_child('webtop')
def getPassword(self):
return self.acl_users.getUser(self.get_uname())._getPassword()
# Get "global" roles, eg. the roles given for the FLE root object.
def getRoles(self):
return get_roles(self.parent().parent(),self.get_uname())
# def getFrozenRoles(self):
# return self.__roles
# Get roles specified for just one object, and not acquired from above.
def getRolesInObject(self,object):
return get_local_roles(object,self.get_uname())
security.declareProtected(perm_view, 'user_courses')
def user_courses(self, REQUEST=None, update=None,filter_dead=0, quick=0):
"""Return a list of the courses the user is on. Sorted by last activity"""
# Two ways to get user's course.
# * from groups.
# with around 1000 groups in acl_users, this took around ~0.001 sec
# * using zcatalog
# two courses indexed, this took around 0.001 and sometimes less.
# resolution: for now, it seems using zcatalog is faster... using stuff like ldapuserfolder is definitly slowing
# acl_users down. Using ZCatalog is rarely slower.
#st = time.time()
#print self.acl_users._getGroupsForPrincipal(self.acl_users.getUser(self.get_uname()))
#print "end 1:", time.time()-st
#st = time.time()
cm = getUtility(ICourseManager)
uname = self.get_uname()
q = {'meta_type': 'Course', 'get_all_users_id':uname}
cl = cm.courses_zcatalog(q)
if quick:
return cl
if len(cl) == 0:
return cl
# getUserCourseStat stat='lastAccess'
cids = [ x.get_id for x in cl ]
cids = str(tuple(cids))
if cids[-2] == ',': cids = cids[:-2] + ")"
sqlres = getUtility(IStatistics).getUserCourseStatMultiple(cids, 'lastAccess', uname)
if sqlres is None:
return cl
tmp = {}
for c in cl:
tmp[c.get_id] = [0, c]
for r in sqlres:
tmp[r.course_id][0] = time.mktime(r.lastAccess.utctimetuple())
def _cmp(o1, o2):
if o1[0] < o2[0]: return -1
if o1[0] > o2[0]: return 1
return 0
tmp = tmp.values()
tmp.sort(_cmp)
tmp.reverse()
# TODO:
# isCourseAlive
# filter_dead
#print "end 2:", time.time()-st
#return cl
return [ x[1] for x in tmp ]
security.declareProtected(perm_view,'set_jooksev_kursus')
def set_jooksev_kursus(self, kursus, user):
""" change course """
fle = getUtility(IFLE)
cm = getUtility(ICourseManager)
if not hasattr(cm, kursus):
self.jooksev_kursus = 0
return 0
x = getattr(cm, kursus)
user = getSecurityManager().getUser()
uroles = user.getRolesInContext(self)
if 'Manager' in uroles or 'IVAAdmin' in uroles:
self.jooksev_kursus=kursus
return 1
islock = x.isLocked()
if islock:
return 0
ac_user = fle.acl_users.getUser(self.get_uname())
for x in fle.acl_users._getGroupsForPrincipal(ac_user):
if x == kursus or x == kursus+'_teachers' :
self.jooksev_kursus = kursus
return 1
return 0
security.declarePublic('get_jooksev_kursus')
def get_jooksev_kursus(self):
""" current course """
jk = getattr(self, 'jooksev_kursus', 0)
x = getattr(getUtility(ICourseManager), str(jk), None)
if x is None:
return 0
islock = x.isLocked()
if islock and not self.has_any_role(('IVAAdmin','Manager',)):
self.jooksev_kursus = 0
return jk
def kysiJooksvaKursuseObjekt(self):
"Kursus kasutatava objektina"
try:
return getattr(self.fle_root().courses, self.get_jooksev_kursus())
except:
return "viga"
def kysiJooksvaKursuseSisegrupid(self):
"Sisegruppide loetelu"
k=self.kysiJooksvaKursuseObjekt()
return self.kysiKursuseSisegrupid(k)
def kysiKursuseSisegrupid(self, kursus):
"Kursusel olevad grupid"
if not hasattr(kursus, 'subgroups'):
return []
m=kursus.subgroups.getSubgroups()
loetelu=[]
for x in m:
#XXX: check me
r=x.get_local_roles()
for paar in r:
#if paar[0]==self.get_uname() and ('User' in paar[1] or 'Owner' in paar[1]):
loetelu.append(x)
return loetelu
security.declarePrivate('check_portfolios')
def check_portfolios(self, obj, course_obj):
"""
Creates portfolio for user
obj - must be user's course folder
eg. /fle_users/vahur/webtop/c12
course_obj - course object
"""
portfolio = getattr(obj.aq_inner, 'portfolio', None)
if not portfolio:
obj.add_portfolio()
obj.portfolio.setObjPermission(4)
assignments = course_obj.kodutood.listAssignments()
todo = []
for x in assignments:
if x.tyyp in [0,1,4,5]:
todo.append(x)
if todo:
for x in todo:
m_id = x.get_id()
asg = getattr(obj.portfolio.aq_self, m_id, None)
if not asg:
obj.portfolio.createAssignmentProxy(m_id, course_obj.get_id())
if x.tyyp==5:
kaust=getattr(obj.portfolio, m_id)
try:
map=getattr(course_obj.wordmaps, x.getWmID())
mapcopy=map.addChildMap(copying=1)
mapcopy.visibletoothers=0
#kaust.add_link("link to map", mapcopy.absolute_url(), 1)
kaust.wmcID=map.absolute_url()+"/"+mapcopy.id
mapcopy.homeworkstatus=1;
mapcopy.hwid=x.id
except:
pass
def kasKeelBrauserist(self):
""" if 1 we should use language that is preferred by browser """
return getattr(self, 'keelBrauserist', 0)
def seaKeelBrauserist(self, seisund):
"""Soovitu seadmine"""
if seisund:
self.keelBrauserist = 1
else:
self.keelBrauserist = 0
security.declareProtected(perm_edit, 'set_language')
def set_language(self, lang):
"""Set language."""
if lang in get_languages():
self.language = lang
security.declareProtected(perm_view, 'get_language')
def get_language(self):
"""Get language."""
if self.language is None:
raise 'FLE Error', 'No language set.'
return self.language
security.declareProtected(perm_edit, 'set_first_name')
def set_first_name(self, name):
"""Set first name."""
self.__first_name = name
security.declareProtected(perm_edit, 'set_last_name')
def set_last_name(self, name):
"""Set last name."""
self.__last_name = name
security.declareProtected(perm_edit, 'set_email')
def set_email(self, email):
"""Set email."""
self.__email = email
security.declareProtected(perm_edit, 'set_language')
def set_language(self, language):
"""Set language."""
self.__language = language
security.declareProtected(perm_edit, 'remove_photo')
def remove_photo(self):
""" removes photo """
imgp = getattr(self.fle_root().images, 'users_imgs')
try:
imgp._delObject('user_'+str(self.get_id())+'_image')
except AttributeError:
pass
security.declareProtected(perm_edit, 'set_photo')
def set_photo(self, photo, content_type=None):
"""Set photo."""
imgp = getattr(self.fle_root().images, 'users_imgs')
try:
imgp._delObject('user_'+str(self.get_id())+'_image')
except AttributeError:
pass
try:
# Try to crop and scale image to 32x32 pixels and
# convert it into JPEG format...
if not PIL_imported:
print "Can't scale user's photo. PIL not installed."
raise ''
s = cStringIO.StringIO(photo)
im = Image.open(s)
(width, height) = im.size
#if width == 32 and height == 32 and im.format == 'JPEG':
if height == 80 and im.format == 'JPEG':
# If the image is already 32x32 JPEG image, we want to
# avoid doing JPEG compression again (lossy!)
# This is important when exporting/importing FLE.
pass
if im.mode != 'RGB':
im = im.convert('RGB')
if width != height:
smaller = min(width, height)
bigger = max(width, height)
# if width == smaller:
# Tall image: save top part of the image
# im = im.crop(( 0, 0, smaller, smaller))
# else:
# Wide image: save center part of the image
# im = im.crop(( (width-height)/2, 0, smaller, smaller))
#im = im.resize((32,32), Image.BICUBIC)
if height > 80:
#u_w = float(width)/float(height)
mod = float(80)/float(height)
width = width*mod
height = height*mod
im = im.resize((int(width),int(height)))
if width > 100:
u_w = float(100)/float(width)
width = width*u_w
height = height*u_w
im = im.resize((int(width),int(height)))
s = cStringIO.StringIO()
try:
im.save(s, "JPEG", quality=100)
except KeyError:
im.save(s, "GIF", quality=100)
s.seek(0)
imgp.manage_addImage('user_'+str(self.get_uname())+'_image', s.read(), 'user\'s image')
img = getattr(imgp, 'user_'+str(self.get_uname())+'_image')
img.ZCacheable_setManagerId('HTTPCache')
img.ZCacheable_invalidate()
#self.__photo = s.read()
except:
# ... or failing that just use the original image.
# (The failure happens if the system has not PIL installed,
# or if the PIL can't read the image format, or if the PIL
# was compiled without JPEG support, or then something
# completely different...)
#imgp.manage_addImage('user_'+str(self.get_uname())+'_image', photo, 'user\'s image')
#img = getattr(imgp, 'user_'+str(self.get_uname())+'_image')
#img.ZCacheable_setManagerId('HTTPCache')
#img.ZCacheable_invalidate()
return 1
#self.__photo = photo
# FIXME: user can change his own group!
# We can do this by calling this method from another
# method that does custom access checking.
security.declareProtected(perm_edit, 'set_group')
def set_group(self, group):
"""Set group."""
self.__group = group
security.declareProtected(perm_edit, 'set_address1')
def set_address1(self, address1):
"""Set address.1 (street address)"""
self.__address1 = address1
security.declareProtected(perm_edit, 'set_address2')
def set_address2(self, address2):
"""Set address.2 (postal address)"""
self.__address2 = address2
security.declareProtected(perm_edit, 'set_city')
def set_city(self, city):
"""Set city."""
self.__city = city
security.declareProtected(perm_edit, 'set_country')
def set_country(self, country):
"""Set country."""
self.__country = country
security.declareProtected(perm_edit, 'set_homepage')
def set_homepage(self, homepage):
"""Set homepage."""
self.__homepage = homepage
security.declareProtected(perm_edit, 'set_phone')
def set_phone(self, phone):
"""Set phone."""
self.__phone = phone
security.declareProtected(perm_edit, 'set_gsm')
def set_gsm(self, gsm):
"""Set gsm."""
self.__gsm = gsm
security.declareProtected(perm_edit, 'set_quote')
def set_quote(self, quote):
"""Set quote."""
self.__quote = quote
security.declareProtected(perm_edit, 'set_background')
def set_background(self, background):
"""Set background."""
self.__background = background
security.declareProtected(perm_edit, 'set_personal_interests')
def set_personal_interests(self, p_i):
"""Set personal interests."""
self.__personal_interests = p_i
security.declareProtected(perm_edit, 'set_professional_interests')
def set_professional_interests(self, p_i):
"""Set professional interests."""
self.__professional_interests = p_i
security.declareProtected(perm_edit, 'set_organization')
def set_organization(self, p_i):
"""Set organization."""
self.__organization = p_i
security.declarePublic('get_uname')
def get_uname(self):
"""Get user name."""
return self.uname
security.declarePublic('get_nickname')
def get_nickname(self):
"""Get user's visible nick name."""
try:
return self.nickname
except AttributeError:
return self.uname
security.declarePrivate('fingerNames')
def fingerNames(self):
""" Fetch names via finger """
HOST = self.getFingerHost()
PORT = self.getFingerPort()
import socket, re, string
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2.0)
try:
sock.connect((HOST,PORT))
except FleError:
return 0
sock.send('-m %s\n' % string.lower(self.get_uname()))
response = sock.recv(1024)
sock.close()
if len(response)<30+len(self.get_uname()):
return 0
name = re.search('Name:.*?\r',response).group().strip().split(' ')
name.remove('Name:')
logname = re.search('Login:.*?\t',response).group().strip().split(' ')
logname.remove('Login:')
if logname[0] and logname[0]== string.lower(self.get_uname()):
if len(name)==2:
#we have two (first and last) names
try:
firstname = name[0].decode('utf-8')
except UnicodeDecodeError:
firstname = name[0].decode('iso-8859-15')
try:
lastname = name[1].decode('utf-8')
except UnicodeDecodeError:
lastname = name[1].decode('iso-8859-15')
firstname = firstname.encode('utf-8')
lastname = lastname.encode('utf-8')
self.set_first_name(firstname)
self.set_last_name(lastname)
elif len(name)<2:
# somethings missing
return 0
elif len(name)>2:
# more than 2 names
try:
firstname = name[0].decode('utf-8')
except UnicodeDecodeError:
firstname = name[0].decode('iso-8859-15')
firstname = firstname.encode('utf-8')
self.set_first_name(firstname)
name.remove(name[0])
lname = ""
for x in name:
if lname: lname += ' '
lname += x
try:
lastname = lname.decode('utf-8')
except UnicodeDecodeError:
lastname = lname.decode('iso-8859-15')
lastname = lastname.encode('utf-8')
self.set_last_name(lastname)
self.reindex_object()
return 1
security.declareProtected(perm_view,'get_first_name')
def get_first_name(self):
"""Get first name."""
if not hasattr(self, '_' + self.__class__.__name__+ '__first_name'):
return ""
else:
return self.__first_name
security.declareProtected(perm_view,'get_last_name')
def get_last_name(self):
"""Get last name."""
if not hasattr(self, '_' + self.__class__.__name__+ '__last_name'):
return ""
else:
return self.__last_name
security.declareProtected(perm_view, 'get_email')
def get_email(self):
"""Get email."""
if not hasattr(self, '_' + self.__class__.__name__+ '__email'):
return ""
else:
return self.__email
security.declareProtected(perm_view, 'get_language')
def get_language(self):
"""Get language."""
if not hasattr(self, '_' + self.__class__.__name__+ '__language'):
return ""
else:
return self.__language
security.declareProtected(perm_view, 'get_group')
def get_group(self):
"""Get group."""
# FIXME: This can't be defined here.
if not hasattr(self, '_' + self.__class__.__name__+ '__group'):
return ""
else:
return self.__group
security.declareProtected(perm_view, 'get_address1')
def get_address1(self):
"""Get address1. (street address)"""
if not hasattr(self, '_' + self.__class__.__name__+ '__address1'):
return ""
else:
return self.__address1
security.declareProtected(perm_view, 'get_address2')
def get_address2(self):
"""Get address2. (postal address2)"""
if not hasattr(self, '_' + self.__class__.__name__+ '__address2'):
return ""
else:
return self.__address2
security.declareProtected(perm_view, 'get_country')
def get_country(self):
"""Get country."""
if not hasattr(self, '_' + self.__class__.__name__+ '__country'):
return ""
else:
return self.__country
security.declareProtected(perm_view, 'get_homepage')
def get_homepage(self):
"""Get homepage."""
if not hasattr(self, '_' + self.__class__.__name__+ '__homepage'):
return ""
else:
return self.__homepage
security.declareProtected(perm_view, 'get_phone')
def get_phone(self):
"""Get phone."""
if not hasattr(self, '_' + self.__class__.__name__+ '__phone'):
return ""
else:
return self.__phone
security.declareProtected(perm_view, 'get_gsm')
def get_gsm(self):
"""Get gsm."""
if not hasattr(self, '_' + self.__class__.__name__+ '__gsm'):
return ""
else:
return self.__gsm
security.declareProtected(perm_view, 'get_quote')
def get_quote(self):
"""Get quote."""
if not hasattr(self, '_' + self.__class__.__name__+ '__quote'):
return ""
else:
return self.__quote
security.declareProtected(perm_view, 'render_quote')
def render_quote(self):
"""Render quote."""
return render(
self.get_quote(),
legal_tags=normal_entry_tags)
security.declareProtected(perm_view, 'get_background')
def get_background(self):
"""Get background."""
if not hasattr(self, '_' + self.__class__.__name__+ '__background'):
return ""
else:
return self.__background
security.declareProtected(perm_view, 'render_background')
def render_background(self):
"""Render background."""
return render(
self.get_background(),
legal_tags=normal_entry_tags)
security.declareProtected(perm_view, 'get_personal_interests')
def get_personal_interests(self):
"""Get personal interests."""
if not hasattr(self, '_' + self.__class__.__name__+ '__personal_interests'):
return ""
else:
return self.__personal_interests
security.declareProtected(perm_view, 'render_personal_interests')
def render_personal_interests(self):
"""Render personal interests."""
return render(
self.get_personal_interests(),
legal_tags=normal_entry_tags)
security.declareProtected(perm_view, 'get_professional_interests')
def get_professional_interests(self):
"""Get professional interests."""
if not hasattr(self, '_' + self.__class__.__name__+ '__professional_interests'):
return ""
else:
return self.__professional_interests
security.declareProtected(perm_view, 'render_professional_interests')
def render_professional_interests(self):
"""Render professional interests."""
return render(
self.get_professional_interests(),
legal_tags=normal_entry_tags)
security.declareProtected(perm_view, 'get_organization')
def get_organization(self):
"""Get organization."""
if not hasattr(self, '_' + self.__class__.__name__+ '__organization'):
return ""
else:
return self.__organization
security.declareProtected(perm_view, 'get_city')
def get_city(self):
"""Get city."""
if not hasattr(self, '_' + self.__class__.__name__+ '__city'):
return ""
else:
return self.__city
security.declarePrivate('setUniqId')
def setUniqId(self, uniq_id):
""" set uniq id to user. It shouldn't be changed and it should be uniq at all times. """
if not uniq_id:
raise 'IVA error:', 'uniq id not passed'
self.__uniq_id = uniq_id
security.declareProtected(perm_manage, 'getUniqId')
def getUniqId(self):
""" return uniq id. """
return self.__uniq_id
security.declareProtected(perm_view, 'get_default_webtop_bgs')
def get_default_webtop_bgs(self):
"""Return a list of default Image objects."""
names = bg_stuff.keys()
names.sort()
return [eval('self.images.%s' % x) for x in names]
security.declarePrivate('last_active')
def last_active(self, course_id):
"""Return time when user was last active."""
return self.Statistics.getUserCourseStat(int(course_id), 'lastAccess', self.get_uname())
security.declareProtected(perm_edit, 'global_last_active')
def global_last_active(self):
""" Last time when user was active. (any click in IVA) """
val = getUtility(IStatistics).getUserGlobalStat(self.get_uname(), 'lastAccessGlobal')
try:
val = float(val)
except TypeError:
if isinstance(val, type(datetime.datetime(1,2,3))):
val = time.mktime(val.utctimetuple())
return val
return float(getUtility(IStatistics).getUserGlobalStat(self.get_uname(), 'lastAccessGlobal'))
def global_last_active_time(self, REQUEST):
""" Tekstina """
if self.global_last_active()==0:return "-"
return time.strftime(translate(self,'timestamp_format',default="%H:%M %Y-%m-%d"), time.localtime(self.global_last_active()))
def is_logged_in(self):
""" returns True is user is logged in """
#return self.get_uname() in self.Statistics.active_users()
return self.get_uname() in getUtility(IStatistics).active_users()
def empty_pwd(self):
"""Return ..."""
return "eightchr"
# security.declareProtected(perm_edit, 'empty_pwd')
def empty_pwd2(self):
""" Return default empty password. Note, user can't use
this password."""
if self.getSetting('perm_must_change'):
return "wightchr"
else:
return "eightchr"
def empty_pwd1(self):
"""Return default empty password. Note, user can't use
this password."""
if self.getSetting('perm_must_change'):
return "magic"
else:
return 'eightchr'
security.declareProtected(perm_edit, 'set_password')
def set_password(self, pwd):
self.muuda_parool(pwd)
#roles = self.acl_users.data.get(self.get_id()).roles
#self.acl_users._doChangeUser(self.getId(), pwd, roles, [])
security.declareProtected(perm_edit, 'muuda_parool')
def muuda_parool(self, uusparool):
""" Püütakse kasutajal parool muuta """
kataloog=self.leiaKasutajaKataloog(self.get_id())
if kataloog:
uuser = kataloog.searchUsers(id = self.get_uname())
if len(uuser) != 1:
return 1
uuser = uuser[0]
tm = getattr(kataloog.aq_base, uuser.get('pluginid'))
tm.updateUserPassword(self.get_id(), uusparool)
return 0
security.declareProtected(perm_view, 'has_role')
def has_role(self, role):
"""Has user given role."""
return role in get_roles(self.parent().parent(),self.get_uname())
security.declareProtected(perm_view, 'has_any_role')
def has_any_role(self, roles):
"""Has user any of given role."""
real_roles = get_roles(self,self.get_uname())
for role in roles:
if role in real_roles: return 1
return 0
# XXX: FAILS!
security.declareProtected('View', 'has_right_to_edit')
def has_right_to_edit(self, REQUEST):
logged_user = self.parent().get_user_info(self.get_current_user(REQUEST))
if self.has_role('IVAAdmin'):
if not logged_user.has_role('IVAAdmin'):
return 0
else:
# a user with FLEAdmin role can edit do anything (even edit
# other user with FLEAdmin role.
return 1
elif self.get_id() == logged_user.get_id():
return 1
else:
return self.is_power_user(
self.get_current_user(REQUEST))
security.declareProtected(perm_edit, 'edit_user_form_handler')
def edit_user_form_handler(
self,
REQUEST,
# actual user info data from forms
pwd = '', # password
pwd_confirm = '', # password confirmation
nickname = None,
first_name = None,
last_name = None,
email = None,
organization = None,
language = None,
role = None,
delete_my_image = None,
photo_upload = None,
photo_url = None,
group = None,
address1 = None,
address2 = None,
city = None,
country = None,
homepage = None,
phone = None,
gsm = None,
quote = None,
background = None,
personal_interests = None,
professional_interests = None,
webtop_bg_upload=None,
default_webtop_bg=None,
keel_brauserist=0,
email_hinded=0,
email_kirjad=0,
email_raamat=0,
email_teadm=0,
email_meedia=0,
eventLimit=1,
cancel = '',
commit = '',
):
"""User info edit form handler."""
redir_base = 'fle_users/'+self.get_uname()
homepage = homepage.strip()
if cancel:
if REQUEST:
REQUEST.RESPONSE.redirect('show_user_info.html')
return
if not self.has_right_to_edit(REQUEST):
raise 'FLE Error', \
'I am sorry Dave. I am afraid I cannot do that.'
errors = []
for s in ('first_name', 'last_name', 'email', 'organization',
'photo_url', 'address1', 'address2', 'city', 'homepage',
'phone', 'gsm'):
e = REQUEST.get(s)
if e:
e = e.strip()
REQUEST.set(s, e)
# Mandatory
for x in ('first_name', 'last_name'):
e = REQUEST.get(x)
if e and not is_valid_title(e):
#XXX: tricky to translate!
errors.append(+ x)
# Optional
for x in ('nickname', 'email', 'organization', 'language', 'address1',
'address2', 'city', 'phone', 'gsm'):
e = REQUEST.get(x)
if e and not is_valid_title(e):
#XXX: tricky to translate!
errors.append(x)
# These are optional, too.
if photo_url and not is_valid_url(photo_url):
errors.append('url_to_photo')
if homepage and not is_valid_url(homepage):
homepage='http://'+homepage
if homepage and not is_valid_url(homepage):
errors.append('homepage')
# FIXME: input_checks: group
for x in ('quote', 'background', 'personal_interests',
'professional_interests'):
value = REQUEST.get(x)
if value and ('<' in value or '>' in value):
#XXX: tricky to translate!
errors.append(x)
# Check that the nick name isn't already taken
if nickname:
if nickname in \
[x.get_uname() for x in self.fle_users.get_users()]\
or nickname in \
[x.get_nickname() for x in self.fle_users.get_users()]:
errors.append('nickname')
if len(errors) > 0:
# Update photo, because we can't save that to URL.
if photo_upload and len(photo_upload.filename) > 0:
self.set_photo(photo_upload.read(),
photo_upload.headers['content-type'])
action = apply(
make_action,
[redir_base+'/edit_user_form.html'] +
[(x, REQUEST.get(x)) for x in
('first_name', 'last_name', 'email', 'homepage',
'organization', 'language', 'role',
'photo_url', 'address1', 'address2', 'city',
'country', 'phone', 'gsm',
'quote', 'background', 'personal_interests',
'professional_interests')])
return self.restrictedTraverse('message_dialog.html')(
self, REQUEST,
title='Invalid input',
message= translate(self,'Invalid fields') + ": '" + \
"' , '".join(errors) + "'",
action=action)
if nickname and not hasattr(self,'nickname'):
self.nickname=nickname
self.seaKeelBrauserist(keel_brauserist)
if webtop_bg_upload and len(webtop_bg_upload.filename) > 0:
self.webtop.set_webtop_bg_from_image_data(webtop_bg_upload.read())
elif default_webtop_bg:
self.webtop.set_webtop_bg_from_default_image(default_webtop_bg)
if not email_hinded:
email_hinded = 0
if not email_kirjad:
email_kirjad =0
if not email_raamat:
email_raamat = 0
if not email_teadm:
email_teadm = 0
if not email_meedia:
email_meedia = 0
self.edit_info(
first_name, last_name, email, organization, language,
delete_my_image,
photo_upload, photo_url, group, address1, address2, city,
country, homepage, phone, gsm, quote,
background, personal_interests,
professional_interests, email_hinded, email_kirjad, email_raamat, email_teadm, email_meedia,eventLimit)
muutis_parooli = 0
if pwd and (pwd != self.empty_pwd()):
# change password
if pwd == pwd_confirm:
#self.set_password(pwd)
if not self.getSetting('perm_pass'):
self.muuda_parool(pwd)
else:
pass
if hasattr(self,'perm_must_change'):
if self.perm_must_change == 1:
muutis_parooli = 1
self.perm_must_change = 0
else:
if REQUEST:
return self.restrictedTraverse('message_dialog.html')(
self, REQUEST,
title='Error',
message='password mismatch',
action=redir_base+'/edit_user_form.html')
if first_name == '':
return self.restrictedTraverse('message_dialog.html')(
self,REQUEST,
title='Error',
message=translate(self,'Enter correct ') + translate(self,'first name'),
action=redir_base+'/edit_user_form.html')
if last_name == '':
return self.restrictedTraverse('message_dialog.html')(
self,REQUEST,
title='Error',
message=translate(self,'Enter correct ') + translate(self,'last_name'),
action=redir_base+'/edit_user_form.html')
if not re.match("^.+@.+\..{2,3}$",email):
return self.restrictedTraverse('message_dialog.html')(
self, REQUEST,
title = 'Error',
message=translate(self, 'Enter correct ') + translate(self, 'email'),
action=redir_base+'/edit_user_form.html')
if REQUEST:
if muutis_parooli:
REQUEST.RESPONSE.redirect('organizer_index')
else:
REQUEST.RESPONSE.redirect('show_user_info.html')
# Implementation of edit_user_form_handler without http code.
security.declarePrivate('edit_info')
def edit_info(
self,
first_name = None,
last_name = None,
email = None,
organization = None,
language = None,
delete_my_image = None,
photo_upload = None,
photo_url = None,
group = None,
address1 = None,
address2 = None,
city = None,
country = None,
homepage = None,
phone = None,
gsm = None,
quote = None,
background = None,
personal_interests = None,
professional_interests = None,
email_hinded = None,
email_kirjad = None,
email_raamat = None,
email_teadm = None,
email_meedia = None,
eventLimit = 1
):
"""Commits changes in userinfo object."""
if first_name != None: self.set_first_name(first_name)
if last_name != None: self.set_last_name(last_name)
if email != None: self.set_email(email)
if organization != None: self.set_organization(organization)
if language != None: self.set_language(language)
if group != None: self.set_group(group)
if address1 != None: self.set_address1(address1)
if address2 != None: self.set_address2(address2)
if city != None: self.set_city(city)
if country != None: self.set_country(country)
if homepage != None: self.set_homepage(homepage)
if phone != None: self.set_phone(phone)
if gsm != None: self.set_gsm(gsm)
if quote != None: self.set_quote(quote)
if background != None: self.set_background(background)
if personal_interests != None:
self.set_personal_interests(personal_interests)
if professional_interests != None:
self.set_professional_interests(professional_interests)
if email_hinded != None: self.email_hinded = int(email_hinded)
if email_kirjad != None: self.email_kirjad = int(email_kirjad)
if email_raamat != None: self.email_raamat = int(email_raamat)
if email_teadm != None: self.email_teadm = int(email_teadm)
if email_meedia != None: self.email_meedia = int(email_meedia)
if delete_my_image == 'delete_my_image':
# delete image
self.remove_photo()
if photo_upload != None:
if hasattr(photo_upload,'filename') and \
len(photo_upload.filename) > 0:
photo_data = photo_upload.read()
self.set_photo(photo_data,photo_upload.headers['content-type'])
#return
if photo_url != None and photo_url != '' and photo_url != 'http://':
photo_data = get_url(photo_url)
self.set_photo(photo_data)
self.set_event_limit(eventLimit)
self.default_catalog = 'userinfo_zcatalog'
self.reindex_object()
security.declareProtected(perm_edit,'set_event_limit')
def set_event_limit(self,eventLimit):
self.eventLimit = int(eventLimit)
return self.eventLimit
security.declareProtected(perm_edit,'get_event_limit')
def get_event_limit(self):
""" return week """
return getattr(self.aq_self, 'eventLimit', 1)
def kysiKirjadeKataloog(self):
"lisatakse kui pole"
return self.kirjad
def checkFitTimelimit(self,event,tstart,tend):
""" check if given event fits time limits """
if tstart