================================================================================
+VERSION 1.1.3 XX XX XXXX
+
+New:
+
+ * API:
+ - Enable the 'sharing' API (profile exchange with other sites) -XEL
+
+ * Auth:
+ - Add per-group options to configure the auth-groupe-x behaviour -XEL
+
+ * Profile:
+ - Significantly improve visibility handling -XEL
+
+ * Xnet:
+ - Allow auth-groupe-x for X.net accounts -XEL
+
+Bug/Wish:
+
+ * Email:
+ - #1517: Fixes bestalias update when two local_part are identical -JAC
+ - #1533: Fixes bestalias after updating melix alias -JAC
+
+ * Profile:
+ - #1532: Allows edition of empty reference birthdates -JAC
+
+From 1.1.2 branch:
+
+ * Newsletter:
+ - #1524: Fixes NL unsubscription when not loggued on the site -JAC
+
+ * Search:
+ - #1520: Fixes deltaten -XEL
+
+================================================================================
VERSION 1.1.2 28 06 2011
New:
// we might run in troubler later if we don't keep the two repos. If we need
// to add a forlife-looking nickname at some point, we'll do it manually.
if (!preg_match('/^[-a-z]+\.[-a-z]+\.\d{4}$/', $nickname['nickname'])) {
- XDB::execute(
- "INSERT INTO gapps_queue
- SET q_recipient_id = {?}, p_entry_date = NOW(), p_notbefore_date = NOW(),
- p_priority = 'offline', j_type = 'n_create', j_parameters = {?}",
- $nickname['uid'],
- json_encode($nickname));
+ $pending_tasks = XDB::fetchOneCell(
+ "SELECT COUNT(*)
+ FROM gapps_queue
+ WHERE q_recipient_id = {?} AND p_status = 'idle' AND j_type = 'n_create' AND j_parameters = {?}",
+ $nickname['id'], json_encode($nickname));
+ if ($pending_tasks == 0) {
+ XDB::execute(
+ "INSERT INTO gapps_queue
+ SET q_recipient_id = {?}, p_entry_date = NOW(), p_notbefore_date = NOW(),
+ p_priority = 'offline', j_type = 'n_create', j_parameters = {?}",
+ $nickname['id'], json_encode($nickname));
+ }
}
}
LEFT JOIN email_source_account AS s ON (s.uid = g.l_userid AND s.type = 'alias' AND s.email = g.g_nickname)
WHERE g.l_userid IS NOT NULL AND s.email IS NULL");
while ($nickname = $res->next()) {
- XDB::execute(
- "INSERT INTO gapps_queue
- SET q_recipient_id = {?}, p_entry_date = NOW(), p_notbefore_date = NOW(),
- p_priority = 'offline', j_type = 'n_delete', j_parameters = {?}",
- $nickname['uid'],
- json_encode($nickname));
+ $pending_tasks = XDB::fetchOneCell(
+ "SELECT COUNT(*)
+ FROM gapps_queue
+ WHERE q_recipient_id = {?} AND p_status = 'idle' AND j_type = 'n_delete' AND j_parameters = {?}",
+ $nickname['id'], json_encode($nickname));
+ if ($pending_tasks == 0) {
+ XDB::execute(
+ "INSERT INTO gapps_queue
+ SET q_recipient_id = {?}, p_entry_date = NOW(), p_notbefore_date = NOW(),
+ p_priority = 'offline', j_type = 'n_delete', j_parameters = {?}",
+ $nickname['id'], json_encode($nickname));
+ }
}
/* Retrieves successful job queues for post-queue processing. */
$message = '';
-$res = XDB::iterRow("SELECT a.registration_date, a.hruid, s.email, GROUP_CONCAT(r.redirect SEPARATOR ', ')
+$res = XDB::iterRow("SELECT DATE(a.registration_date), a.hruid, GROUP_CONCAT(DISTINCT r.redirect SEPARATOR ', ')
FROM accounts AS a
INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms))
INNER JOIN profile_display AS pd ON (ap.pid = pd.pid)
MYSQL_USER = get_config('Core', 'dbuser')
MYSQL_PASS = get_config('Core', 'dbpwd')
+MYSQL_HOST = get_config('Core', 'dbhost')
MYSQL_DB = get_config('Core', 'dbdb')
PLATAL_DOMAIN = get_config('Mail', 'domain')
db=MYSQL_DB,
user=MYSQL_USER,
passwd=MYSQL_PASS,
- unix_socket='/var/run/mysqld/mysqld.sock')
+ host=MYSQL_HOST)
db.ping()
db.autocommit(True)
return db.cursor()
public function format()
{
$this->text = trim($this->text);
- $this->phones = Phone::formatFormArray($this->phones, $this->error, new ProfileVisibility($this->pub));
+ $this->phones = Phone::formatFormArray($this->phones, $this->error, $this->pub);
if ($this->removed == 1) {
if (!S::user()->checkPerms('directory_private') && Phone::hasPrivate($this->phones)) {
Platal::page()->trigWarning("L'adresse ne peut être supprimée car elle contient des informations pour lesquelles vous n'avez le droit d'édition.");
// addresses before secondary addresses.
static private function compare(array $a, array $b)
{
- $value = ProfileVisibility::comparePublicity($a, $b);
+ $value = Visibility::comparePublicity($a, $b);
if ($value == 0) {
if ($a['secondary'] != $b['secondary']) {
$value = $a['secondary'] ? 1 : -1;
}
static public function iterate(array $pids = array(), array $types = array(),
- array $jobids = array(), array $pubs = array())
+ array $jobids = array(), Visibility $visibility)
{
- return new AddressIterator($pids, $types, $jobids, $pubs);
+ return new AddressIterator($pids, $types, $jobids, $visibility);
}
}
{
private $dbiter;
- public function __construct(array $pids, array $types, array $jobids, array $pubs)
+ public function __construct(array $pids, array $types, array $jobids, Visibility $visibility)
{
$where = array();
if (count($pids) != 0) {
if (count($jobids) != 0) {
$where[] = XDB::format('(pa.jobid IN {?})', $jobids);
}
- if (count($pubs) != 0) {
- $where[] = XDB::format('(pa.pub IN {?})', $pubs);
+ if ($visibility == null) {
+ $visibility = Visibility::defaultForRead();
}
+ $where[] = 'pve.best_display_level+0 <= pa.pub+0';
+
$sql = 'SELECT pa.pid, pa.jobid, pa.groupid, pa.type, pa.id, pa.flags, pa.text, pa.postalText, pa.pub, pa.comment,
pa.types, pa.formatted_address, pa.location_type, pa.partial_match, pa.latitude, pa.longitude,
pa.southwest_latitude, pa.southwest_longitude, pa.northeast_latitude, pa.northeast_longitude,
LEFT JOIN profile_addresses_components_enum AS pace2 ON (FIND_IN_SET(\'locality\', pace2.types) AND pace2.id = pc.component_id)
LEFT JOIN profile_addresses_components_enum AS pace3 ON (FIND_IN_SET(\'administrative_area_level_1\', pace3.types) AND pace3.id = pc.component_id)
LEFT JOIN profile_addresses_components_enum AS pace4 ON (FIND_IN_SET(\'country\', pace4.types) AND pace4.id = pc.component_id)
- ' . ((count($where) > 0) ? 'WHERE ' . implode(' AND ', $where) : '') . '
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE ' . implode(' AND ', $where) . '
GROUP BY pa.pid, pa.jobid, pa.groupid, pa.type, pa.id
ORDER BY pa.pid, pa.jobid, pa.id';
- $this->dbiter = XDB::iterator($sql);
+ $this->dbiter = XDB::iterator($sql, $visibility->level());
}
public function next()
// {{{ class DE_JobTerms
class DE_JobTerms extends DirEnumeration
{
+ protected $valfield = 'profile_job_term_enum.name';
+ protected $from = 'profile_job_term_enum';
+ protected $idfield = 'profile_job_term_enum.jtid';
+
// {{{ function getAutoComplete
public function getAutoComplete($text)
{
$phone = new Phone($item);
$success = (!$phone->error && ($phone->format() || $phone->isEmpty()) && $success);
if (!$phone->isEmpty()) {
- if (!is_null($maxPublicity) && $maxPublicity->isVisible($phone->pub)) {
- $phone->pub = $maxPublicity->level();
+ // Restrict phone visibility to $maxPublicity
+ if (!is_null($maxPublicity) && Visibility::isLessRestrictive($phone->pub, $maxPublicity)) {
+ $phone->pub = $maxPublicity;
}
$phones[] = call_user_func(array($phone, $function));
}
}
if (count($phones) == 0 && $requiresEmptyPhone) {
$phone = new Phone();
- if (!is_null($maxPublicity) && $maxPublicity->isVisible($phone->pub)) {
- $phone->pub = $maxPublicity->level();
+ if (!is_null($maxPublicity) && Visibility::isLessRestrictive($phone->pub, $maxPublicity)) {
+ // Restrict phone visibility to $maxPublicity
+ $phone->pub = $maxPublicity;
}
$phones[] = call_user_func(array($phone, $function));
}
static public function formatFormArray(array $data, &$success = true, $maxPublicity = null)
{
$phones = self::formArrayWalk($data, 'toFormArray', $success, true, $maxPublicity);
- usort($phones, 'ProfileVisibility::comparePublicity');
+ usort($phones, 'Visibility::comparePublicity');
return $phones;
}
}
static public function iterate(array $pids = array(), array $link_types = array(),
- array $link_ids = array(), array $pubs = array())
+ array $link_ids = array(), Visibility $visibility)
{
- return new PhoneIterator($pids, $link_types, $link_ids, $pubs);
+ return new PhoneIterator($pids, $link_types, $link_ids, $visibility);
}
}
{
private $dbiter;
- public function __construct(array $pids, array $link_types, array $link_ids, array $pubs)
+ public function __construct(array $pids, array $link_types, array $link_ids, Visibility $visibility)
{
$where = array();
if (count($pids) != 0) {
if (count($link_ids) != 0) {
$where[] = XDB::format('(link_id IN {?})', $link_ids);
}
- if (count($pubs) != 0) {
- $where[] = XDB::format('(pub IN {?})', $pubs);
+ if ($visibility == null) {
+ $visibility = Visibility::defaultForRead();
}
+ $where[] = 'pve.best_display_level+0 <= pub+0';
+
$sql = 'SELECT search_tel AS search, display_tel AS display, comment, link_id,
tel_type AS type, link_type, tel_id AS id, pid, pub
FROM profile_phones
- ' . ((count($where) > 0) ? 'WHERE ' . implode(' AND ', $where) : '') . '
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE ' . implode(' AND ', $where) . '
ORDER BY pid, link_id, tel_id';
- $this->dbiter = XDB::iterator($sql);
+ $this->dbiter = XDB::iterator($sql, $visibility->level());
}
public function next()
const FETCH_JOB_TERMS = 0x000200;
const FETCH_MENTOR_TERMS = 0x000400;
const FETCH_DELTATEN = 0x000800;
+ const FETCH_PARTNER = 0x001000;
const FETCH_MINIFICHES = 0x00012D; // FETCH_ADDRESSES | FETCH_EDU | FETCH_JOBS | FETCH_NETWORKING | FETCH_PHONES
- const FETCH_ALL = 0x000FFF; // OR of FETCH_*
+ const FETCH_ALL = 0x001FFF; // OR of FETCH_*
static public $descriptions = array(
'search_names' => 'Noms',
private $visibility = null;
- private function __construct(array $data)
+ private function __construct(array $data, Visibility $visibility)
{
$this->data = $data;
$this->pid = $this->data['pid'];
$this->hrpid = $this->data['hrpid'];
- $this->visibility = new ProfileVisibility();
+ $this->visibility = $visibility;
}
public function id()
public function displayEmail()
{
$o = $this->owner();
- if ($o != null) {
+ if ($o != null && $this->isVisible(Visibility::EXPORT_PRIVATE)) {
return $o->bestEmail();
} else {
return $this->email_directory;
* Clears a profile.
* *always deletes in: profile_addresses, profile_binets, profile_deltaten,
* profile_job, profile_langskills, profile_mentor, profile_networking,
- * profile_phones, profile_skills, watch_profile
+ * profile_partnersharing_settings, profile_phones, profile_skills,
+ * watch_profile
* *always keeps in: profile_corps, profile_display, profile_education,
* profile_medals, profile_*_names, profile_photos, search_name
* *modifies: profiles
'profile_job', 'profile_langskills', 'profile_mentor',
'profile_networking', 'profile_skills', 'watch_profile',
'profile_phones', 'profile_addresses', 'profile_binets',
- 'profile_deltaten');
+ 'profile_deltaten', 'profile_partnersharing_settings');
foreach ($tables as $t) {
XDB::execute('DELETE FROM ' . $t . '
$this->id());
}
- /** Sets the level of visibility of the profile
- * Sets $this->visibility to a list of valid visibilities.
- * @param one of the self::VIS_* values
- */
- public function setVisibilityLevel($visibility)
- {
- $this->visibility->setLevel($visibility);
- }
-
/** Determine whether an item with visibility $visibility can be displayed
* with the current level of visibility of the profile
* @param $visibility The level of visibility to be checked
*/
public function getBinets()
{
- if ($this->visibility->isVisible(ProfileVisibility::VIS_PRIVATE)) {
+ if ($this->visibility->isVisible(Visibility::EXPORT_PRIVATE)) {
return XDB::fetchColumn('SELECT binet_id
FROM profile_binets
WHERE pid = {?}', $this->id());
}
public function getBinetsNames()
{
- if ($this->visibility->isVisible(ProfileVisibility::VIS_PRIVATE)) {
+ if ($this->visibility->isVisible(Visibility::EXPORT_PRIVATE)) {
return XDB::fetchColumn('SELECT text
FROM profile_binets AS pb
LEFT JOIN profile_binet_enum AS pbe ON (pbe.id = pb.binet_id)
return $this->medals->medals;
}
+ /** Sharing data with partner websites
+ */
+ private $partners_settings = null;
+ public function setPartnersSettings(ProfilePartnerSharing $partners_settings)
+ {
+ $this->partners_settings = $partners_settings;
+ }
+
+ public function getPartnerSettings($partner_id)
+ {
+ if ($this->partners_settings === null && !$this->fetched(self::FETCH_PARTNER)) {
+ $this->setPartnersSettings($this->getProfileField(self::FETCH_PARTNER));
+ }
+ if ($this->partners_settings === null) {
+ return PartnerSettings::getEmpty($partner_id);
+ }
+ return $this->partners_settings->get($partner_id);
+ }
+
public function compareNames($firstname, $lastname)
{
$_lastname = mb_strtoupper($this->lastName());
$order = '';
}
- $visibility = new ProfileVisibility($visibility);
+ if ($visibility === null) {
+ $visibility = Visibility::defaultForRead();
+ }
$it = XDB::Iterator('SELECT p.pid, p.hrpid, p.xorg_id, p.ax_id, p.birthdate, p.birthdate_ref,
p.next_birthday, p.deathdate, p.deathdate_rec, p.sex = \'female\' AS sex,
IF ({?}, p.cv, NULL) AS cv, p.medals_pub, p.alias_pub, p.email_directory,
p.last_change, p.nationality1, p.nationality2, p.nationality3,
- IF (p.freetext_pub IN {?}, p.freetext, NULL) AS freetext,
+ IF (p.freetext_pub >= {?}, p.freetext, NULL) AS freetext,
pe.entry_year, pe.grad_year, pe.promo_year, pe.program, pe.fieldid,
IF ({?}, pse.text, NULL) AS section,
ppn.firstname_main AS firstname, ppn.lastname_main AS lastname, IF ({?}, pn.name, NULL) AS nickname,
IF (ppn.lastname_ordinary = \'\', ppn.firstname_main, ppn.lastname_ordinary) AS lastname_ordinary,
pd.yourself, pd.promo, pd.short_name, pd.public_name AS full_name,
pd.directory_name, pd.public_name, pd.private_name,
- IF (pp.pub IN {?}, pp.display_tel, NULL) AS mobile,
- (ph.pub IN {?} AND ph.attach IS NOT NULL) AS has_photo,
+ IF (pp.pub >= {?}, pp.display_tel, NULL) AS mobile,
+ (ph.pub >= {?} AND ph.attach IS NOT NULL) AS has_photo, ph.pub as photo_pub,
ph.x AS photo_width, ph.y AS photo_height,
p.last_change < DATE_SUB(NOW(), INTERVAL 365 DAY) AS is_old,
pm.expertise AS mentor_expertise,
WHERE p.pid IN {?}
GROUP BY p.pid
' . $order,
- $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // CV
- $visibility->levels(), // freetext
- $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // section
- $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // nickname
- $visibility->levels(), // mobile
- $visibility->levels(), // photo
- $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // deltaten_message
+ $visibility->isVisible(Visibility::EXPORT_PRIVATE), // CV
+ $visibility->level(), // freetext
+ $visibility->isVisible(Visibility::EXPORT_PRIVATE), // section
+ $visibility->isVisible(Visibility::EXPORT_PRIVATE), // nickname
+ $visibility->level(), // mobile
+ $visibility->level(), // photo
+ $visibility->isVisible(Visibility::EXPORT_PRIVATE), // deltaten_message
$pids
);
return new ProfileIterator($it, $pids, $fields, $visibility);
*/
public static function get($login, $fields = 0x0000, $visibility = null)
{
+ if ($visibility === null) {
+ $visibility = Visibility::defaultForRead();
+ }
+
if (is_array($login)) {
- $pf = new Profile($login);
- $pf->setVisibilityLevel($visibility);
+ $pf = new Profile($login, $visibility);
return $pf;
}
$pid = self::getPID($login);
if (!($login instanceof PlUser)) {
$user = User::getSilent($login);
if ($user && $user->hasProfile()) {
- return $user->profile();
+ return $user->profile(false, $fields, $visibility);
}
}
return null;
const FETCH_ALL = 0x000033F; // FETCH_ADDRESSES | FETCH_CORPS | FETCH_EDU | FETCH_JOBS | FETCH_MEDALS | FETCH_NETWORKING | FETCH_PHONES | FETCH_JOB_TERMS
- public function __construct(PlIterator $it, array $pids, $fields = 0x0000, ProfileVisibility $visibility = null)
+ public function __construct(PlIterator $it, array $pids, $fields = 0x0000, $visibility = null)
{
require_once 'profilefields.inc.php';
- if ($visibility == null) {
- $visibility = new ProfileVisibility();
+ if ($visibility === null) {
+ $visibility = Visibility::defaultForRead();
}
$this->fields = $fields;
private function fillProfile(array $vals)
{
- $pf = Profile::get($vals[0]);
- $pf->setVisibilityLevel($this->visibility->level());
+ $pf = Profile::get($vals[0], 0x0, $this->visibility);
$pf->setFetchedFields($this->fields);
if ($this->hasData(Profile::FETCH_PHONES, $vals)) {
+++ /dev/null
-<?php
-/***************************************************************************
- * Copyright (C) 2003-2011 Polytechnique.org *
- * http://opensource.polytechnique.org/ *
- * *
- * This program 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. *
- * *
- * 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 Software *
- * Foundation, Inc., *
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
- ***************************************************************************/
-
-class ProfileVisibility
-{
- static private $v_values = array(self::VIS_PUBLIC => array(self::VIS_PUBLIC),
- self::VIS_AX => array(self::VIS_AX, self::VIS_PUBLIC),
- self::VIS_PRIVATE => array(self::VIS_PRIVATE, self::VIS_AX, self::VIS_PUBLIC));
-
- const VIS_PUBLIC = 'public';
- const VIS_AX = 'ax';
- const VIS_PRIVATE = 'private';
-
- private $level;
-
- public function __construct($level = null, $force = false)
- {
- if ($force) {
- $this->forceLevel($level);
- } else {
- $this->setLevel($level);
- }
- }
-
- public function setLevel($level = self::VIS_PUBLIC)
- {
- if ($level != null && $level != self::VIS_PRIVATE && $level != self::VIS_AX && $level != self::VIS_PUBLIC) {
- Platal::page()->kill("Invalid visibility: " . $level);
- }
-
- // Unlogged or not allowed to view directory_ax or requesting public
- // => public view
- if (!S::logged() || !S::user()->checkPerms('directory_ax') || $level == self::VIS_PUBLIC) {
- $level = self::VIS_PUBLIC;
- // Not allowed to view directory_private or requesting ax
- } else if (!S::user()->checkPerms('directory_private') || $level == self::VIS_AX) {
- $level = self::VIS_AX;
- } else {
- $level = self::VIS_PRIVATE;
- }
-
- if ($this->level == null || $this->level == self::VIS_PRIVATE) {
- $this->level = $level;
- } else if ($this->level == self::VIS_AX && $level == self::VIS_PRIVATE) {
- return;
- } else {
- $this->level = self::VIS_PUBLIC;
- }
- }
-
- public function forceLevel($level)
- {
- if ($level != self::VIS_PRIVATE && $level != self::VIS_AX && $level != self::VIS_PUBLIC) {
- Platal::page()->kill('Invalid visibility: ' . $level);
- }
-
- $this->level = $level;
- }
-
- public function level()
- {
- if ($this->level == null) {
- return self::VIS_PUBLIC;
- } else {
- return $this->level;
- }
- }
-
- public function levels()
- {
- return self::$v_values[$this->level()];
- }
-
- public function isVisible($visibility)
- {
- return in_array($visibility, $this->levels());
- }
-
- static public function comparePublicity($a, $b)
- {
- $a_pub = new ProfileVisibility($a['pub'], true);
- $b_pub = new ProfileVisibility($b['pub'], true);
-
- return !$a_pub->isVisible($b_pub->level());
- }
-}
-
-
-// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
-?>
$this->perm_flags = null;
}
+ /** Retrieve the 'general' read visibility.
+ * This is the maximum level of fields that may be viewed by the current user on other profiles.
+ *
+ * Rules are:
+ * - Everyone can view 'public'
+ * - directory_ax gives access to 'AX' level
+ * - directory_private gives access to 'private' level
+ * - admin gives access to 'hidden' level
+ */
+ public function readVisibility()
+ {
+ $level = Visibility::VIEW_NONE;
+ if ($this->is_admin) {
+ $level = Visibility::VIEW_ADMIN;
+ } elseif ($this->checkPerms('directory_private')) {
+ $level = Visibility::VIEW_PRIVATE;
+ } elseif ($this->checkPerms('directory_ax')) {
+ $level = Visibility::VIEW_AX;
+ } else {
+ $level = Visibility::VIEW_PUBLIC;
+ }
+ return Visibility::get($level);
+ }
+
+ /** Retrieve the 'general' edit visibility.
+ * This is the maximum level of fields that may be edited by the current user on other profiles.
+ *
+ * Rules are:
+ * - Only admins can edit the 'hidden' fields
+ * - If someone has 'directory_edit' (which is actually directory_ax_edit): AX level
+ * - Otherwise, nothing.
+ */
+ public function editVisibility()
+ {
+ $level = Visibility::VIEW_NONE;
+ if ($this->is_admin) {
+ $level = Visibility::VIEW_ADMIN;
+ } elseif ($this->checkPerms('directory_edit')) {
+ $level = Visibility::VIEW_AX;
+ }
+ return Visibility::get($level);
+ }
+
// We do not want to store the password in the object.
// So, fetch it 'on demand'
public function password()
if (!$this->_profile_fetched || $forceFetch) {
$this->_profile_fetched = true;
$this->_profile = Profile::get($this, $fields, $visibility);
+ } else if ($this->_profile !== null && !$this->_profile->visibility->equals($visibility)) {
+ return Profile::get($this, $fields, $visibility);
}
return $this->_profile;
}
public static function makePerms($perms, $is_admin)
{
$flags = new PlFlagSet($perms);
- $flags->addFlag(PERMS_USER);
if ($is_admin) {
$flags->addFlag(PERMS_ADMIN);
}
private $orderby = null;
// Store the current 'search' visibility.
- private $profile_visibility = null;
+ private $visibility = null;
+ // If the 'search' visibility should be based on a DB field instead.
+ private $visibility_field = null;
private $lastusercount = null;
private $lastprofilecount = null;
}
// This will set the visibility to the default correct level.
- $this->profile_visibility = new ProfileVisibility();
+ $this->visibility = Visibility::defaultForRead();
}
- public function getVisibilityLevels()
- {
- return $this->profile_visibility->levels();
- }
-
- public function getVisibilityLevel()
- {
- return $this->profile_visibility->level();
- }
-
- public function restrictVisibilityTo($level)
- {
- $this->profile_visibility->setLevel($level);
+ /** Get the SQL condition to filter by visibility level for a field.
+ * This will return a SQL condition which evaluates to True if the given
+ * field display level is available from the current access level.
+ * @param $field Name of the field holding a display level
+ * @return string SQL condition, properly escaped, for that field.
+ */
+ public function getVisibilityConditionForField($field)
+ {
+ if ($this->visibility_field != null) {
+ // Use enum 'bit' arithmetic.
+ // Display levels are ordered as 'hidden, private, ax, public'
+ // Thus ax > private.
+ // The $sub.display_level cell will contain the 'most private' display
+ // level available based on $field. If it is 'ax' and $field is
+ // 'private','ax' <= 'private' is false.
+ $sub = $this->addVisibilityFieldFilter($this->visibility_field);
+ return $sub . '.best_display_level + 0 <= 0 + ' . $field;
+ } else {
+ $sub = $this->addVisibilityAbsoluteFilter($this->visibility->level());
+ return $sub . '.best_display_level + 0 <= 0 + ' . $field;
+ }
}
- public function getVisibilityCondition($field)
+ /** Get the SQL condition to filter by a given visibility level.
+ * @param $level One of Visibility::EXPORT_*
+ * @return string A SQL condition, properly escaped, which evaluates to 'true' if the $level can be viewed with the current access level.
+ */
+ public function getVisibilityConditionAbsolute($level)
{
- return $field . ' IN ' . XDB::formatArray($this->getVisibilityLevels());
+ if ($this->visibility_field != null) {
+ // The $sub.display_levels cell will contain allowed display levels
+ // for an access level of $this->visibility_field.
+ $sub = $this->addVisibilityFieldFilter($this->visibility_field);
+ return XDB::format('FIND_IN_SET({?}, ' . $sub . '.display_levels)', $level);
+ } else {
+ if ($this->visibility->isVisible($level)) {
+ return 'TRUE';
+ } else {
+ return 'FALSE';
+ }
+ }
}
private function buildQuery()
return array();
}
}
+
+
+ /** PARTNER SHARING
+ */
+
+ // Lists partner shortnames in use, as a $partner_shortname => true map.
+ private $ppss = array();
+
+ /** Add a filter on user having settings for a given partner.
+ * @param $partner_id the ID of the partner
+ * @return the name of the table to use in joins (e.g ppss_$partner_id).
+ */
+ public function addPartnerSharingFilter($partner_id)
+ {
+ $this->requireProfiles();
+ $sub = "ppss_" . $partner_id;
+ $this->ppss[$sub] = $partner_id;
+ return $sub;
+ }
+
+ protected function partnerSharingJoins()
+ {
+ $joins = array();
+ foreach ($this->ppss as $sub => $partner_id) {
+ $joins[$sub] = PlSqlJoin::left('profile_partnersharing_settings', '$ME.pid = $PID AND $ME.partner_id = {?} AND $ME.sharing_level != \'none\'', $partner_id);
+ }
+ return $joins;
+ }
+
+ public function restrictVisibilityForPartner($partner_id)
+ {
+ $sub = $this->addPartnerSharingFilter($partner_id);
+ $this->visibility_field = $sub . '.sharing_level';
+ }
+
+ /** VISIBILITY
+ */
+ private $vlevels = array();
+ private $vfields = array();
+ public function addVisibilityAbsoluteFilter($level)
+ {
+ $sub = 'pvel_' . $level;
+ $this->vlevels[$level] = $sub;
+ return $sub;
+ }
+
+ public function addVisibilityFieldFilter($field)
+ {
+ $sub = 'pvef_' . self::getDBSuffix($field);
+ $this->vfields[$field] = $sub;
+ return $sub;
+ }
+
+ /** Since this method might perform inner joins on tables which have been
+ * joined previously (e.g when using addVisibilityFieldFilter), it has to
+ * come after the Joins() methods for those tables.
+ * This is due to the implementation logic for discovering joins and the
+ * ordering used by PHP introspection.
+ */
+ protected function visibilityJoins()
+ {
+ $joins = array();
+ foreach ($this->vlevels as $level => $sub) {
+ $joins[$sub] = PlSqlJoin::inner('profile_visibility_enum', '$ME.access_level = {?}', $level);
+ }
+ foreach ($this->vfields as $field => $sub) {
+ $joins[$sub] = PlSqlJoin::inner('profile_visibility_enum', '$ME.access_level = ' . $field);
+ }
+ return $joins;
+ }
+
}
// }}}
// {{{ class ProfileFilter
public function buildCondition(PlFilter $uf)
{
$uf->requireProfiles();
- return $uf->getVisibilityCondition('p.freetext_pub') . ' AND p.freetext ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->text);
+ return $uf->getVisibilityConditionForField('p.freetext_pub') . ' AND p.freetext ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->text);
}
public function export()
if ($this->general_type) {
$c .= XDB::format(' AND ' . $sub . '.general_type = {?}', $this->general_type);
}
+ $c .= ' AND (' . $uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' OR ' . $sub . '.general_type != \'nickname\')';
$conds[] = $c;
}
public function buildCondition(PlFilter $uf)
{
- // Binets are private.
- if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) {
- return self::COND_TRUE;
- }
$sub = $uf->addBinetsFilter();
- return XDB::format($sub . '.binet_id IN {?}', $this->val);
+ // Binets are private.
+ return XDB::format($uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' AND ' . $sub . '.binet_id IN {?}', $this->val);
}
}
// }}}
public function buildCondition(PlFilter $uf)
{
// Sections are private.
- if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) {
- return self::COND_TRUE;
- }
$uf->requireProfiles();
- return XDB::format('p.section IN {?}', $this->section);
+ return XDB::format($uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' AND p.section IN {?}', $this->section);
}
}
// }}}
public function buildCondition(PlFilter $uf)
{
$sub = $uf->addAddressFilter($this->fieldtype);
- $conds = $this->initConds($sub, $uf->getVisibilityCondition('pa' . $sub . '.pub'));
+ $conds = $this->initConds($sub, $uf->getVisibilityConditionForField('pa' . $sub . '.pub'));
$conds[] = XDB::format('pace' . $sub . '.id IN {?}', $this->val);
return implode(' AND ', $conds);
}
// XXX(x2006barrois): find a way to get rid of that hardcoded
// reference to 'pc'.
- $cond .= ' AND ' . $uf->getVisibilityCondition('pc.corps_pub');
+ $cond .= ' AND ' . $uf->getVisibilityConditionForField('pc.corps_pub');
return $cond;
}
}
}
// XXX(x2006barrois): find a way to get rid of that hardcoded
// reference to 'pc'.
- $cond .= ' AND ' . $uf->getVisibilityCondition('pc.corps_pub');
+ $cond .= ' AND ' . $uf->getVisibilityConditionForField('pc.corps_pub');
return $cond;
}
}
$sub = $uf->addJobCompanyFilter();
$cond = $sub . '.' . $this->type . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value);
$jsub = $uf->addJobFilter();
- $cond .= ' AND ' . $uf->getVisibilityCondition($jsub . '.pub');
+ $cond .= ' AND ' . $uf->getVisibilityConditionForField($jsub . '.pub');
return $cond;
}
}
$conditions[] = $sub[$i] . '.jtid_1 = ' . XDB::escape($jtid);
}
$jsub = $uf->addJobFilter();
- $conditions[] = $uf->getVisibilityCondition($jsub . '.pub');
+ $conditions[] = $uf->getVisibilityConditionForField($jsub . '.pub');
return implode(' AND ', $conditions);
}
}
$conds = array();
$jsub = $uf->addJobFilter();
- // CV is private => if only CV requested, and not private,
- // don't do anything. Otherwise restrict to standard job visibility.
- if ($this->fields == UserFilter::JOB_CV) {
- if ($uf->getVisibilityLevel() != ProfileVisibility::VIS_PRIVATE) {
- return self::COND_TRUE;
- }
- }
if ($this->fields & UserFilter::JOB_USERDEFINED) {
$conds[] = $jsub . '.description ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description);
}
- if ($this->fields & UserFilter::JOB_CV && $uf->getVisibilityLevel() == ProfileVisibility::VIS_PRIVATE) {
+ if ($this->fields & UserFilter::JOB_CV) {
$uf->requireProfiles();
- $conds[] = 'p.cv ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description);
+ // CV is private
+ $conds[] = '( ' . $uf->getVisibilityConditionAbsolute(Visibility::EXPORT_PRIVATE) . ' AND p.cv ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->description) . ')';
}
if (count($conds) == 0) {
return self::COND_TRUE;
}
- return $uf->getVisibilityCondition($jsub . '.pub') . ' AND ( ' . implode(' OR ', $conds) . ' )';
+ return $uf->getVisibilityConditionForField($jsub . '.pub') . ' AND ( ' . implode(' OR ', $conds) . ' )';
}
}
// }}}
{
$sub = $uf->addNetworkingFilter();
$conds = array();
- $conds[] = $uf->getVisibilityCondition($sub . '.pub');
+ $conds[] = $uf->getVisibilityConditionForField($sub . '.pub');
$conds[] = $sub . '.address ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->value);
if ($this->type != -1) {
$conds[] = $sub . '.nwid = ' . XDB::format('{?}', $this->type);
$sub = $uf->addPhoneFilter();
$conds = array();
- $conds[] = $uf->getVisibilityCondition($sub . '.pub');
+ $conds[] = $uf->getVisibilityConditionForField($sub . '.pub');
$conds[] = $sub . '.search_tel = ' . XDB::format('{?}', $this->number);
if ($this->num_type != self::NUM_ANY) {
// This will require profiles => table 'p' will be available.
$sub = $uf->addMedalFilter();
- $conds[] = $uf->getVisibilityCondition('p.medals_pub');
+ $conds[] = $uf->getVisibilityConditionForField('p.medals_pub');
$conds[] = $sub . '.mid = ' . XDB::format('{?}', $this->medal);
if ($this->grade != null) {
public function buildCondition(PlFilter $uf)
{
$sub = $uf->addPhotoFilter();
- return $sub . '.attach IS NOT NULL AND ' . $uf->getVisibilityCondition($sub . '.pub');
+ return $sub . '.attach IS NOT NULL AND ' . $uf->getVisibilityConditionForField($sub . '.pub');
}
}
// }}}
}
}
// }}}
+// {{{ class UFC_PartnerSharing
+/** Filters users, keeping only those sharing data with a given partner.
+ */
+class UFC_PartnerSharing extends UserFilterCondition
+{
+ const PTA = 'pta';
+
+ private $partner_id;
+
+ public function __construct($partner_id)
+ {
+ $this->partner_id = $partner_id;
+ }
+
+ public function buildCondition(PlFilter $uf)
+ {
+ $sub = $uf->addPartnerSharingFilter($this->partner_id);
+ return XDB::format("$sub.exposed_uid IS NOT NULL");
+ }
+}
+// }}}
+// {{{ class UFC_PartnerSharingEmail
+/** Filters users, keeping only those allowing emails to be sent by
+ * a given partner.
+ */
+class UFC_PartnerSharingEmail extends UserFilterCondition
+{
+ private $partner_id;
+
+ public function __construct($partner_id)
+ {
+ $this->partner_id = $partner_id;
+ }
+
+ public function buildCondition(PlFilter $uf)
+ {
+ $sub = $uf->addPartnerSharingFilter($this->partner_id);
+ return XDB::format("$sub.allow_email IN ('digest', 'direct')");
+ }
+}
+// }}}
+// {{{ class UFC_PartnerSharingID
+/** Filters users according to a list of partner-known IDs
+ */
+class UFC_PartnerSharingID extends UserFilterCondition
+{
+ private $partner_id;
+ private $ids;
+
+ public function __construct($partner_id)
+ {
+ $this->partner_id = $partner_id;
+ $ids = func_get_args();
+ array_shift($ids);
+ $this->ids = pl_flatten($ids);
+ }
+
+ public function buildCondition(PlFilter $uf)
+ {
+ $uf->requireProfiles();
+ $ids = $this->ids;
+ $sub = $uf->addPartnerSharingFilter($this->partner_id);
+ return XDB::format("$sub.exposed_uid IN {?}", $ids);
+ }
+}
+// }}}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
?>
--- /dev/null
+<?php
+/***************************************************************************
+ * Copyright (C) 2003-2011 Polytechnique.org *
+ * http://opensource.polytechnique.org/ *
+ * *
+ * This program 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. *
+ * *
+ * 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 Software *
+ * Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ ***************************************************************************/
+
+class Visibility
+{
+ /** Visibility levels.
+ * The VIEW_* constants describe the access level
+ * The EXPORT_* constants describe the degree of confidentiality of the data.
+ */
+ const VIEW_NONE = 'none';
+ const VIEW_PUBLIC = 'public';
+ const VIEW_AX = 'ax';
+ const VIEW_PRIVATE = 'private';
+ const VIEW_ADMIN = 'admin';
+
+ const EXPORT_PUBLIC = 'public';
+ const EXPORT_AX = 'ax';
+ const EXPORT_PRIVATE = 'private';
+ const EXPORT_HIDDEN = 'hidden';
+
+ /** Map each VIEW_ level to the list of EXPORT_ levels it can view.
+ */
+ static private $view_levels = array(
+ self::VIEW_NONE => array(),
+ self::VIEW_PUBLIC => array(self::EXPORT_PUBLIC),
+ self::VIEW_AX => array(self::EXPORT_AX, self::EXPORT_PUBLIC),
+ self::VIEW_PRIVATE => array(self::EXPORT_PRIVATE, self::EXPORT_AX, self::EXPORT_PUBLIC),
+ self::VIEW_ADMIN => array(self::EXPORT_HIDDEN, self::EXPORT_PRIVATE, self::EXPORT_AX, self::EXPORT_PUBLIC),
+ );
+
+ static private $display_levels = array(
+ self::EXPORT_PUBLIC => 0,
+ self::EXPORT_AX => 1,
+ self::EXPORT_PRIVATE => 2,
+ self::EXPORT_HIDDEN => 3,
+ );
+
+ private $level;
+
+ private function __construct($level)
+ {
+ $this->level = $level;
+ }
+
+ static private $vis_list = array();
+ public static function get($level)
+ {
+ Platal::assert(array_key_exists($level, self::$view_levels), "Invalid visibility access level $level.");
+ if (!array_key_exists($level, self::$vis_list)) {
+ self::$vis_list[$level] = new Visibility($level);
+ }
+ return self::$vis_list[$level];
+ }
+
+ public function level()
+ {
+ return $this->level;
+ }
+
+ public static function defaultForRead($max_level = null)
+ {
+ if (!S::logged()) {
+ $vis = self::get(self::VIEW_PUBLIC);
+ } else {
+ $vis = S::user()->readVisibility();
+ }
+ if ($max_level != null) {
+ return $vis->restrict($max_level);
+ } else {
+ return $vis;
+ }
+ }
+
+ public static function defaultForEdit($max_level = null)
+ {
+ if (!S::logged()) {
+ $vis = self::get(self::VIEW_NONE);
+ } else {
+ $vis = S::user()->editVisibility();
+ }
+ if ($max_level != null) {
+ return $vis->restrict($max_level);
+ } else {
+ return $vis;
+ }
+ }
+
+ /** Retrieve a 'restricted' version of the current Visibility.
+ *
+ * @param $level The visibility level to restrict to
+ * @return A new Visibility instance, whose level is min($this->level, $level)
+ */
+ public function restrict($level = null)
+ {
+ if ($level != null && !$this->isVisible($level)) {
+ $level = $this->level();
+ }
+
+ return self::get($level);
+ }
+
+ public function isVisible($visibility)
+ {
+ return in_array($visibility, self::$view_levels[$this->level()]);
+ }
+
+ public function equals($visibility)
+ {
+ return $visibility !== null && $this->level() == $visibility->level();
+ }
+
+ static public function isLessRestrictive($level_a, $level_b)
+ {
+ // self::$display_levels is order from least restrictive
+ // to most restrictive.
+ return self::$display_levels[$a] >= self::$display_levels[$b];
+ }
+
+ /** Compare the visibility of two fields.
+ * Returns:
+ * >0 if $a is less restrictive than $b,
+ * <0 if $a is more restrictive than $b,
+ * 0 if $a is equal to $b.
+ */
+ static public function cmpLessRestrictive($a, $b)
+ {
+ $a_pub = self::$display_levels[$a];
+ $b_pub = self::$display_levels[$b];
+ /* self::$display_levels is ordered from least restrictive to
+ * most restrictive.
+ * This will be 0 if both levels are equal, < 0 if $b_pub is less
+ * than $a_pub, thus less restrictive, which means that $a comes
+ * before $b in descending restrictiveness order.
+ */
+ return $b_pub - $a_pub;
+ }
+
+ static public function comparePublicity($a, $b)
+ {
+ return self::cmpLessRestrictive($a['pub'], $b['pub']);
+ }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
{
public function __construct()
{
- parent::__construct('xnet', 'xnetgrp', 'xnetlists', 'xnetevents',
- 'payment', 'bandeau', 'xnetnl', 'geoloc');
+ parent::__construct(
+ 'xnet',
+
+ 'bandeau',
+ 'geoloc',
+ 'payment',
+ 'xnetevents',
+ 'xnetgrp',
+ 'xnetlists',
+ 'xnetnl'
+ );
}
public function hook_map($name)
$sub['documentation'] = 'Xnet';
if (S::user()->type == 'xnet') {
$sub['mon compte'] = 'edit';
- $sub['mon mot de passe'] = 'password';
+ $sub['mes préférences'] = $globals->xnet->xorg_baseurl . 'prefs';
}
$sub['signaler un bug'] = array('href' => 'send_bug/'.$_SERVER['REQUEST_URI'], 'class' => 'popup_840x600');
$menu["no_title"] = $sub;
}
}
- if (!S::logged() && Post::has('auth_type') && Post::v('auth_type') == 'xnet' && !Post::has('wait')) {
- $email = Post::v('username');
- $type = XDB::fetchOneCell('SELECT type
- FROM accounts
- WHERE email = {?}',
- $email);
- if ((!is_null($type) && $type != 'xnet') || !User::isForeignEmailAddress($email)) {
- Platal::page()->trigErrorRedirect('Ce formulaire d\'authentification est réservé aux extérieurs à la communauté polytechnicienne.', '');
- }
-
- $user = parent::doAuth(AUTH_MDP);
- if (is_null($user)) {
- return false;
- }
- if (!parent::checkAuth(AUTH_MDP) || !parent::startSessionAs($user, AUTH_MDP)) {
- $this->destroy();
- return false;
- }
- }
-
global $globals;
if (!S::logged() && $globals->xnet->auth_baseurl) {
// prevent connection to be linked to disconnection
protected function doAuth($level)
{
- if (S::identified()) { // ok, c'est bon, on n'a rien à faire
+ if (S::identified()) { // Nothing to do there
return User::getSilentWithValues(null, array('uid' => S::i('uid')));
}
if (!Get::has('auth')) {
if (!$user->checkPerms('groups')) {
return false;
}
+
if ($level == AUTH_SUID) {
S::set('auth', AUTH_MDP);
}
S::set('perms', $user->perms);
S::set('is_admin', $user->is_admin);
-
- $this->makePerms($user->perms, $user->is_admin);
+ // Add the 'user' perms to the user.
+ $this->makePerms($user->perms . ',' . PERMS_USER, $user->is_admin);
S::kill('challenge');
S::kill('loginX');
S::kill('may_update');
if (!$this->startSUID($user)) {
return false;
}
- S::set('perms', User::makePerms(PERMS_USER));
+ S::set('perms', User::makePerms(PERMS_USER . ",groups"));
return true;
}
{
public function __construct()
{
- parent::__construct('auth', 'carnet', 'email', 'events', 'forums',
- 'lists', 'marketing', 'payment', 'platal',
- 'profile', 'register', 'search', 'stats', 'admin',
- 'newsletter', 'axletter', 'epletter', 'bandeau', 'survey',
- 'fusionax', 'gadgets', 'googleapps', 'poison',
- 'openid', 'reminder', 'api', 'urlshortener', 'deltaten', 'geoloc');
+ parent::__construct(
+ 'auth',
+
+ 'admin',
+ 'api',
+ 'axletter',
+ 'bandeau',
+ 'carnet',
+ 'deltaten',
+ 'email',
+ 'epletter',
+ 'events',
+ 'forums',
+ 'fusionax',
+ 'gadgets',
+ 'geoloc',
+ 'googleapps',
+ 'lists',
+ 'marketing',
+ 'newsletter',
+ 'openid',
+ 'payment',
+ 'platal',
+ 'poison',
+ 'profile',
+ 'register',
+ 'reminder',
+ 'search',
+ 'sharingapi',
+ 'stats',
+ 'survey',
+ 'urlshortener'
+ );
}
public function find_hook()
class XorgPage extends PlPage
{
+ protected $forced_skin = null;
+ protected $default_skin = null;
+
public function __construct()
{
parent::__construct();
}
}
+ /** Force the skin to use, bypassing user choice.
+ * Typically used for the 'register' page.
+ * @param $skin The skin to use.
+ */
+ public function forceSkin($skin)
+ {
+ $this->forced_skin = $skin;
+ }
+
+ /** Choose another 'default' skin.
+ * Typically used for the 'Auth Groupe X' login page.
+ * @param $skin The default skin to use.
+ */
+ public function setDefaultSkin($skin)
+ {
+ $this->default_skin = $skin;
+ }
+
public function run()
{
global $globals, $platal;
- if (isset($platal) && $platal->path == 'register') {
- $skin = $globals->register_skin . ".tpl";
+ if ($this->forced_skin !== null) {
+ $skin = $this->forced_skin . '.tpl';
} else {
- $skin = S::v('skin', $globals->skin . ".tpl");
+ if ($this->default_skin === null) {
+ $default_skin = $globals->skin;
+ } else {
+ $default_skin = $this->default_skin;
+ }
+ $skin = S::v('skin', $default_skin . '.tpl');
}
$this->_run('skin/' . $skin);
}
return self::INVALID_USER;
}
- private function checkPassword($uname, $login, $response, $login_type)
+ const TEXT_INVALID_LOGIN = "Mot de passe ou nom d'utilisateur invalide";
+ const TEXT_INVALID_PASS = "Mot de passe invalide";
+
+ private function checkPassword($login, User $user, $response)
{
- if ($login_type == 'alias') {
- $res = XDB::query('SELECT a.uid, a.password
- FROM accounts AS a
- INNER JOIN email_source_account AS e ON (e.uid = a.uid)
- WHERE e.email = {?}',
- $login);
+ if ($user === null) {
+ Platal::page()->trigError(self::TEXT_INVALID_LOGIN);
+ return false;
} else {
- $res = XDB::query('SELECT uid, password
- FROM accounts
- WHERE ' . $login_type . ' = {?}',
- $login);
- }
- if (list($uid, $password) = $res->fetchOneRow()) {
- $expected_response = sha1("$uname:$password:" . S::v('challenge'));
+ $password = $user->password();
+ $expected_response = sha1("$login:$password:" . S::v('challenge'));
/* Deprecates len(password) > 10 conversion. */
if ($response != $expected_response) {
if (!S::logged()) {
- Platal::page()->trigError('Mot de passe ou nom d\'utilisateur invalide');
+ Platal::page()->trigError(self::TEXT_INVALID_LOGIN);
} else {
- Platal::page()->trigError('Mot de passe invalide');
+ Platal::page()->trigError(self::TEXT_INVALID_PASS);
}
S::logger($uid)->log('auth_fail', 'bad password');
- return null;
+ return false;
}
- return $uid;
+ return true;
}
- Platal::page()->trigError('Mot de passe ou nom d\'utilisateur invalide');
- return null;
}
/** We come from an authentication form.
*/
if (S::suid()) {
- $login = $uname = S::suid('uid');
- $loginType = 'uid';
+ $login = S::suid('uid');
} else {
- $uname = Post::v('username');
- if (Post::s('domain') == "alias") {
- $login = XDB::fetchOneCell('SELECT uid
- FROM email_source_account
- WHERE email = {?} AND type = \'alias_aux\'',
- $uname);
- $loginType = 'uid';
- } else if (Post::s('domain') == 'hruid') {
- $login = $uname;
- $loginType = 'hruid';
- } else if ((Post::s('domain') == 'email')) {
- $login = XDB::fetchOneCell('SELECT SQL_CALC_FOUND_ROWS uid
- FROM accounts
- WHERE email = {?}',
- $uname);
- if (!(XDB::fetchOneCell('SELECT FOUND_ROWS()') == 1)) {
- $login =null;
- }
- $loginType = 'uid';
- } else {
- $login = $uname;
- $loginType = is_numeric($uname) ? 'uid' : 'alias';
- }
+ $login = Post::v('username');
}
- $uid = $this->checkPassword($uname, $login, Post::v('response'), $loginType);
- if (!is_null($uid) && S::suid()) {
- if (S::suid('uid') == $uid) {
- $uid = S::i('uid');
- } else {
- $uid = null;
- }
+ $user = User::getSilent($login);
+
+ $success = $this->checkPassword($login, $user, Post::v('response'));
+
+ if (!is_null($user) && S::suid()) {
+ $success = (S::suid('uid') == $user->id());
+ } else {
+ $success = $this->checkPassword($login, $user, Post::v('response'));
}
- if (!is_null($uid)) {
+
+ if ($success) {
S::set('auth', AUTH_MDP);
- if (!S::suid()) {
- if (Post::has('domain')) {
- $domain = Post::v('domain', 'login');
- if ($domain == 'alias') {
- Cookie::set('domain', 'alias', 300);
- } else if ($domain == 'ax') {
- Cookie::set('domain', 'ax', 300);
- } else {
- Cookie::kill('domain');
- }
- }
- }
S::kill('challenge');
- S::logger($uid)->log('auth_ok');
+ S::logger($user->id())->log('auth_ok');
}
- return User::getSilentWithUID($uid);
+ return $user;
}
protected function startSessionAs($user, $level)
$this->securityChecks();
$this->setSkin();
$this->updateNbNotifs();
- check_redirect();
+ // Only check email redirection for 'internal' users.
+ if ($user->checkPerms(PERMS_USER)) {
+ check_redirect();
+ }
// We should not have to use this private data anymore
S::kill('auth_by_cookie');
from="Polytechnique.org" <validation_modification@polytechnique.org>
cc="Polytechnique.org" <validation_modification@polytechnique.org>
+[password_recovery_xnet]
+from="Gestion des mots de passe" <support+password@polytechnique.org>
+
[xnet_notification]
from="Polytechnique.org" <contact@polytechnique.org>
; select a skin.
skin = "default"
-; $globals->register_skin
-; Skin to use during registration process
-register_skin = "register"
-
; $globals->core->econfiance
; Key used to perform transactions with the 'econfiance' webservice in order
; to synchronize the X-Informatique directory with polytechnique.net
per_page = 20
+; The SharingAPI section contains parameters about the 'sharing' webservice
+[SharingAPI]
+
+; $globals->sharingapi->max_result_per_query
+; Maximum number of results returned in an API response.
+max_result_per_query = 10;
+
+
; The register section contains parameters for the registration process
[Register]
secret = ""
; $globals->xnet->auth_baseurl
-; Baseur of the site used to perform authentication
+; Baseurl of the site used to perform authentication
auth_baseurl = ""
+; $globals->xnet->xorg_baseurl
+; Baseurl of the 'X.org' website
+xorg_baseurl = "https://www.polytechnique.org/"
+
; $globals->xnet->evts_domain
; Domain address where the aliases containing the list of (non-)subscribers
; of an event are created.
-Subproject commit 68785a05436244b5032f4399bb47f21b161075c9
+Subproject commit a552b53ac5b4e512720d77b457bfda823ed3e10b
}
document.forms.loginsub.username.value = document.forms.login.username.value;
document.forms.loginsub.remember.value = document.forms.login.remember.checked;
- document.forms.loginsub.domain.value = document.forms.login.domain.value;
document.forms.login.password.value = "";
document.forms.loginsub.submit();
}
--- /dev/null
+<?php
+/***************************************************************************
+ * Copyright (C) 2003-2011 Polytechnique.org *
+ * http://opensource.polytechnique.org/ *
+ * *
+ * This program 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. *
+ * *
+ * 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 Software *
+ * Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ ***************************************************************************/
+
+// {{{ class PartnerSharing
+// Holds data about a "directory partner".
+class PartnerSharing
+{
+ public $id;
+ public $shortname;
+ public $name;
+ public $url;
+ public $has_directory = false;
+ public $has_bulkmail = false;
+ public $default_sharing_level = Visibility::VIEW_NONE;
+ protected $api_uid = null;
+
+ protected function __construct(array $data)
+ {
+ foreach ($data as $key => $val) {
+ $this->$key = $val;
+ }
+ }
+
+ public function apiUser()
+ {
+ return User::getSilentWithUID($this->api_uid);
+ }
+
+ public static function fetchByAPIUser(User $user)
+ {
+ $res = XDB::fetchOneAssoc('SELECT id, shortname, name, url,
+ has_directory, has_bulkmail,
+ default_sharing_level, api_uid
+ FROM profile_partnersharing_enum
+ WHERE api_uid = {?}', $user->uid);
+ if ($res == null) {
+ return null;
+ } else {
+ return new PartnerSharing($res);
+ }
+ }
+
+ public static function fetchById($id)
+ {
+ $res = XDB::fetchOneAssoc('SELECT id, shortname, name, url,
+ has_directory, has_bulkmail,
+ default_sharing_level, api_uid
+ FROM profile_partnersharing_enum
+ WHERE id = {?}', $id);
+ if ($res == null) {
+ return null;
+ } else {
+ return new PartnerSharing($res);
+ }
+ }
+}
+// }}}
+// {{{ class PartnerSettings
+class PartnerSettings
+{
+ public $exposed_uid;
+ public $sharing_level;
+ public $allow_email = false;
+ protected $partner_id;
+ public $partner = null;
+
+ public function __construct(array $data)
+ {
+ foreach ($data as $key => $val) {
+ $this->$key = $val;
+ }
+ $this->partner = PartnerSharing::fetchById($this->partner_id);
+ $this->sharing_visibility = Visibility::get($this->sharing_level);
+ }
+
+ public static function getEmpty($partner_id)
+ {
+ $data = array(
+ 'partner_id' => $partner_id,
+ 'exposed_uid' => 0,
+ 'sharing_level' => Visibility::VIEW_NONE,
+ 'allow_email' => false,
+ );
+ return new PartnerSettings($data);
+ }
+}
+// }}}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
Profile::FETCH_MENTOR_COUNTRY => 'ProfileMentoringCountries',
Profile::FETCH_JOB_TERMS => 'ProfileJobTerms',
Profile::FETCH_MENTOR_TERMS => 'ProfileMentoringTerms',
+ Profile::FETCH_PARTNER => 'ProfilePartnerSharing',
);
/** The profile to which this field belongs
*
* MUST be reimplemented for each kind of ProfileField.
*/
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
return PlIteratorUtils::emptyIterator();
}
- public static function buildForPID($cls, $pid, ProfileVisibility $visibility)
+ public static function buildForPID($cls, $pid, Visibility $visibility)
{
$res = self::buildFromPIDs($cls, array($pid), $visibility);
return array_pop($res);
* @param $visibility An array of allowed visibility contexts
* @return An array of $pid => ProfileField
*/
- public static function buildFromPIDs($cls, array $pids, ProfileVisibility $visibility)
+ public static function buildFromPIDs($cls, array $pids, Visibility $visibility)
{
$it = new ProfileFieldIterator($cls, $pids, $visibility);
$res = array();
return $res;
}
- public static function getForPID($cls, $pid, ProfileVisibility $visibility)
+ public static function getForPID($cls, $pid, Visibility $visibility)
{
$it = new ProfileFieldIterator($cls, array($pid), $visibility);
return $it->next();
private $data;
private $cls;
- public function __construct($cls, array $pids, ProfileVisibility $visibility)
+ public function __construct($cls, array $pids, Visibility $visibility)
{
if (is_numeric($cls) && isset(ProfileField::$fields[$cls])) {
$cls = ProfileField::$fields[$cls];
public $user_site;
public $user_email;
+ public $pub;
+ public $email_pub;
+
/** Fields are:
* pid, id, company_id, description, url, email
*/
return $educations;
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT pe.id, pe.pid,
pe.entry_year, pe.grad_year, pe.program, pe.flags,
}
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT pm.pid, pm.mid, pm.gid, pme.text, pme.img, pmge.text AS grade
FROM profile_medals AS pm
LEFT JOIN profiles AS p ON (pm.pid = p.pid)
LEFT JOIN profile_medal_enum AS pme ON (pme.id = pm.mid)
LEFT JOIN profile_medal_grade_enum AS pmge ON (pmge.mid = pm.mid AND pmge.gid = pm.gid)
- WHERE pm.pid IN {?} AND p.medals_pub IN {?}
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE pm.pid IN {?} AND pve.best_display_level + 0 <= p.medals_pub + 0
ORDER BY ' . XDB::formatCustomOrder('pm.pid', $pids),
- $pids, $visibility->levels());
+ $visibility->level(), $pids);
return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
}
}
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT pid, id, address, pne.nwid, pne.network_type, pne.link, pne.name
FROM profile_networking AS pn
LEFT JOIN profile_networking_enum AS pne USING(nwid)
- WHERE pid IN {?} AND pub IN {?}
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE pn.pid IN {?} AND pve.best_display_level + 0 <= pn.pub + 0
ORDER BY ' . XDB::formatCustomOrder('pid', $pids) . ',
pn.nwid, id',
- $pids, $visibility->levels());
+ $visibility->level(), $pids);
return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
}
}
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT pc.pid, pc.original_corpsid AS original, pc.current_corpsid AS current,
pceo.name AS original_name, pceo.abbreviation AS original_abbrev,
LEFT JOIN profile_corps_enum AS pceo ON (pceo.id = pc.original_corpsid)
LEFT JOIN profile_corps_enum AS pcec ON (pcec.id = pc.current_corpsid)
LEFT JOIN profile_corps_rank_enum AS pcrec ON (pcrec.id = pc.rankid)
- WHERE pc.pid IN {?} AND pc.corps_pub IN {?} AND pceo.id != 1
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE pc.pid IN {?} AND pve.best_display_level + 0 <= pc.corps_pub + 0 AND pceo.id != 1
ORDER BY ' . XDB::formatCustomOrder('pid', $pids),
- $pids, $visibility->levels());
+ $visibility->level(), $pids);
return $data;
}
}
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT pmc.pid, pmc.country AS id, gc.country AS name
FROM profile_mentor_country AS pmc
return $addresses;
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
- $it = Address::iterate($pids, array(), array(), $visibility->levels());
+ $it = Address::iterate($pids, array(), array(), $visibility);
return PlIteratorUtils::subIterator($it->value(), PlIteratorUtils::arrayValueCallback('pid'));
}
return $phones;
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
- $it = Phone::iterate($pids, array(), array(), $visibility->levels());
+ $it = Phone::iterate($pids, array(), array(), $visibility);
return PlIteratorUtils::subIterator($it->value(), PlIteratorUtils::arrayValueCallback('pid'));
}
}
}
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
CompanyList::preload($pids);
- $data = XDB::iterator('SELECT id, pid, description, url as user_site, jobid,
- IF(email_pub IN {?}, email, NULL) AS user_email
+ $data = XDB::iterator('SELECT id, pid, description, url as user_site, jobid, pub, IF(pve.best_display_level + 0 <= email_pub + 0, email, NULL) AS user_email, email_pub
FROM profile_job
- WHERE pid IN {?} AND pub IN {?}
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE pid IN {?} AND pve.best_display_level + 0 <= pub + 0
ORDER BY ' . XDB::formatCustomOrder('pid', $pids) . ', id',
- $visibility->levels(), $pids, $visibility->levels());
+ $visibility->level(), $pids);
return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
}
return $this->jobterms;
}
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT jt.jtid, jte.full_name, jt.pid, jt.jid
FROM profile_job_term AS jt
INNER JOIN profile_job AS j ON (jt.pid = j.pid AND jt.jid = j.id)
LEFT JOIN profile_job_term_enum AS jte USING(jtid)
- WHERE jt.pid IN {?} AND j.pub IN {?}
+ LEFT JOIN profile_visibility_enum AS pve ON (pve.access_level = {?})
+ WHERE jt.pid IN {?} AND pve.best_display_level + 0 <= j.pub + 0
ORDER BY ' . XDB::formatCustomOrder('jt.pid', $pids),
- $pids, $visibility->levels());
+ $visibility->level(), $pids);
return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
}
}
// {{{ class ProfileMentoringTerms [ Field ]
class ProfileMentoringTerms extends ProfileJobTerms
{
- public static function fetchData(array $pids, ProfileVisibility $visibility)
+ public static function fetchData(array $pids, Visibility $visibility)
{
$data = XDB::iterator('SELECT mt.jtid, jte.full_name, mt.pid
FROM profile_mentor_term AS mt
}
}
// }}}
+// {{{ class ProfilePartnerSharing [ Field ]
+class ProfilePartnerSharing extends ProfileField
+{
+ public function __construct(PlInnerSubIterator $it)
+ {
+ require_once 'partnersharing.inc.php';
+
+ $this->pid = $it->value();
+ while ($partner_settings = $it->next()) {
+ $settings = new PartnerSettings($partner_settings);
+ $this->partners_settings[$settings->partner->id] = $settings;
+ }
+ }
+
+ public static function fetchData(array $pids, Visibility $visibility)
+ {
+ $data = XDB::iterator('SELECT ppss.pid, ppss.exposed_uid, ppss.sharing_level,
+ ppss.allow_email, ppss.partner_id,
+ ppse.shortname AS partner_shortname,
+ ppse.name AS partner_name,
+ ppse.url AS partner_url
+ FROM profile_partnersharing_settings AS ppss
+ LEFT JOIN profile_partnersharing_enum AS ppse ON (ppss.partner_id = ppse.id)
+ WHERE ppss.pid IN {?}
+ ORDER BY ' . XDB::formatCustomOrder('ppss.pid', $pids),
+ $pids);
+ return PlIteratorUtils::subIterator($data, PlIteratorUtils::arrayValueCallback('pid'));
+ }
+
+ public function get($partner_id)
+ {
+ if (isset($this->partners_settings[$partner_id])) {
+ return $this->partners_settings[$partner_id];
+ } else {
+ return PartnerSettings::getEmpty($partner_id);
+ }
+ }
+}
+// }}}
// {{{ class CompanyList
class CompanyList
{
// Add phones to hq
if (count($newcompanies)) {
- $it = Phone::iterate(array(), array(Phone::LINK_COMPANY), $newcompanies);
+ $it = Phone::iterate(array(), array(Phone::LINK_COMPANY), $newcompanies, Visibility::defaultForRead());
while ($phone = $it->next()) {
self::$companies[$phone->link_id]->setPhone($phone);
}
return null;
}
}
+// }}}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
?>
public function apply(PlPage $page)
{
$pids = $this->set->getIds(new PlLimit());
- $visibility = new ProfileVisibility(ProfileVisibility::VIS_AX);
+ $visibility = Visibility::defaultForRead(Visibility::VIEW_AX);
pl_cached_content_headers('text/x-csv', 1);
$csv = fopen('php://output', 'w');
protected function _mail_body($isok)
{
if ($isok) {
- return " Nous avons réussit à mieux localiser l'adresse.";
+ return " Nous avons réussi à mieux localiser l'adresse suivante :\n{$this->given_text}.";
} else {
return " L'adresse est suffisemment bien localisée pour les besoins du site (recherche avancée, planisphère), nous avons donc choisi de ne pas la modifier.";
}
$this->alias, $this->user->id(), Platal::globals()->mail->alias_dom);
}
+ if ($success) {
+ // Update the local User object, to pick up the new bestalias.
+ fix_bestalias($this->user);
+ $this->user = User::getSilentWithUID($this->user->id());
+ }
+
return $success;
}
}
public function __construct($photos = true, $freetext = null)
{
PlVCard::$folding = false;
- $this->visibility = new ProfileVisibility(ProfileVisibility::VIS_PRIVATE);
+ $this->visibility = Visibility::defaultForRead(Visibility::VIEW_PRIVATE);
$this->freetext = $freetext;
$this->photos = $photos;
}
define('PL_PAGE_CLASS', 'XnetPage');
require_once dirname(dirname(__FILE__)) . '/core/include/platal.inc.php';
-require_once 'security.inc.php';
require_once 'common.inc.php';
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
// TODO(vzanotti): Extend the plat/al engine to support placeholders
// in handler urls, for instance "api/1/user/%forlife/isRegistered".
'api/1/user' => $this->make_api_hook('user', AUTH_COOKIE, 'api_user_readonly'),
- 'api/1/search' => $this->make_api_hook('search', AUTH_COOKIE),
+ 'api/1/search' => $this->make_api_hook('search', AUTH_COOKIE, 'user'),
);
}
'webservices/manageurs.php' => $this->make_hook('manageurs', AUTH_PUBLIC, 'user', NO_HTTPS),
- 'auth-redirect.php' => $this->make_hook('redirect', AUTH_COOKIE),
- 'auth-groupex.php' => $this->make_hook('groupex_old', AUTH_COOKIE),
- 'auth-groupex' => $this->make_hook('groupex', AUTH_COOKIE),
+ 'auth-redirect.php' => $this->make_hook('redirect', AUTH_COOKIE, 'user'),
+ 'auth-groupex.php' => $this->make_hook('groupex_old', AUTH_COOKIE, 'user'),
+ 'auth-groupex' => $this->make_hook('groupex', AUTH_PUBLIC),
'admin/auth-groupes-x' => $this->make_hook('admin_authgroupesx', AUTH_MDP, 'admin'),
);
}
return $this->handler_groupex($page, 'iso-8859-1');
}
+ /** Handles the 'auth-groupe-x' authentication.
+ * Expects the following GET parameters:
+ * - pass: the 'password' for the authentication
+ * - challenge: the authentication challenge
+ * - url: the return URL
+ * - session: the remote PHP session ID
+ */
function handler_groupex($page, $charset = 'utf8')
{
+ if (!S::logged()) {
+ $page->assign('referer', true);
+ $page->setTitle('Authentification');
+ $page->setDefaultSkin('group_login');
+
+ if (Get::has('group')) {
+ $res = XDB::query('SELECT nom
+ FROM groups
+ WHERE diminutif = {?}', Get::s('group'));
+ $page->assign('group', $res->fetchOneCell());
+ } else {
+ $page->assign('group', null);
+ }
+ return PL_DO_AUTH;
+ }
+
$this->load('auth.inc.php');
- $page->assign('referer', true);
- $gpex_pass = $_GET["pass"];
- $gpex_url = urldecode($_GET["url"]);
- if (strpos($gpex_url, '?') === false) {
- $gpex_url .= "?PHPSESSID=" . $_GET["session"];
- } else {
- $gpex_url .= "&PHPSESSID=" . $_GET["session"];
+ $gpex_pass = Get::s('pass');
+ $gpex_url = urldecode(Get::s('url'));
+ if (Get::has('session')) {
+ if (strpos($gpex_url, '?') === false) {
+ $gpex_url .= "?PHPSESSID=" . Get::s('session');
+ } else {
+ $gpex_url .= "&PHPSESSID=" . Get::s('session');
+ }
}
// Normalize the return URL.
if (!preg_match("/^(http|https):\/\/.*/",$gpex_url)) {
$gpex_url = "http://$gpex_url";
}
- $gpex_challenge = $_GET["challenge"];
+ $gpex_challenge = Get::s('challenge');
// Update the last login information (unless the user is in SUID).
$uid = S::i('uid');
S::logger($uid)->log('connexion_auth_ext', $platal->path.' '.urldecode($_GET['url']));
}
+ if (Get::has('group')) {
+ $req_group_id = XDB::fetchOneCell('SELECT asso_id
+ FROM groups
+ WHERE diminutif = {?}',
+ Get::s('group'));
+ } else {
+ $req_group_id = null;
+ }
+
// Iterate over the auth token to find which one did sign the request.
- $res = XDB::iterRow('SELECT privkey, name, datafields, returnurls FROM group_auth');
- while (list($privkey,$name,$datafields,$returnurls) = $res->next()) {
+ $res = XDB::iterRow(
+ 'SELECT ga.privkey, ga.name, ga.datafields, ga.returnurls,
+ ga.group_id, ga.flags, g.nom
+ FROM group_auth AS ga
+ LEFT JOIN groups AS g ON (g.id = ga.group_id)');
+
+ while (list($privkey, $name, $datafields, $returnurls, $group_id, $group_flags, $group_name) = $res->next()) {
if (md5($gpex_challenge.$privkey) == $gpex_pass) {
$returnurls = trim($returnurls);
// We check that the return url matches a per-key regexp to prevent
SET last_used = DATE(NOW())
WHERE name = {?}',
$name);
+
+ // Two conditions control access to the return URL:
+ // - If that URL is attached to a group:
+ // - If the user belongs to the group, OK
+ // - If the user is 'xnet' and doesn't belong, NOK
+ // - If the user is not 'xnet' and the group is not 'strict', OK
+ // - If the user is not 'xnet' and the group is 'strict', NOK
+ // - Otherwise, all but 'xnet' accounts may access the URL.
+ $user_is_xnet = S::user()->type == 'xnet';
+ $group_flags = new PlFlagSet($group_flags);
+
+ // If this key is not attached to a group, but a group was
+ // requested (e.g query from wiki / blogs / ...), use the
+ // requested group_id.
+ if (!$group_id && $req_group_id) {
+ $group_id = $req_group_id;
+ }
+
+ if ($group_id) {
+ // Check group permissions
+ $is_member = XDB::fetchOneCell('SELECT COUNT(*)
+ FROM group_members
+ WHERE uid = {?} AND asso_id = {?}',
+ S::user()->id(), $group_id);
+ if (!$is_member && ($user_is_xnet || $group_flags->hasFlag('group_only'))) {
+ $page->kill("Le site demandé est réservé aux membres du groupe $group_name.");
+ }
+
+ } else if ($user_is_xnet && !$group_flags->hasFlag('allow_xnet')) {
+ $page->kill("Le site demandé est réservé aux polytechniciens.");
+ }
+
http_redirect($returl);
} else if (S::admin()) {
$page->kill("La requête d'authentification a échouée (url de retour invalide).");
function handlers()
{
return array(
- 'ax' => $this->make_hook('nl', AUTH_COOKIE),
+ 'ax' => $this->make_hook('nl', AUTH_COOKIE, 'user'),
'ax/out' => $this->make_hook('out', AUTH_PUBLIC),
- 'ax/show' => $this->make_hook('nl_show', AUTH_COOKIE),
- 'ax/search' => $this->make_hook('nl_search', AUTH_COOKIE),
- 'ax/admin' => $this->make_hook('admin_nl', AUTH_MDP),
- 'ax/admin/edit' => $this->make_hook('admin_nl_edit', AUTH_MDP),
- 'ax/admin/edit/valid' => $this->make_hook('admin_nl_valid', AUTH_MDP),
- 'ax/admin/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP),
- 'ax/admin/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP),
- 'ax/admin/categories' => $this->make_hook('admin_nl_cat', AUTH_MDP),
+ 'ax/show' => $this->make_hook('nl_show', AUTH_COOKIE, 'user'),
+ 'ax/search' => $this->make_hook('nl_search', AUTH_COOKIE, 'user'),
+ 'ax/admin' => $this->make_hook('admin_nl', AUTH_MDP, 'user'),
+ 'ax/admin/edit' => $this->make_hook('admin_nl_edit', AUTH_MDP, 'user'),
+ 'ax/admin/edit/valid' => $this->make_hook('admin_nl_valid', AUTH_MDP, 'user'),
+ 'ax/admin/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP, 'user'),
+ 'ax/admin/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP, 'user'),
+ 'ax/admin/categories' => $this->make_hook('admin_nl_cat', AUTH_MDP, 'user'),
);
}
return NewsLetter::forGroup(NewsLetter::GROUP_AX);
}
- function handler_out($page, $hash = null)
+ function handler_out($page, $hash = null, $issue_id = null)
{
if (!$hash) {
if (!S::logged()) {
return PL_DO_AUTH;
}
}
- return $this->handler_nl($page, 'out', $hash);
+ return $this->handler_nl($page, 'out', $hash, $issue_id);
}
}
function handlers()
{
return array(
- 'deltaten/search' => $this->make_hook('index', AUTH_COOKIE),
- 'deltaten' => $this->make_hook('index', AUTH_COOKIE),
+ 'deltaten/search' => $this->make_hook('index', AUTH_COOKIE, 'user'),
+ 'deltaten' => $this->make_hook('index', AUTH_COOKIE, 'user'),
);
}
'emails' => $this->make_hook('emails', AUTH_COOKIE, 'mail'),
'emails/alias' => $this->make_hook('alias', AUTH_MDP, 'mail'),
'emails/antispam' => $this->make_hook('antispam', AUTH_MDP, 'mail'),
- 'emails/broken' => $this->make_hook('broken', AUTH_COOKIE),
+ 'emails/broken' => $this->make_hook('broken', AUTH_COOKIE, 'user'),
'emails/redirect' => $this->make_hook('redirect', AUTH_MDP, 'mail'),
'emails/send' => $this->make_hook('send', AUTH_MDP, 'mail'),
- 'emails/antispam/submit' => $this->make_hook('submit', AUTH_COOKIE),
+ 'emails/antispam/submit' => $this->make_hook('submit', AUTH_COOKIE, 'user'),
'emails/test' => $this->make_hook('test', AUTH_COOKIE, 'mail', NO_AUTH),
'emails/rewrite/in' => $this->make_hook('rewrite_in', AUTH_PUBLIC),
WHERE uid = {?}", $user->id());
// Then gives the bestalias flag to the given email.
list($email, $domain) = explode('@', $email);
- XDB::execute("UPDATE email_source_account
+ XDB::execute("UPDATE email_source_account AS s
+ INNER JOIN email_virtual_domains AS m ON (m.id = s.domain)
+ INNER JOIN email_virtual_domains AS d ON (d.aliasing = m.id)
SET flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'bestalias')
- WHERE uid = {?} AND email = {?}", $user->id(), $email);
+ WHERE s.uid = {?} AND s.email = {?} AND d.name = {?}",
+ $user->id(), $email, $domain);
XDB::execute('UPDATE accounts AS a
INNER JOIN email_virtual_domains AS d ON (d.name = {?})
INNER JOIN email_virtual_domains AS m ON (d.aliasing = m.id)
function handlers()
{
return array(
- 'epletter' => $this->make_hook('nl', AUTH_COOKIE),
+ 'epletter' => $this->make_hook('nl', AUTH_COOKIE, 'user'),
'epletter/out' => $this->make_hook('out', AUTH_PUBLIC),
- 'epletter/show' => $this->make_hook('nl_show', AUTH_COOKIE),
- 'epletter/search' => $this->make_hook('nl_search', AUTH_COOKIE),
- 'epletter/admin' => $this->make_hook('admin_nl', AUTH_MDP),
- 'epletter/admin/edit' => $this->make_hook('admin_nl_edit', AUTH_MDP),
- 'epletter/admin/edit/valid' => $this->make_hook('admin_nl_valid', AUTH_MDP),
- 'epletter/admin/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP),
- 'epletter/admin/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP),
- 'epletter/admin/categories' => $this->make_hook('admin_nl_cat', AUTH_MDP),
+ 'epletter/show' => $this->make_hook('nl_show', AUTH_COOKIE, 'user'),
+ 'epletter/search' => $this->make_hook('nl_search', AUTH_COOKIE, 'user'),
+ 'epletter/admin' => $this->make_hook('admin_nl', AUTH_MDP, 'user'),
+ 'epletter/admin/edit' => $this->make_hook('admin_nl_edit', AUTH_MDP, 'user'),
+ 'epletter/admin/edit/valid' => $this->make_hook('admin_nl_valid', AUTH_MDP, 'user'),
+ 'epletter/admin/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP, 'user'),
+ 'epletter/admin/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP, 'user'),
+ 'epletter/admin/categories' => $this->make_hook('admin_nl_cat', AUTH_MDP, 'user'),
);
}
return NewsLetter::forGroup(NewsLetter::GROUP_EP);
}
- function handler_out($page, $hash = null)
+ function handler_out($page, $hash = null, $issue_id = null)
{
if (!$hash) {
if (!S::logged()) {
return PL_DO_AUTH;
}
}
- return $this->handler_nl($page, 'out', $hash);
+ return $this->handler_nl($page, 'out', $hash, $issue_id);
}
}
function handlers()
{
return array(
- 'events' => $this->make_hook('ev', AUTH_COOKIE),
+ 'events' => $this->make_hook('ev', AUTH_COOKIE, 'user'),
'events/preview' => $this->make_hook('preview', AUTH_PUBLIC, 'user', NO_AUTH),
'events/photo' => $this->make_hook('photo', AUTH_PUBLIC),
- 'events/submit' => $this->make_hook('ev_submit', AUTH_MDP),
+ 'events/submit' => $this->make_hook('ev_submit', AUTH_MDP, 'user'),
'admin/events' => $this->make_hook('admin_events', AUTH_MDP, 'admin'),
- 'rss' => $this->make_token_hook('rss', AUTH_COOKIE),
+ 'rss' => $this->make_token_hook('rss', AUTH_COOKIE, 'user'),
'ajax/tips' => $this->make_hook('tips', AUTH_COOKIE, 'user', NO_AUTH),
'admin/tips' => $this->make_hook('admin_tips', AUTH_MDP, 'admin'),
function handlers()
{
return array(
- 'map' => $this->make_hook('map', AUTH_COOKIE),
- 'map_url' => $this->make_hook('map_url', AUTH_COOKIE)
+ 'map' => $this->make_hook('map', AUTH_COOKIE, 'user'),
+ 'map_url' => $this->make_hook('map_url', AUTH_COOKIE, 'user')
);
}
function handlers()
{
return array(
- 'lists' => $this->make_hook('lists', AUTH_MDP),
+ 'lists' => $this->make_hook('lists', AUTH_MDP, 'user'),
'lists/ajax' => $this->make_hook('ajax', AUTH_MDP, 'user', NO_AUTH),
'lists/create' => $this->make_hook('create', AUTH_MDP, 'lists'),
- 'lists/members' => $this->make_hook('members', AUTH_COOKIE),
- 'lists/csv' => $this->make_hook('csv', AUTH_COOKIE),
- 'lists/annu' => $this->make_hook('annu', AUTH_COOKIE),
- 'lists/archives' => $this->make_hook('archives', AUTH_COOKIE),
+ 'lists/members' => $this->make_hook('members', AUTH_COOKIE, 'user'),
+ 'lists/csv' => $this->make_hook('csv', AUTH_COOKIE, 'user'),
+ 'lists/annu' => $this->make_hook('annu', AUTH_COOKIE, 'user'),
+ 'lists/archives' => $this->make_hook('archives', AUTH_COOKIE, 'user'),
'lists/archives/rss' => $this->make_hook('rss', AUTH_PUBLIC, 'user', NO_HTTPS),
- 'lists/moderate' => $this->make_hook('moderate', AUTH_MDP),
- 'lists/admin' => $this->make_hook('admin', AUTH_MDP),
- 'lists/options' => $this->make_hook('options', AUTH_MDP),
- 'lists/delete' => $this->make_hook('delete', AUTH_MDP),
+ 'lists/moderate' => $this->make_hook('moderate', AUTH_MDP, 'user'),
+ 'lists/admin' => $this->make_hook('admin', AUTH_MDP, 'user'),
+ 'lists/options' => $this->make_hook('options', AUTH_MDP, 'user'),
+ 'lists/delete' => $this->make_hook('delete', AUTH_MDP, 'user'),
- 'lists/soptions' => $this->make_hook('soptions', AUTH_MDP),
- 'lists/check' => $this->make_hook('check', AUTH_MDP),
+ 'lists/soptions' => $this->make_hook('soptions', AUTH_MDP, 'user'),
+ 'lists/check' => $this->make_hook('check', AUTH_MDP, 'user'),
'admin/lists' => $this->make_hook('admin_all', AUTH_MDP, 'admin'),
'admin/aliases' => $this->make_hook('aaliases', AUTH_MDP, 'admin')
);
function handlers()
{
return array(
- 'marketing' => $this->make_hook('marketing', AUTH_MDP, 'admin'),
- 'marketing/promo' => $this->make_hook('promo', AUTH_MDP, 'admin'),
- 'marketing/relance' => $this->make_hook('relance', AUTH_MDP, 'admin'),
- 'marketing/this_week' => $this->make_hook('week', AUTH_MDP, 'admin'),
- 'marketing/volontaire' => $this->make_hook('volontaire', AUTH_MDP, 'admin'),
-
- 'marketing/private' => $this->make_hook('private', AUTH_MDP, 'admin'),
- 'marketing/public' => $this->make_hook('public', AUTH_COOKIE),
- 'marketing/broken' => $this->make_hook('broken', AUTH_COOKIE),
+ 'marketing' => $this->make_hook('marketing', AUTH_MDP, 'admin'),
+ 'marketing/promo' => $this->make_hook('promo', AUTH_MDP, 'admin'),
+ 'marketing/relance' => $this->make_hook('relance', AUTH_MDP, 'admin'),
+ 'marketing/this_week' => $this->make_hook('week', AUTH_MDP, 'admin'),
+ 'marketing/volontaire' => $this->make_hook('volontaire', AUTH_MDP, 'admin'),
+
+ 'marketing/private' => $this->make_hook('private', AUTH_MDP, 'admin'),
+ 'marketing/public' => $this->make_hook('public', AUTH_COOKIE, 'user'),
+ 'marketing/broken' => $this->make_hook('broken', AUTH_COOKIE, 'user'),
);
}
function handlers()
{
return array(
- 'nl' => $this->make_hook('nl', AUTH_COOKIE),
- 'nl/show' => $this->make_hook('nl_show', AUTH_COOKIE),
- 'nl/search' => $this->make_hook('nl_search', AUTH_COOKIE),
- 'nl/submit' => $this->make_hook('nl_submit', AUTH_MDP),
- 'nl/remaining' => $this->make_hook('nl_remaining', AUTH_MDP),
- 'admin/nls' => $this->make_hook('admin_nl_groups', AUTH_MDP, 'admin'),
- 'admin/newsletter' => $this->make_hook('admin_nl', AUTH_MDP, 'admin'),
- 'admin/newsletter/categories' => $this->make_hook('admin_nl_cat', AUTH_MDP, 'admin'),
- 'admin/newsletter/edit' => $this->make_hook('admin_nl_edit', AUTH_MDP, 'admin'),
- 'admin/newsletter/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP, 'admin'),
+ 'nl' => $this->make_hook('nl', AUTH_COOKIE, 'user'),
+ 'nl/show' => $this->make_hook('nl_show', AUTH_COOKIE, 'user'),
+ 'nl/search' => $this->make_hook('nl_search', AUTH_COOKIE, 'user'),
+ 'nl/submit' => $this->make_hook('nl_submit', AUTH_MDP, 'user'),
+ 'nl/remaining' => $this->make_hook('nl_remaining', AUTH_MDP, 'user'),
+ 'admin/nls' => $this->make_hook('admin_nl_groups', AUTH_MDP, 'admin'),
+ 'admin/newsletter' => $this->make_hook('admin_nl', AUTH_MDP, 'admin'),
+ 'admin/newsletter/categories' => $this->make_hook('admin_nl_cat', AUTH_MDP, 'admin'),
+ 'admin/newsletter/edit' => $this->make_hook('admin_nl_edit', AUTH_MDP, 'admin'),
+ 'admin/newsletter/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP, 'admin'),
// Automatic mailing is disabled for X.org NL
// 'admin/newsletter/edit/cancel' => $this->make_hook('cancel', AUTH_MDP, 'admin'),
// 'admin/newsletter/edit/valid' => $this->make_hook('valid', AUTH_MDP, 'admin'),
return PL_NOT_FOUND;
}
- $page->changeTpl('newsletter/index.tpl');
- $page->setTitle('Lettres mensuelles');
-
$hash = ($hash == 'nohash') ? null : $hash;
switch ($action) {
- case 'out': $nl->unsubscribe($issue_id, $hash, $hash != null); break;
+ case 'out':
+ $success = $nl->unsubscribe($issue_id, $hash, $hash != null);
+ if (!is_null($hash)) {
+ if ($success) {
+ $page->trigSuccess('La désinscription a été effectuée avec succès.');
+ } else {
+ $page->trigError("La désinscription n'a été pas pu être effectuée.");
+ }
+ return;
+ }
+ break;
case 'in': $nl->subscribe(); break;
default: ;
}
+ $page->changeTpl('newsletter/index.tpl');
+ $page->setTitle('Lettres mensuelles');
+
$page->assign_by_ref('nl', $nl);
$page->assign('nls', $nl->subscriptionState());
$page->assign('nl_list', $nl->listSentIssues(true));
'openid' => $this->make_hook('openid', AUTH_PUBLIC),
'openid/melix' => $this->make_hook('melix', AUTH_PUBLIC),
'openid/xrds' => $this->make_hook('xrds', AUTH_PUBLIC),
- 'openid/trust' => $this->make_hook('trust', AUTH_MDP),
- 'openid/trusted' => $this->make_hook('trusted', AUTH_MDP),
+ 'openid/trust' => $this->make_hook('trust', AUTH_MDP, 'user'),
+ 'openid/trusted' => $this->make_hook('trusted', AUTH_MDP, 'user'),
'admin/openid/trusted' => $this->make_hook('admin_trusted', AUTH_MDP, 'admin'),
);
}
'payment' => $this->make_hook('payment', AUTH_MDP, 'payment'),
'payment/cyber2_return' => $this->make_hook('cyber2_return', AUTH_PUBLIC, 'user', NO_HTTPS),
'payment/paypal_return' => $this->make_hook('paypal_return', AUTH_PUBLIC, 'user', NO_HTTPS),
- '%grp/paiement' => $this->make_hook('xnet_payment', AUTH_MDP),
- '%grp/payment' => $this->make_hook('xnet_payment', AUTH_MDP),
+ '%grp/paiement' => $this->make_hook('xnet_payment', AUTH_MDP, 'user'),
+ '%grp/payment' => $this->make_hook('xnet_payment', AUTH_MDP, 'user'),
'%grp/payment/csv' => $this->make_hook('payment_csv', AUTH_MDP, 'groupadmin'),
'%grp/payment/cyber2_return' => $this->make_hook('cyber2_return', AUTH_PUBLIC, 'user', NO_HTTPS),
'%grp/payment/paypal_return' => $this->make_hook('paypal_return', AUTH_PUBLIC, 'user', NO_HTTPS),
'changelog' => $this->make_hook('changelog', AUTH_PUBLIC),
// Preferences thingies
- 'prefs' => $this->make_hook('prefs', AUTH_COOKIE),
- 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE),
- 'prefs/webredirect' => $this->make_hook('webredir', AUTH_MDP, 'mail'),
- 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE),
+ 'prefs' => $this->make_hook('prefs', AUTH_COOKIE, 'user,groups'),
+ 'prefs/rss' => $this->make_hook('prefs_rss', AUTH_COOKIE, 'user'),
+ 'prefs/webredirect' => $this->make_hook('webredir', AUTH_MDP, 'mail'),
+ 'prefs/skin' => $this->make_hook('skin', AUTH_COOKIE, 'user'),
// password related thingies
- 'password' => $this->make_hook('password', AUTH_MDP),
+ 'password' => $this->make_hook('password', AUTH_MDP, 'user,groups'),
'tmpPWD' => $this->make_hook('tmpPWD', AUTH_PUBLIC),
- 'password/smtp' => $this->make_hook('smtppass', AUTH_MDP, 'mail'),
+ 'password/smtp' => $this->make_hook('smtppass', AUTH_MDP, 'mail'),
'recovery' => $this->make_hook('recovery', AUTH_PUBLIC),
+ 'recovery/ext' => $this->make_hook('recovery_ext', AUTH_PUBLIC),
+ 'register/ext' => $this->make_hook('register_ext', AUTH_PUBLIC),
'exit' => $this->make_hook('exit', AUTH_PUBLIC),
'review' => $this->make_hook('review', AUTH_PUBLIC),
'deconnexion.php' => $this->make_hook('exit', AUTH_PUBLIC),
S::logger($user->id())->log('recovery', is_null($to) ? $inactives_to . ', ' . $user->bestEmail() : $to);
}
+ function handler_recovery_ext($page)
+ {
+ $page->changeTpl('xnet/recovery.tpl');
+
+ if (!Post::has('login')) {
+ return;
+ }
+
+ $user = User::getSilent(Post::t('login'));
+ if (is_null($user)) {
+ $page->trigError('Le compte n\'existe pas.');
+ return;
+ }
+ if ($user->state != 'active') {
+ $page->trigError('Ton compte n\'est pas activé.');
+ return;
+ }
+
+ $page->assign('ok', true);
+
+ $hash = rand_url_id();
+ XDB::execute('INSERT INTO account_lost_passwords (uid, created, certificat)
+ VALUES ({?}, NOW(), {?})',
+ $user->id(), $hash);
+
+ $mymail = new PlMailer('platal/password_recovery_xnet.mail.tpl');
+ $mymail->addTo($user);
+ $mymail->assign('hash', $hash);
+ $mymail->assign('email', Post::t('login'));
+ $mymail->send();
+
+ S::logger($user->id())->log('recovery', $user->bestEmail());
+ }
+
function handler_tmpPWD($page, $certif = null)
{
global $globals;
- // XXX: recovery requires data from the profile
XDB::execute('DELETE FROM account_lost_passwords
WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > created');
}
}
+ function handler_register_ext($page, $hash = null)
+ {
+ XDB::execute('DELETE FROM register_pending_xnet
+ WHERE DATE_SUB(NOW(), INTERVAL 1 MONTH) > date');
+ $res = XDB::fetchOneAssoc('SELECT uid, hruid, email
+ FROM register_pending_xnet
+ WHERE hash = {?}',
+ $hash);
+
+ if (is_null($hash) || is_null($res)) {
+ $page->trigErrorRedirect('Cette adresse n\'existe pas ou n\'existe plus sur le serveur.', '');
+ }
+
+ if (Post::has('pwhash') && Post::t('pwhash')) {
+ XDB::startTransaction();
+ XDB::query('UPDATE accounts
+ SET password = {?}, state = \'active\', registration_date = NOW()
+ WHERE uid = {?} AND state = \'pending\' AND type = \'xnet\'',
+ Post::t('pwhash'), $res['uid']);
+ XDB::query('DELETE FROM register_pending_xnet
+ WHERE uid = {?}',
+ $res['uid']);
+ XDB::commit();
+
+ S::logger($res['uid'])->log('passwd', '');
+
+ // Try to start a session (so the user don't have to log in); we will use
+ // the password available in Post:: to authenticate the user.
+ Post::kill('wait');
+ Platal::session()->startAvailableAuth();
+
+ $page->changeTpl('xnet/register.success.tpl');
+ $page->assign('email', $res['email']);
+ } else {
+ $page->changeTpl('platal/password.tpl');
+ $page->assign('xnet', true);
+ $page->assign('hruid', $res['hruid']);
+ $page->assign('do_auth', 1);
+ }
+ }
+
function handler_skin($page)
{
global $globals;
{
return array(
'photo' => $this->make_hook('photo', AUTH_PUBLIC),
- 'photo/change' => $this->make_hook('photo_change', AUTH_MDP),
+ 'photo/change' => $this->make_hook('photo_change', AUTH_MDP, 'user'),
'fiche.php' => $this->make_hook('fiche', AUTH_PUBLIC),
'profile' => $this->make_hook('profile', AUTH_PUBLIC),
- 'profile/private' => $this->make_hook('profile', AUTH_COOKIE),
+ 'profile/private' => $this->make_hook('profile', AUTH_COOKIE, 'user'),
'profile/ax' => $this->make_hook('ax', AUTH_COOKIE, 'admin,edit_directory'),
- 'profile/edit' => $this->make_hook('p_edit', AUTH_MDP),
+ 'profile/edit' => $this->make_hook('p_edit', AUTH_MDP, 'user'),
'profile/ajax/address' => $this->make_hook('ajax_address', AUTH_COOKIE, 'user', NO_AUTH),
- 'profile/ajax/address/del' => $this->make_hook('ajax_address_del', AUTH_MDP),
+ 'profile/ajax/address/del' => $this->make_hook('ajax_address_del', AUTH_MDP, 'user'),
'profile/ajax/tel' => $this->make_hook('ajax_tel', AUTH_COOKIE, 'user', NO_AUTH),
'profile/ajax/edu' => $this->make_hook('ajax_edu', AUTH_COOKIE, 'user', NO_AUTH),
'profile/ajax/medal' => $this->make_hook('ajax_medal', AUTH_COOKIE, 'user', NO_AUTH),
'profile/ajax/buildnames' => $this->make_hook('ajax_buildnames', AUTH_COOKIE, 'user', NO_AUTH),
'profile/ajax/tree/jobterms' => $this->make_hook('ajax_tree_job_terms', AUTH_COOKIE, 'user', NO_AUTH),
'profile/jobterms' => $this->make_hook('jobterms', AUTH_COOKIE, 'user', NO_AUTH),
- 'javascript/education.js' => $this->make_hook('education_js', AUTH_COOKIE),
- 'javascript/grades.js' => $this->make_hook('grades_js', AUTH_COOKIE),
+ 'javascript/education.js' => $this->make_hook('education_js', AUTH_COOKIE, 'user'),
+ 'javascript/grades.js' => $this->make_hook('grades_js', AUTH_COOKIE, 'user'),
'profile/medal' => $this->make_hook('medal', AUTH_PUBLIC),
- 'referent' => $this->make_hook('referent', AUTH_COOKIE),
+ 'referent' => $this->make_hook('referent', AUTH_COOKIE, 'user'),
'referent/country' => $this->make_hook('ref_country', AUTH_COOKIE, 'user', NO_AUTH),
'referent/autocomplete' => $this->make_hook('ref_autocomplete', AUTH_COOKIE, 'user', NO_AUTH),
- 'groupes-x' => $this->make_hook('xnet', AUTH_COOKIE),
+ 'groupes-x' => $this->make_hook('xnet', AUTH_COOKIE, 'groups'),
'groupes-x/logo' => $this->make_hook('xnetlogo', AUTH_PUBLIC),
'vcard' => $this->make_hook('vcard', AUTH_COOKIE, 'user', NO_HTTPS),
}
// Determines the access level at which the profile will be displayed.
- if (!S::logged() || !S::user()->checkPerms('directory_ax') || Env::v('view') == 'public') {
- $view = 'public';
- } else if (!S::user()->checkPerms('directory_private') || Env::v('view') == 'ax') {
- $view = 'ax';
+ if (Env::v('view') == 'public') {
+ $view = Visibility::VIEW_PUBLIC;
+ } else if (Env::v('view') == 'ax') {
+ $view = Visibility::VIEW_AX;
} else {
- $view = 'private';
+ $view = Visibility::VIEW_PRIVATE;
}
+ $visibility = Visibility::defaultForRead($view);
// Display pending picture
if (S::logged() && Env::v('modif') == 'new') {
if (is_null($pid)) {
$owner = User::getSilent($id);
if ($owner) {
- $profile = $owner->profile(true, Profile::FETCH_ALL, $view);
+ $profile = $owner->profile(true, Profile::FETCH_ALL, $visibility);
if ($profile) {
$pid = $profile->id();
}
} else {
// Fetches profile's and profile's owner information and redirects to
// marketing if the owner has not subscribed and the requirer has logged in.
- $profile = Profile::get($pid, Profile::FETCH_ALL, $view);
+ $profile = Profile::get($pid, Profile::FETCH_ALL, $visibility);
$owner = $profile->owner();
}
if (is_null($pid)) {
}
return PL_NOT_FOUND;
}
+
// Now that we know this is an existing profile, we can switch to the
// appropriate template.
$page->changeTpl('profile/profile.tpl', SIMPLE);
$page->setTitle($profile->fullName());
// Determines and displays the virtual alias.
- if (!is_null($owner) && $profile->alias_pub == 'public') {
+ if (!is_null($owner) && $profile->isVisible($profile->alias_pub)) {
$page->assign('virtualalias', $owner->emailAlias());
}
$page->assign_by_ref('profile', $profile);
$page->assign_by_ref('owner', $owner);
- $page->assign('view', $view);
+ $page->assign('view', $visibility);
$page->assign('logged', S::logged());
header('Last-Modified: ' . date('r', strtotime($profile->last_change)));
if (!S::user()->isMe($this->owner)) {
$this->settings['deathdate'] = new ProfileSettingDate(true);
$this->settings['birthdate'] = new ProfileSettingDate(true);
+ $this->settings['birthdate_ref'] = new ProfileSettingDate(true);
} else {
$this->settings['yourself'] = null;
$this->settings['birthdate'] = new ProfileSettingDate();
$res = XDB::query("SELECT p.nationality1, p.nationality2, p.nationality3, IF(p.birthdate = 0, '', p.birthdate) AS birthdate,
p.email_directory as email_directory, pd.promo AS promo_display,
p.freetext, p.freetext_pub, p.ax_id AS matricule_ax, pd.yourself,
- p.deathdate
+ p.deathdate, IF(p.birthdate_ref = 0, '', p.birthdate_ref) AS birthdate_ref
FROM profiles AS p
INNER JOIN profile_display AS pd ON (pd.pid = p.pid)
WHERE p.pid = {?}", $this->pid());
}
}
}
+ if ($this->orig['birthdate_ref'] == 0 && !S::user()->isMe($this->owner) && $this->changed['birthdate_ref']) {
+ XDB::execute('UPDATE profiles
+ SET birthdate_ref = {?}
+ WHERE pid = {?}',
+ ProfileSettingDate::toSQLDate($this->values['birthdate_ref']), $this->pid());
+ }
if (!S::user()->isMe($this->owner) && $this->changed['deathdate']) {
XDB::execute('UPDATE profiles
SET deathdate = {?}, deathdate_rec = NOW()
return $jobs;
}
- private function cleanJob(ProfilePage $page, $jobid, array &$job, &$success, $maxPublicity)
+ private function cleanJob(ProfilePage $page, $jobid, array &$job, &$success, $job_level)
{
if ($job['w_email'] == "new@example.org") {
$job['w_email'] = $job['w_email_new'];
}
}
- if ($maxPublicity->isVisible($job['w_email_pub'])) {
- $job['w_email_pub'] = $maxPublicity->level();
+ if (Visibility::isLessRestrictive($job['w_email_pub'], $job_level)) {
+ $job['w_email_pub'] = $job_level;
}
- $job['w_phone'] = Phone::formatFormArray($job['w_phone'], $s, $maxPublicity);
+ $job['w_phone'] = Phone::formatFormArray($job['w_phone'], $s, $job_level);
if ($job['w_entry_year'] && strlen($job['w_entry_year']) != 4) {
$job['w_entry_year_error'] = true;
foreach ($value as $key => &$job) {
$address = new Address($job['w_address']);
$s = $address->format();
- $maxPublicity = new ProfileVisibility($job['pub']);
- if ($maxPublicity->isVisible($address->pub)) {
- $address->pub = $maxPublicity->level();
+
+ // Force the address publicity to be at least as restricted as
+ // the job publicity.
+ $job_level = $job['pub'];
+ if (Visibility::isLessRestrictive($address->pub, $job_level)) {
+ $address->pub = $job_level;
}
$job['w_address'] = $address->toFormArray();
- $this->cleanJob($page, $key, $job, $s, $maxPublicity);
+ $this->cleanJob($page, $key, $job, $s, $job_level);
if (!$init) {
$success = ($success && $s);
}
}
- usort($value, 'ProfileVisibility::comparePublicity');
+ usort($value, 'Visibility::comparePublicity');
return $value;
}
$phones = array();
if (is_null($value)) {
- $it = Phone::iterate(array($page->pid()), array(Phone::LINK_PROFILE), array(0));
+ $it = Phone::iterate(array($page->pid()), array(Phone::LINK_PROFILE), array(0), Visibility::defaultForEdit());
while ($phone = $it->next()) {
$success = ($phone->format() && $success);
$phones[] = $phone->toFormArray();
function handler_register($page, $hash = null)
{
+ $page->forceSkin('register');
+
$alert = array();
$alert_details = '';
$subState = new PlDict(S::v('subState', array()));
if (abs($ref_year - $year) > 2) {
$error[] = "La 'Date de naissance' n'est pas correcte.";
$alert[] = "Date de naissance incorrecte à l'inscription";
- $alert_details .= "\n * Date de naissance renseignée : " . $birth . ' (date connue : ' . $subState->v('birthdateRef') . ')';
+ $alert_details .= "\n * Date de naissance renseignée : " . Post::t('birthdate') . ' (date connue : ' . $subState->v('birthdateRef') . ')';
$subState->set('wrong_birthdate', $birth);
}
}
if ($subState->s('birthdateRef') != '0000-00-00'
&& $subState->s('birthdateRef') != $subState->s('birthdate')) {
$alert[] = "Date de naissance incorrecte à l'inscription";
- $alert_details .= "\n * Date de naissance renseignée : " . $subState->s('birthdateRef') . ' (date connue : ' . $subState->s('birthdateRef') . ')';
+ $alert_details .= "\n * Date de naissance renseignée : " . $subState->s('birthdate') . ' (date connue : ' . $subState->s('birthdateRef') . ')';
}
if ($bannedIp) {
$alert[] = "Tentative d'inscription depuis une IP surveillée";
function handlers()
{
return array(
- 'ajax/reminder' => $this->make_hook('reminder', AUTH_COOKIE),
+ 'ajax/reminder' => $this->make_hook('reminder', AUTH_COOKIE, 'user'),
);
}
'search/autocomplete' => $this->make_hook('autocomplete', AUTH_COOKIE, 'directory_ax', NO_AUTH),
'search/list' => $this->make_hook('list', AUTH_COOKIE, 'directory_ax', NO_AUTH),
'search/list/count' => $this->make_hook('list_count', AUTH_COOKIE, 'directory_ax', NO_AUTH),
- 'jobs' => $this->make_hook('referent', AUTH_COOKIE),
- 'emploi' => $this->make_hook('referent', AUTH_COOKIE),
- 'referent/search' => $this->make_hook('referent', AUTH_COOKIE),
- 'search/referent/countries' => $this->make_hook('referent_countries', AUTH_COOKIE),
+ 'jobs' => $this->make_hook('referent', AUTH_COOKIE, 'user'),
+ 'emploi' => $this->make_hook('referent', AUTH_COOKIE, 'user'),
+ 'referent/search' => $this->make_hook('referent', AUTH_COOKIE, 'user'),
+ 'search/referent/countries' => $this->make_hook('referent_countries', AUTH_COOKIE, 'user'),
);
}
--- /dev/null
+<?php
+/***************************************************************************
+ * Copyright (C) 2003-2011 Polytechnique.org *
+ * http://opensource.polytechnique.org/ *
+ * *
+ * This program 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. *
+ * *
+ * 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 Software *
+ * Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ ***************************************************************************/
+
+
+class SharingAPIModule extends PlModule
+{
+ function handlers()
+ {
+ return array(
+ 'api/1/sharing/search' => $this->make_api_hook('search', AUTH_COOKIE, 'api_user_readonly'),
+ 'api/1/sharing/bulkmail' => $this->make_api_hook('bulkmail', AUTH_COOKIE, 'api_user_readonly'),
+ 'api/1/sharing/picture' => $this->make_hook('picture_token', AUTH_PUBLIC),
+ );
+ }
+
+ function handler_search(PlPage $page, PlUser $authUser, $payload)
+ {
+ require_once 'partnersharing.inc.php';
+ $partner = PartnerSharing::fetchByAPIUser($authUser);
+ if ($partner == null || !$partner->has_directory) {
+ return PL_FORBIDDEN;
+ }
+
+ $this->load('request.inc.php');
+
+ $payload = new PlDict($payload);
+
+ $errors = WSDirectoryRequest::validatePayload($payload);
+
+ if (count($errors)) {
+ foreach ($errors as $error_code) {
+ $page->trigError(WSDirectoryRequest::$ERROR_MESSAGES[$error_code]);
+ }
+ return PL_BAD_REQUEST;
+ }
+
+ // Processing
+ $request = new WSDirectoryRequest($partner, $payload);
+ $request->assignToPage($page);
+ return PL_JSON;
+ }
+
+ function handler_bulkmail(PlPage $page, PlUser $authUser, $payload)
+ {
+ require_once 'partnersharing.inc.php';
+ $partner = PartnerSharing::fetchByAPIUser($authUser);
+ if ($partner == null || !$partner->has_bulkmail) {
+ return PL_FORBIDDEN;
+ }
+
+ if (!isset($payload['uids'])) {
+ $page->trigError('Malformed query.');
+ return PL_BAD_REQUEST;
+ }
+
+ $uids = $payload['uids'];
+
+ $pf = new UserFilter(
+ new PFC_And(
+ new UFC_PartnerSharingID($partner->id, $uids),
+ new UFC_HasValidEmail(),
+ new UFC_PartnerSharingEmail($partner->id)
+ ));
+
+ $contexts = array();
+ foreach ($pf->iterUsers() as $user) {
+ $contexts[] = array(
+ 'name' => $user->fullName(),
+ 'email' => $user->bestEmail(),
+ 'gender' => $user->isFemale() ? 'woman' : 'man',
+ );
+ }
+ $page->jsonAssign('contexts', $contexts);
+ return PL_JSON;
+ }
+
+ function handler_picture_token(PlPage $page, $size, $token)
+ {
+ XDB::rawExecute('DELETE FROM profile_photo_tokens
+ WHERE expires <= NOW()');
+ $pid = XDB::fetchOneCell('SELECT pid
+ FROM profile_photo_tokens
+ WHERE token = {?}', $token);
+ if ($pid != null) {
+ $res = XDB::fetchOneAssoc('SELECT attach, attachmime, x, y, last_update
+ FROM profile_photos
+ WHERE pid = {?}', $pid);
+ $photo = PlImage::fromData($res['attach'], 'image/' . $res['attachmime'], $res['x'], $res['y'], $res['last_update']);
+ $photo->send();
+ } else {
+ return PL_NOT_FOUND;
+ }
+ }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
--- /dev/null
+<?php
+/***************************************************************************
+ * Copyright (C) 2003-2011 Polytechnique.org *
+ * http://opensource.polytechnique.org/ *
+ * *
+ * This program 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. *
+ * *
+ * 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 Software *
+ * Foundation, Inc., *
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
+ ***************************************************************************/
+
+
+class WSDirectoryRequest
+{
+ // Default number of returned results.
+ const DEFAULT_AMOUNT = 20;
+
+ public $fields;
+ public $criteria;
+ public $order = array();
+ public $amount = 0;
+ protected $partner = null;
+
+ const ORDER_RAND = 'rand';
+ const ORDER_NAME = 'name';
+ const ORDER_PROMOTION = 'promotion';
+
+ public static $order_choices = array(
+ self::ORDER_RAND,
+ self::ORDER_NAME,
+ self::ORDER_PROMOTION,
+ );
+
+ public function __construct($partner, PlDict $payload)
+ {
+ $this->partner = $partner;
+ global $globals;
+
+ $this->fields = array_intersect($payload->v('fields'), WSRequestFields::$choices);
+ $this->order = array_intersect($payload->v('order', array()), self::$order_choices);
+
+ $this->criteria = array();
+ $criteria = new PlDict($payload->v('criteria'));
+ foreach (WSRequestCriteria::$choices_simple as $criterion) {
+ if ($criteria->has($criterion)) {
+ $this->criteria[$criterion] = $criteria->s($criterion);
+ }
+ }
+ foreach (WSRequestCriteria::$choices_enum as $criterion) {
+ if ($criteria->has($criterion)) {
+ $this->criteria[$criterion] = $criteria->s($criterion);
+ }
+ }
+ foreach (WSRequestCriteria::$choices_list as $criterion) {
+ if ($criteria->has($criterion)) {
+ $this->criteria[$criterion] = $criteria->v($criterion);
+ }
+ }
+
+ // Amount may not exceed $globals->sharingapi->max_result_per_query.
+ $amount = $payload->i('amount', self::DEFAULT_AMOUNT);
+ $this->amount = min($amount, $globals->sharingapi->max_result_per_query);
+ }
+
+ public function get()
+ {
+ $cond = $this->getCond();
+ $cond->addChild(new UFC_PartnerSharing($this->partner->id));
+ $pf = new ProfileFilter($cond, $this->getOrders());
+ $pf->restrictVisibilityForPartner($this->partner->id);
+ $response = array();
+ $matches = $pf->getTotalProfileCount();
+ $response['matches'] = $matches;
+
+ $profiles = array();
+ if ($matches) {
+ // TODO : improve fetching by passing an adequate FETCH field
+ $iter = $pf->iterProfiles(new PlLimit($this->amount), 0x0000, Visibility::get(Visibility::VIEW_PRIVATE));
+ while ($profile = $iter->next()) {
+ if ($profile->getPartnerSettings($this->partner->id)->exposed_uid !== 0) {
+ $profile_data = new WSRequestEntry($this->partner, $profile);
+ $profiles[] = $profile_data->getFields($this->fields);
+ }
+ }
+ }
+ $response['profiles'] = $profiles;
+ return $response;
+ }
+
+ public function assignToPage(PlPage $page)
+ {
+ $response = $this->get();
+ $page->jsonAssign('matches', $response['matches']);
+ $page->jsonAssign('profiles', $response['profiles']);
+ }
+
+ /** Compute the orders to use for the current request.
+ * @return array of PlFilterOrder
+ */
+ protected function getOrders()
+ {
+ $orders = array();
+ foreach ($this->order as $order)
+ {
+ switch ($order) {
+ case self::ORDER_RAND:
+ $orders[] = new PFO_Random();
+ break;
+ case self::ORDER_NAME:
+ $orders[] = new UFO_Name(Profile::DN_SORT);
+ break;
+ case self::ORDER_PROMOTION:
+ $orders[] = new UFO_Promo();
+ break;
+ default:
+ break;
+ }
+ }
+ return $orders;
+ }
+
+ /** Compute the conditions to use for the current request.
+ * @return A PlFilterCondition instance (actually a PFC_And)
+ */
+ protected function getCond()
+ {
+ $cond = new PFC_And();
+ foreach ($this->criteria as $criterion => $value) {
+ switch ($criterion) {
+
+ // ENUM fields
+ case WSRequestCriteria::SCHOOL:
+ // Useless criterion: we don't need to check on origin school
+ if (WSRequestCriteria::$choices_enum[$criterion][$value]) {
+ $cond->addChild(new PFC_True());
+ } else {
+ $cond->addChild(new PFC_False());
+ };
+ break;
+ case WSRequestCriteria::DIPLOMA:
+ $diploma = WSRequestCriteria::$choices_enum[$criterion][$value];
+ $id_X = XDB::fetchOneCell('SELECT id
+ FROM profile_education_enum
+ WHERE abbreviation = {?}', 'X');
+ $cond->addChildren(array(
+ new UFC_EducationSchool($id_X),
+ new UFC_EducationDegree($diploma),
+ ));
+ break;
+
+ // TEXT fields
+ case WSRequestCriteria::FIRSTNAME:
+ case WSRequestCriteria::LASTNAME:
+ $cond->addChild(new UFC_NameTokens($value, UFC_NameTokens::FLAG_PUBLIC, false, false, $criterion));
+ break;
+ case WSRequestCriteria::PROMOTION:
+ $cond->addChild(new PFC_Or(
+ new UFC_Promo(UserFilter::OP_EQUALS,
+ UserFilter::GRADE_ING,
+ $value),
+ new UFC_Promo(UserFilter::OP_EQUALS,
+ UserFilter::GRADE_MST,
+ $value),
+ new UFC_Promo(UserFilter::OP_EQUALS,
+ UserFilter::GRADE_PHD,
+ $value)
+ ));
+ break;
+ case WSRequestCriteria::ALT_DIPLOMA:
+ $cond->addChild(
+ new UFC_EducationDegree(
+ DirEnum::getIds(DirEnum::EDUDEGREES, $value)));
+ break;
+ case WSRequestCriteria::DIPLOMA_FIELD:
+ $cond->addChild(
+ new UFC_EducationField(
+ DirEnum::getIds(DirEnum::EDUFIELDS, $value)));
+ break;
+ case WSRequestCriteria::CITY:
+ $cond->addChild(
+ new UFC_AddressField($value,
+ UFC_AddressField::FIELD_LOCALITY,
+ UFC_Address::TYPE_HOME,
+ UFC_Address::FLAG_CURRENT));
+ break;
+ case WSRequestCriteria::COUNTRY:
+ $cond->addChild(
+ new UFC_AddressField($value,
+ UFC_AddressField::FIELD_COUNTRY,
+ UFC_Address::TYPE_HOME,
+ UFC_Address::FLAG_CURRENT));
+ break;
+ case WSRequestCriteria::ZIPCODE:
+ $cond->addChild(
+ new UFC_AddressField($value,
+ UFC_AddressField::FIELD_ZIPCODE,
+ UFC_Address::TYPE_HOME,
+ UFC_Address::FLAG_CURRENT));
+ break;
+ case WSRequestCriteria::JOB_ANY_COUNTRY:
+ $cond->addChild(
+ new UFC_AddressField($value,
+ UFC_AddressField::FIELD_COUNTRY,
+ UFC_Address::TYPE_PRO,
+ UFC_Address::FLAG_ANY));
+ break;
+ case WSRequestCriteria::JOB_CURRENT_CITY:
+ $cond->addChild(
+ new UFC_AddressField($value,
+ UFC_AddressField::FIELD_LOCALITY,
+ UFC_Address::TYPE_PRO,
+ UFC_Address::FLAG_ANY));
+ break;
+ case WSRequestCriteria::JOB_ANY_COMPANY:
+ case WSRequestCriteria::JOB_CURRENT_COMPANY:
+ $cond->addChild(
+ new UFC_Job_Company(UFC_Job_Company::JOBNAME,
+ $value));
+ break;
+ case WSRequestCriteria::JOB_ANY_SECTOR:
+ case WSRequestCriteria::JOB_CURRENT_SECTOR:
+ case WSRequestCriteria::JOB_CURRENT_TITLE:
+ $cond->addChild(
+ new UFC_Job_Terms(DirEnum::getIds(DirEnum::JOBTERMS, $value)));
+ break;
+
+ // LIST fields
+ case WSRequestCriteria::HOBBIES:
+ $subcond = new PFC_Or();
+ foreach ($value as $val) {
+ $subcond->addChild(new UFC_Comment($value));
+ }
+ $cond->addChild($subcond);
+ break;
+ case WSRequestCriteria::JOB_COMPETENCIES:
+ case WSRequestCriteria::JOB_RESUME:
+ case WSRequestCriteria::PROFESSIONAL_PROJECT:
+ $subcond = new PFC_Or();
+ foreach ($value as $val) {
+ $subcond->addChild(
+ new UFC_Job_Description($value, UserFilter::JOB_USERDEFINED));
+ }
+ $cond->addChild($subcond);
+ break;
+ case WSRequestCriteria::NOT_UID:
+ $cond->addChild(
+ new PFC_Not(
+ new UFC_PartnerSharingID($this->partner->id, $value)));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return $cond;
+ }
+
+ /** Input validation
+ */
+ const ERROR_MISSING_FIELDS = 'missing_fields';
+ const ERROR_MISSING_CRITERIA = 'missing_criteria';
+ const ERROR_MALFORMED_AMOUNT = 'malformed_amount';
+ const ERROR_MALFORMED_ORDER = 'malformed_order';
+
+ public static $ERROR_MESSAGES = array(
+ self::ERROR_MISSING_FIELDS => "The 'fields' field is mandatory.",
+ self::ERROR_MISSING_CRITERIA => "The 'criteria' field is mandatory.",
+ self::ERROR_MALFORMED_AMOUNT => "The 'amount' value is invalid (expected an int)",
+ self::ERROR_MALFORMED_ORDER => "The 'order' value is invalid (expected an array)",
+ );
+
+ /** Static method performing all input validation on the payload.
+ * @param PlDict $payload The payload to validate
+ * @return array Errors discovered when validating input
+ */
+ public static function validatePayload(PlDict $payload)
+ {
+ $errors = array();
+ if (!$payload->has('fields')) {
+ $errors[] = self::ERROR_MISSING_FIELDS;
+ }
+ if (!$payload->has('criteria')) {
+ $errors[] = self::ERROR_MISSING_CRITERIA;
+ }
+
+ if ($payload->has('amount') && $payload->i('amount', -1) < 0) {
+ $errors[] = self::ERROR_MALFORMED_AMOUNT;
+ }
+
+ if (!is_array($payload->v('order', array()))) {
+ $errors[] = self::ERROR_MALFORMED_ORDER;
+ }
+
+ return $errors;
+ }
+}
+
+// {{{ WSRequestEntry
+/** Performs field retrieval for a profile.
+ */
+class WSRequestEntry
+{
+ private $profile = null;
+ private $partner = null;
+ private $settings = null;
+
+ public function __construct($partner, $profile)
+ {
+ $this->partner = $partner;
+ $this->profile = $profile;
+ $this->settings = $this->profile->getPartnerSettings($this->partner->id);
+ }
+
+ public function isVisible($level)
+ {
+ return $this->settings->sharing_visibility->isVisible($level);
+ }
+
+ public function getFields($fields)
+ {
+ $data = array();
+ foreach ($fields as $field)
+ {
+ $val = $this->getFieldValue($field);
+ if ($val !== null) {
+ $data[$field] = $val;
+ }
+ }
+ $data['uid'] = $this->settings->exposed_uid;
+ return $data;
+ }
+
+ protected function getFieldValue($field)
+ {
+ // Shortcut
+ $p = $this->profile;
+
+ switch ($field) {
+ case WSRequestFields::UID:
+ // UID is always included
+ return;
+ case WSRequestFields::BIRTHDATE:
+ case WSRequestFields::FAMILY_POSITION:
+ case WSRequestFields::HONORARY_TITLES:
+ case WSRequestFields::LANGS:
+ case WSRequestFields::JOB_COMPETENCIES:
+ case WSRequestFields::RESUME:
+ case WSRequestFields::PROFESSIONAL_PROJECT:
+ case WSRequestFields::HOBBIES:
+ // Ignored fields
+ return;
+
+ // Public fields
+ case WSRequestFields::FIRSTNAME:
+ return $p->firstName();
+ case WSRequestFields::LASTNAME:
+ return $p->lastName();
+ case WSRequestFields::GENDER:
+ if ($p->isFemale()) {
+ return WSRequestFields::GENDER_WOMAN;
+ } else {
+ return WSRequestFields::GENDER_MAN;
+ }
+ case WSRequestFields::SCHOOL:
+ return WSRequestCriteria::SCHOOL_X;
+ case WSRequestFields::DIPLOMA:
+ $edu = $p->getEducations(Profile::EDUCATION_MAIN);
+ if (count($edu)) {
+ return WSRequestFields::profileDegreeToWSDiploma(
+ array_pop($edu)->degree);
+ } else {
+ return null;
+ }
+ case WSRequestFields::DIPLOMA_FIELD:
+ $edu = $p->getEducations(Profile::EDUCATION_MAIN);
+ if (count($edu)) {
+ return array_pop($edu)->field;
+ } else {
+ return null;
+ }
+ case WSRequestFields::PROMOTION:
+ return $p->yearpromo();
+ case WSRequestFields::ALT_DIPLOMAS:
+ $diplomas = array();
+ foreach ($p->getExtraEducations() as $edu) {
+ $diplomas[] = WSRequestFields::profileDegreeToWSDiploma(
+ $edu->degree);
+ }
+ return $diplomas;
+
+ // Other generic profile fields
+ case WSRequestFields::EMAIL:
+ if ($this->settings->sharing_visibility->isVisible(Visibility::EXPORT_PRIVATE)) {
+ // If sharing "all" data, share best email.
+ return $p->displayEmail();
+ } elseif ($this->settings->sharing_visibility->isVisible(Visibility::EXPORT_AX)) {
+ // If sharing "AX" level, share "AX" email.
+ return $p->email_directory;
+ } else {
+ // Otherwise, don't share.
+ return null;
+ }
+ case WSRequestFields::MOBILE_PHONE:
+ $phones = $p->getPhones(Profile::PHONE_TYPE_MOBILE | Profile::PHONE_LINK_PROFILE);
+ if (count($phones)) {
+ $phone = array_pop($phones);
+ if ($this->isVisible($phone->pub)) {
+ return $phone->display;
+ }
+ }
+ return null;
+ case WSRequestFields::PIC_SMALL:
+ case WSRequestFields::PIC_MEDIUM:
+ case WSRequestFields::PIC_LARGE:
+ if ($this->isVisible($p->photo_pub)) {
+ $token = sha1(uniqid(rand(), true));
+ XDB::execute('DELETE FROM profile_photo_tokens
+ WHERE pid = {?}', $p->pid);
+ XDB::execute('INSERT INTO profile_photo_tokens
+ SET pid = {?}, token = {?},
+ expires = ADDTIME(NOW(), \'0:05:00\')',
+ $p->pid, $token);
+ $size_mappings = array(
+ WSRequestFields::PIC_SMALL => 'small',
+ WSRequestFields::PIC_MEDIUM => 'medium',
+ WSRequestFields::PIC_LARGE => 'large',
+ );
+ $size = $size_mappings[$field];
+ return pl_url("api/1/sharing/picture/$size/$token");
+ } else {
+ return null;
+ }
+
+ // Address related
+ case WSRequestFields::CURRENT_CITY:
+ $address = $p->getMainAddress();
+ if ($address != null && $this->isVisible($address->pub)) {
+ return $address->locality;
+ } else {
+ return null;
+ }
+ case WSRequestFields::CURRENT_COUNTRY:
+ $address = $p->getMainAddress();
+ if ($address != null && $this->isVisible($address->pub)) {
+ return $address->country;
+ } else {
+ return null;
+ }
+ case WSRequestFields::ADDRESS:
+ $address = $p->getMainAddress();
+ if ($address != null && $this->isVisible($address->pub)) {
+ return $this->addressToResponse($address);
+ } else {
+ return null;
+ }
+
+ // Job related
+ case WSRequestFields::CURRENT_COMPANY:
+ $job = $p->getMainJob();
+ if ($job != null && $this->isVisible($job->pub)) {
+ return $job->company->name;
+ } else {
+ return null;
+ }
+ case WSRequestFields::JOB:
+ $jobs = $p->getJobs(Profile::JOBS_ALL);
+ $res = array();
+ foreach ($jobs as $job) {
+ if ($this->isVisible($job->pub)) {
+ $res[] = $this->jobToResponse($job);
+ }
+ }
+ return $res;
+ case WSRequestFields::MINI_RESUME:
+ if ($this->isVisible(Visibility::EXPORT_PRIVATE)) {
+ return $p->cv;
+ } else {
+ return null;
+ }
+
+ // Community
+ case WSRequestFields::GROUPS:
+ $groups = array();
+ if ($this->isVisible(Visibility::EXPORT_PRIVATE)) {
+ foreach ($p->owner()->groups(true, true) as $group) {
+ $groups[] = array('name' => $group['nom']);
+ }
+ }
+ return $groups;
+ case WSRequestFields::FRIENDS:
+ $friends = array();
+ if ($this->isVisible(Visibility::EXPORT_PRIVATE)) {
+ $contacts = $p->owner()->iterContacts();
+ if ($contacts == null) {
+ return $friends;
+ }
+
+ while ($contact = $contacts->next()) {
+ $cps = $contact->getPartnerSettings($this->partner->id);
+ if ($cps->sharing_visibility->isVisible(Visibility::EXPORT_PRIVATE)) {
+ $friends[] = $cps->exposed_uid;
+ }
+ }
+ }
+ return $friends;
+ case WSRequestFields::NETWORKING:
+ $networks = array();
+ if ($this->isVisible(Visibility::EXPORT_PRIVATE)) {
+ foreach ($p->getNetworking(Profile::NETWORKING_ALL) as $nw) {
+ $networks[] = array(
+ 'network' => $nw['name'],
+ 'login' => $nw['address'],
+ );
+ }
+ }
+ return $networks;
+
+ default:
+ return null;
+ }
+ }
+
+ protected function jobToResponse($job)
+ {
+ $data = array(
+ 'company' => $job->company->name,
+ 'title' => $job->description,
+ 'sector' => array_pop($job->terms),
+ 'entry' => null,
+ 'left' => null,
+ );
+ foreach($job->phones() as $phone) {
+ if ($this->isVisible($phone->pub)) {
+ $data['phone'] = $phone->display;
+ break;
+ }
+ }
+ if ($job->address && $this->isVisible($job->address->pub)) {
+ $data['address'] = $this->addressToResponse($job->address);
+ }
+ return $data;
+ }
+
+ protected function addressToResponse($address)
+ {
+ $data = array(
+ 'street' => $address->postalText,
+ 'zipcode' => $address->postalCode,
+ 'city' => $address->locality,
+ 'country' => $address->country,
+ 'latitude' => $address->latitude,
+ 'longitude' => $address->longitude,
+ );
+ return $data;
+ }
+}
+// }}}
+// {{{ WSRequestCriteria
+/** Holds all enums and related mappings for criterias.
+ */
+class WSRequestCriteria
+{
+ const FIRSTNAME = 'firstname';
+ const LASTNAME = 'lastname';
+ const SCHOOL = 'school';
+ const DIPLOMA = 'diploma';
+ const DIPLOMA_FIELD = 'diploma_field';
+ const PROMOTION = 'promotion';
+ const HOBBIES = 'hobbies';
+ const ZIPCODE = 'zipcode';
+ const CITY = 'city';
+ const COUNTRY = 'country';
+ const JOB_CURRENT_SECTOR = 'job_current_sector';
+ const JOB_CURRENT_TITLE = 'job_current_title';
+ const JOB_CURRENT_COMPANY = 'job_current_company';
+ const JOB_CURRENT_CITY = 'job_current_city';
+ const JOB_CURRENT_COUNTRY = 'job_current_country';
+ const JOB_ANY_SECTOR = 'job_any_sector';
+ const JOB_ANY_COMPANY = 'job_any_company';
+ const JOB_ANY_COUNTRY = 'job_any_country';
+ const JOB_RESUME = 'job_resume';
+ const JOB_COMPETENCIES = 'job_competencies';
+ const PROFESSIONAL_PROJECT = 'professional_project';
+ const ALT_DIPLOMA = 'alt_diploma';
+ const NOT_UID = 'not_uid';
+
+ public static $choices_simple = array(
+ self::FIRSTNAME,
+ self::LASTNAME,
+ self::PROMOTION,
+ self::ALT_DIPLOMA,
+ self::DIPLOMA_FIELD,
+ self::CITY,
+ self::ZIPCODE,
+ self::COUNTRY,
+ self::JOB_ANY_COUNTRY,
+ self::JOB_CURRENT_CITY,
+ self::JOB_CURRENT_COUNTRY,
+ self::JOB_ANY_COMPANY,
+ self::JOB_ANY_SECTOR,
+ self::JOB_CURRENT_COMPANY,
+ self::JOB_CURRENT_SECTOR,
+ self::JOB_CURRENT_TITLE,
+ );
+
+ const SCHOOL_AGRO = 'agro';
+ const SCHOOL_ENSAE = 'ensae';
+ const SCHOOL_ENSCP = 'enscp';
+ const SCHOOL_ENST = 'enst';
+ const SCHOOL_ENSTA = 'ensta';
+ const SCHOOL_ESPCI = 'espci';
+ const SCHOOL_GADZ = 'gadz';
+ const SCHOOL_HEC = 'hec';
+ const SCHOOL_MINES = 'ensmp';
+ const SCHOOL_PONTS = 'enpc';
+ const SCHOOL_SUPELEC = 'supelec';
+ const SCHOOL_SUPOP = 'supop';
+ const SCHOOL_X = 'X';
+
+ const DIPLOMA_ING = 'ING';
+ const DIPLOMA_MASTER = 'MASTER';
+ const DIPLOMA_PHD = 'PHD';
+
+ public static $choices_enum = array(
+ self::SCHOOL => array(
+ self::SCHOOL_AGRO => false,
+ self::SCHOOL_ENSAE => false,
+ self::SCHOOL_ENSCP => false,
+ self::SCHOOL_ENST => false,
+ self::SCHOOL_ENSTA => false,
+ self::SCHOOL_ESPCI => false,
+ self::SCHOOL_GADZ => false,
+ self::SCHOOL_HEC => false,
+ self::SCHOOL_MINES => false,
+ self::SCHOOL_PONTS => false,
+ self::SCHOOL_SUPELEC => false,
+ self::SCHOOL_SUPOP => false,
+ self::SCHOOL_X => true,
+ ),
+ self::DIPLOMA => array(
+ self::DIPLOMA_ING => UserFilter::GRADE_ING,
+ self::DIPLOMA_MASTER => UserFilter::GRADE_MST,
+ self::DIPLOMA_PHD => UserFilter::GRADE_PHD,
+ ),
+ );
+
+ public static $choices_list = array(
+ self::HOBBIES,
+ self::JOB_COMPETENCIES,
+ self::JOB_RESUME,
+ self::NOT_UID,
+ self::PROFESSIONAL_PROJECT,
+ );
+}
+
+// }}}
+// {{{ WSRequestFields
+/** Holds all enums for fields.
+ */
+class WSRequestFields
+{
+ const UID = 'uid';
+ const FIRSTNAME = 'firstname';
+ const LASTNAME = 'lastname';
+ const BIRTHDATE = 'birthdate';
+ const GENDER = 'gender';
+ const FAMILY_POSITION = 'family_position';
+ const SCHOOL = 'school';
+ const DIPLOMA = 'diploma';
+ const DIPLOMA_FIELD = 'diploma_field';
+ const PROMOTION = 'promotion';
+ const ALT_DIPLOMAS = 'alt_diplomas';
+ const CURRENT_COMPANY = 'current_company';
+ const CURRENT_CITY = 'current_city';
+ const CURRENT_COUNTRY = 'current_country';
+ const MOBILE_PHONE = 'mobile_phone';
+ const HONORARY_TITLES = 'honorary_titles';
+ const EMAIL = 'email';
+ const PIC_SMALL = 'pic_small';
+ const PIC_MEDIUM = 'pic_medium';
+ const PIC_LARGE = 'pic_large';
+ const ADDRESS = 'address';
+ const JOB = 'job';
+ const GROUPS = 'groups';
+ const LANGS = 'langs';
+ const JOB_COMPETENCIES = 'job_competencies';
+ const MINI_RESUME = 'mini_resume';
+ const RESUME = 'resume';
+ const PROFESSIONAL_PROJECT = 'professional_project';
+ const HOBBIES = 'hobbies';
+ const FRIENDS = 'friends';
+ const NETWORKING = 'networking';
+
+ const GENDER_MAN = 'man';
+ const GENDER_WOMAN = 'woman';
+
+ const DIPLOMA_ING = 'engineer';
+ const DIPLOMA_MASTER = 'master';
+ const DIPLOMA_PHD = 'phd';
+
+ public static $choices = array(
+ self::UID,
+ self::FIRSTNAME,
+ self::LASTNAME,
+ self::BIRTHDATE,
+ self::GENDER,
+ self::FAMILY_POSITION,
+ self::SCHOOL,
+ self::DIPLOMA,
+ self::DIPLOMA_FIELD,
+ self::PROMOTION,
+ self::ALT_DIPLOMAS,
+ self::CURRENT_COMPANY,
+ self::CURRENT_CITY,
+ self::CURRENT_COUNTRY,
+ self::MOBILE_PHONE,
+ self::HONORARY_TITLES,
+ self::EMAIL,
+ self::PIC_SMALL,
+ self::PIC_MEDIUM,
+ self::PIC_LARGE,
+ self::ADDRESS,
+ self::JOB,
+ self::GROUPS,
+ self::LANGS,
+ self::JOB_COMPETENCIES,
+ self::MINI_RESUME,
+ self::RESUME,
+ self::PROFESSIONAL_PROJECT,
+ self::HOBBIES,
+ self::FRIENDS,
+ self::NETWORKING,
+ );
+
+ public static function profileDegreeToWSDiploma($degree)
+ {
+ switch ($degree) {
+ case Profile::DEGREE_X:
+ return self::DIPLOMA_ING;
+ case Profile::DEGREE_M:
+ return self::DIPLOMA_MASTER;
+ case Profile::DEGREE_D:
+ return self::DIPLOMA_PHD;
+ default:
+ return null;
+ }
+ }
+
+}
+// }}}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
function handlers()
{
return array(
- 'stats' => $this->make_hook('stats', AUTH_COOKIE),
- 'stats/evolution' => $this->make_hook('evolution', AUTH_COOKIE),
- 'stats/graph' => $this->make_hook('graph', AUTH_COOKIE),
- 'stats/graph/evolution' => $this->make_hook('graph_evo', AUTH_COOKIE),
- 'stats/promos' => $this->make_hook('promos', AUTH_COOKIE),
+ 'stats' => $this->make_hook('stats', AUTH_COOKIE, 'user'),
+ 'stats/evolution' => $this->make_hook('evolution', AUTH_COOKIE, 'user'),
+ 'stats/graph' => $this->make_hook('graph', AUTH_COOKIE, 'user'),
+ 'stats/graph/evolution' => $this->make_hook('graph_evo', AUTH_COOKIE, 'user'),
+ 'stats/promos' => $this->make_hook('promos', AUTH_COOKIE, 'user'),
'stats/coupures' => $this->make_hook('coupures', AUTH_PUBLIC),
);
'survey' => $this->make_hook('index', AUTH_PUBLIC),
'survey/vote' => $this->make_hook('vote', AUTH_PUBLIC),
'survey/result' => $this->make_hook('result', AUTH_PUBLIC),
- 'survey/edit' => $this->make_hook('edit', AUTH_COOKIE),
- 'survey/ajax' => $this->make_hook('ajax', AUTH_COOKIE),
- 'survey/admin' => $this->make_hook('admin', AUTH_MDP, 'admin'),
- 'survey/admin/edit' => $this->make_hook('adminEdit', AUTH_MDP, 'admin'),
- 'survey/admin/valid' => $this->make_hook('adminValidate', AUTH_MDP, 'admin'),
- 'survey/admin/del' => $this->make_hook('adminDelete', AUTH_MDP, 'admin'),
+ 'survey/edit' => $this->make_hook('edit', AUTH_COOKIE, 'user'),
+ 'survey/ajax' => $this->make_hook('ajax', AUTH_COOKIE, 'user'),
+ 'survey/admin' => $this->make_hook('admin', AUTH_MDP, 'admin'),
+ 'survey/admin/edit' => $this->make_hook('adminEdit', AUTH_MDP, 'admin'),
+ 'survey/admin/valid' => $this->make_hook('adminValidate', AUTH_MDP, 'admin'),
+ 'survey/admin/del' => $this->make_hook('adminDelete', AUTH_MDP, 'admin'),
);
}
// }}}
default:
return null;
}
+ if (!S::user()->checkPerms(PERMS_USER)) {
+ $where .= XDB::format(' AND mode = {?}', self::MODE_ALL);
+ }
$sql = 'SELECT id, title, end, mode
FROM surveys
WHERE '.$where.'
'groups' => $this->make_hook('groups', AUTH_PUBLIC),
'groupes.php' => $this->make_hook('groups2', AUTH_PUBLIC),
'plan' => $this->make_hook('plan', AUTH_PUBLIC),
- 'photo' => $this->make_hook('photo', AUTH_MDP),
- 'autologin' => $this->make_hook('autologin', AUTH_MDP),
- 'login/ext' => $this->make_hook('login_ext', AUTH_PUBLIC),
+ 'photo' => $this->make_hook('photo', AUTH_MDP, 'groups'),
+ 'autologin' => $this->make_hook('autologin', AUTH_MDP, 'groups'),
'register/ext' => $this->make_hook('register_ext', AUTH_PUBLIC),
- 'recovery/ext' => $this->make_hook('recovery_ext', AUTH_PUBLIC),
- 'tmpPWD/ext' => $this->make_hook('tmpPWD_ext', AUTH_PUBLIC),
- 'edit' => $this->make_hook('edit', AUTH_MDP, 'user'),
- 'password' => $this->make_hook('password', AUTH_MDP, 'user'),
-
+ 'edit' => $this->make_hook('edit', AUTH_MDP, 'groups'),
'Xnet' => $this->make_wiki_hook(),
);
}
exit;
}
- function handler_login_ext($page)
- {
- if (!S::logged()) {
- $page->changeTpl('xnet/login.tpl');
- } else {
- pl_redirect('');
- }
- }
-
- function handler_register_ext($page, $hash = null)
- {
- XDB::execute('DELETE FROM register_pending_xnet
- WHERE DATE_SUB(NOW(), INTERVAL 1 MONTH) > date');
- $res = XDB::fetchOneAssoc('SELECT uid, hruid
- FROM register_pending_xnet
- WHERE hash = {?}',
- $hash);
-
- if (is_null($hash) || is_null($res)) {
- $page->trigErrorRedirect('Cette adresse n\'existe pas ou n\'existe plus sur le serveur.', '');
- }
-
- if (Post::has('pwhash') && Post::t('pwhash')) {
- XDB::query('UPDATE accounts
- SET password = {?}, state = \'active\', registration_date = NOW()
- WHERE uid = {?} AND state = \'pending\' AND type = \'xnet\'',
- Post::t('pwhash'), $res['uid']);
- XDB::query('DELETE FROM register_pending_xnet
- WHERE uid = {?}',
- $res['uid']);
-
- S::logger($res['uid'])->log('passwd', '');
-
- // Try to start a session (so the user don't have to log in); we will use
- // the password available in Post:: to authenticate the user.
- Post::kill('wait');
- Platal::session()->startAvailableAuth();
-
- $page->changeTpl('xnet/register.success.tpl');
- $page->assign('email', $res['email']);
- } else {
- $page->changeTpl('platal/password.tpl');
- $page->assign('xnet', true);
- $page->assign('hruid', $res['hruid']);
- $page->assign('do_auth', 1);
- }
- }
-
- function handler_recovery_ext($page)
- {
- $page->changeTpl('xnet/recovery.tpl');
-
- if (!Post::has('login')) {
- return;
- }
-
- $user = User::getSilent(Post::t('login'));
- if (is_null($user)) {
- $page->trigError('Le compte n\'existe pas.');
- return;
- }
- if ($user->state != 'active') {
- $page->trigError('Ton compte n\'est pas activé.');
- return;
- }
-
- $page->assign('ok', true);
-
- $hash = rand_url_id();
- XDB::execute('INSERT INTO account_xnet_lost_passwords (uid, date, hash)
- VALUES ({?}, NOW(), {?})',
- $user->id(), $hash);
-
- $mymail = new PlMailer();
- $mymail->setFrom('"Gestion des mots de passe" <support+password@' . Platal::globals()->mail->domain . '>');
- $mymail->addTo($user);
- $mymail->setSubject("Votre certificat d'authentification");
- $mymail->setTxtBody("Visitez la page suivante qui expire dans six heures :
-http://polytechnique.net/tmpPWD/ext/$hash
-
-Si en cliquant dessus vous n'y arrivez pas, copiez intégralement l'adresse dans la barre de votre navigateur. Si vous n'avez pas utilisé ce lien dans six heures, vous pouvez tout simplement recommencer cette procédure.
-
---
-Polytechnique.org
-\"Le portail des élèves & anciens élèves de l'École polytechnique\"
-
-Email envoyé à " . Post::t('login'));
- $mymail->send();
-
- S::logger($user->id())->log('recovery', $user->bestEmail());
- }
-
- function handler_tmpPWD_ext($page, $hash = null)
- {
- global $globals;
- XDB::execute('DELETE FROM account_xnet_lost_passwords
- WHERE DATE_SUB(NOW(), INTERVAL 380 MINUTE) > date');
-
- $uid = XDB::fetchOneCell('SELECT uid
- FROM account_xnet_lost_passwords
- WHERE hash = {?}',
- $hash);
- if (is_null($uid)) {
- $page->trigErrorRedirect("Cette adresse n'existe pas ou n'existe plus sur le serveur.", '');
- }
-
- $email = XDB::fetchOneCell('SELECT email
- FROM accounts
- WHERE uid = {?}',
- $uid);
-
- if (Post::has('pwhash') && Post::t('pwhash')) {
- $password = Post::t('pwhash');
- XDB::query('UPDATE accounts
- SET password = {?}
- WHERE uid = {?} AND state = \'active\'',
- $password, $uid);
- XDB::query('DELETE FROM account_xnet_lost_passwords
- WHERE hash = {?}',
- $hash);
-
- S::logger($uid)->log('passwd', '');
-
- // Try to start a session (so the user don't have to log in); we will use
- // the password available in Post:: to authenticate the user.
- Post::kill('wait');
- Platal::session()->startAvailableAuth();
-
- $page->changeTpl('xnet/register.success.tpl');
- $page->assign('email', $email);
- } else {
- $page->changeTpl('platal/password.tpl');
- $page->assign('xnet_reset', true);
- $page->assign('email', $email);
- $page->assign('do_auth', 1);
- }
- }
-
-
-
function handler_edit($page)
{
global $globals;
$page->assign('user', $user);
}
- function handler_password ($page)
- {
- if (Post::has('pwhash') && Post::t('pwhash')) {
- S::assert_xsrf_token();
-
- S::set('password', $password = Post::t('pwhash'));
- XDB::execute('UPDATE accounts
- SET password = {?}
- WHERE uid={?}', $password,
- S::i('uid'));
- S::logger()->log('passwd');
- Platal::session()->setAccessCookie(true);
- $page->changeTpl('platal/password.success.tpl');
- $page->run();
- }
-
- $page->changeTpl('platal/password.tpl');
- $page->assign('xnet_reset', true);
- $page->assign('do_auth', 0);
- }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
function handlers()
{
return array(
- '%grp/events' => $this->make_hook('events', AUTH_MDP),
- '%grp/events/sub' => $this->make_hook('sub', AUTH_MDP),
- '%grp/events/csv' => $this->make_hook('csv', AUTH_MDP, 'user', NO_HTTPS),
- '%grp/events/ical' => $this->make_hook('ical', AUTH_MDP, 'user', NO_HTTPS),
+ '%grp/events' => $this->make_hook('events', AUTH_MDP, 'groups'),
+ '%grp/events/sub' => $this->make_hook('sub', AUTH_MDP, 'groups'),
+ '%grp/events/csv' => $this->make_hook('csv', AUTH_MDP, 'groups', NO_HTTPS),
+ '%grp/events/ical' => $this->make_hook('ical', AUTH_MDP, 'groups', NO_HTTPS),
'%grp/events/edit' => $this->make_hook('edit', AUTH_MDP, 'groupadmin'),
'%grp/events/admin' => $this->make_hook('admin', AUTH_MDP, 'groupmember'),
);
'%grp/directory/unact' => $this->make_hook('non_active', AUTH_MDP, 'groupadmin'),
'%grp/trombi' => $this->make_hook('trombi', AUTH_MDP, 'groupannu'),
'%grp/geoloc' => $this->make_hook('geoloc', AUTH_MDP, 'groupannu'),
- '%grp/subscribe' => $this->make_hook('subscribe', AUTH_MDP),
+ '%grp/subscribe' => $this->make_hook('subscribe', AUTH_MDP, 'groups'),
'%grp/subscribe/valid' => $this->make_hook('subscribe_valid', AUTH_MDP, 'groupadmin'),
'%grp/unsubscribe' => $this->make_hook('unsubscribe', AUTH_MDP, 'groupmember'),
- '%grp/change_rights' => $this->make_hook('change_rights', AUTH_MDP),
+ '%grp/change_rights' => $this->make_hook('change_rights', AUTH_MDP, 'groups'),
'%grp/admin/annuaire' => $this->make_hook('admin_annuaire', AUTH_MDP, 'groupadmin'),
'%grp/member' => $this->make_hook('admin_member', AUTH_MDP, 'groupadmin'),
'%grp/member/new' => $this->make_hook('admin_member_new', AUTH_MDP, 'groupadmin'),
- '%grp/member/new/ajax' => $this->make_hook('admin_member_new_ajax', AUTH_MDP, 'user', NO_AUTH),
+ '%grp/member/new/ajax' => $this->make_hook('admin_member_new_ajax', AUTH_MDP, 'groups', NO_AUTH),
'%grp/member/del' => $this->make_hook('admin_member_del', AUTH_MDP, 'groupadmin'),
'%grp/member/suggest' => $this->make_hook('admin_member_suggest', AUTH_MDP, 'groupadmin'),
$append = "\n"
. "-- \n"
. "Ce message a été envoyé suite à la demande d'inscription de\n"
- . S::user()->fullName() . ' (X' . S::v('promo') . ")\n"
+ . S::user()->fullName(true) . "\n"
. "Via le site www.polytechnique.net. Tu peux choisir de valider ou\n"
. "de refuser sa demande d'inscription depuis la page :\n"
. "http://www.polytechnique.net/" . $globals->asso("diminutif") . "/subscribe/" . S::user()->login() . "\n"
function handlers()
{
return array(
- '%grp/lists' => $this->make_hook('lists', AUTH_MDP, 'groupmember'),
- '%grp/lists/create' => $this->make_hook('create', AUTH_MDP, 'groupmember'),
+ '%grp/lists' => $this->make_hook('lists', AUTH_MDP, 'groupmember'),
+ '%grp/lists/create' => $this->make_hook('create', AUTH_MDP, 'groupmember'),
- '%grp/lists/members' => $this->make_hook('members', AUTH_COOKIE),
- '%grp/lists/csv' => $this->make_hook('csv', AUTH_COOKIE),
- '%grp/lists/annu' => $this->make_hook('annu', AUTH_COOKIE),
- '%grp/lists/archives' => $this->make_hook('archives', AUTH_COOKIE),
+ '%grp/lists/members' => $this->make_hook('members', AUTH_COOKIE, 'groups'),
+ '%grp/lists/csv' => $this->make_hook('csv', AUTH_COOKIE, 'groups'),
+ '%grp/lists/annu' => $this->make_hook('annu', AUTH_COOKIE, 'groups'),
+ '%grp/lists/archives' => $this->make_hook('archives', AUTH_COOKIE, 'groups'),
'%grp/lists/archives/rss' => $this->make_hook('rss', AUTH_PUBLIC),
- '%grp/lists/moderate' => $this->make_hook('moderate', AUTH_MDP),
- '%grp/lists/admin' => $this->make_hook('admin', AUTH_MDP),
- '%grp/lists/options' => $this->make_hook('options', AUTH_MDP),
- '%grp/lists/delete' => $this->make_hook('delete', AUTH_MDP),
+ '%grp/lists/moderate' => $this->make_hook('moderate', AUTH_MDP, 'groups'),
+ '%grp/lists/admin' => $this->make_hook('admin', AUTH_MDP, 'groups'),
+ '%grp/lists/options' => $this->make_hook('options', AUTH_MDP, 'groups'),
+ '%grp/lists/delete' => $this->make_hook('delete', AUTH_MDP, 'groups'),
- '%grp/lists/soptions' => $this->make_hook('soptions', AUTH_MDP),
- '%grp/lists/check' => $this->make_hook('check', AUTH_MDP),
- '%grp/lists/sync' => $this->make_hook('sync', AUTH_MDP),
+ '%grp/lists/soptions' => $this->make_hook('soptions', AUTH_MDP, 'groups'),
+ '%grp/lists/check' => $this->make_hook('check', AUTH_MDP, 'groups'),
+ '%grp/lists/sync' => $this->make_hook('sync', AUTH_MDP, 'groups'),
- '%grp/alias/admin' => $this->make_hook('aadmin', AUTH_MDP, 'groupadmin'),
- '%grp/alias/create' => $this->make_hook('acreate', AUTH_MDP, 'groupadmin'),
+ '%grp/alias/admin' => $this->make_hook('aadmin', AUTH_MDP, 'groupadmin'),
+ '%grp/alias/create' => $this->make_hook('acreate', AUTH_MDP, 'groupadmin'),
/* hack: lists uses that */
'profile' => $this->make_hook('profile', AUTH_PUBLIC),
function handlers()
{
return array(
- '%grp/nl' => $this->make_hook('nl', AUTH_MDP),
- '%grp/nl/show' => $this->make_hook('nl_show', AUTH_MDP),
- '%grp/nl/search' => $this->make_hook('nl_search', AUTH_MDP),
+ '%grp/nl' => $this->make_hook('nl', AUTH_MDP, 'groups'),
+ '%grp/nl/show' => $this->make_hook('nl_show', AUTH_MDP, 'groups'),
+ '%grp/nl/search' => $this->make_hook('nl_search', AUTH_MDP, 'groups'),
'%grp/admin/nl' => $this->make_hook('admin_nl', AUTH_MDP, 'groupadmin'),
'%grp/admin/nl/sync' => $this->make_hook('admin_nl_sync', AUTH_MDP, 'groupadmin'),
'%grp/admin/nl/enable' => $this->make_hook('admin_nl_enable', AUTH_MDP, 'groupadmin'),
$with_link = $params->b('link', true);
$with_dir = $params->b('directory', true);
$with_groupperms = $params->b('groupperms', true);
+ $raw = $params->b('raw', true);
$user = $params->v('user');
if (is_int($user) || ctype_digit($user)) {
$user = User::getWithUID($user);
} else {
$name = pl_entities($user->fullName());
}
- if ($with_sex && $user->isFemale()) {
- $name = '•' . $name;
- }
if ($with_promo) {
$promo = $user->category();
if ($promo) {
$name .= ' (' . pl_entities($promo) . ')';
}
}
+ if ($raw) {
+ return $name;
+ }
+
+ if ($with_sex && $user->isFemale()) {
+ $name = '•' . $name;
+ }
if ($with_link) {
$profile = ($user instanceof Profile) ? $user : $user->profile();
if ($profile) {
return '';
}
- $domain = Cookie::v('domain', 'login');
- if ($domain == 'hruid') {
- return XDB::fetchOneCell('SELECT hruid
- FROM accounts
- WHERE uid = {?}',
- $id);
- } elseif ($domain == 'alias') {
- return XDB::fetchOneCell('SELECT email
- FROM email_source_account
- WHERE uid = {?} AND type = \'alias_aux\'',
- $id);
- } else {
- return XDB::fetchOneCell('SELECT email
- FROM email_source_account
- WHERE uid = {?} AND type != \'alias_aux\'
- ORDER BY NOT FIND_IN_SET(\'bestalias\', flags), CHAR_LENGTH(email)',
- $id);
- }
-
- return '';
+ $user = User::getSilentWithUID($id);
+ return $user->bestEmail();
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
</h1>
<p>
Bonjour,<br />
- la page que vous avez demandée
- (<strong>{if $referer}{$smarty.server.HTTP_REFERER}{else}{$globals->baseurl}/{$platal->pl_self()}{/if}</strong>)
+ {if t($group)}
+ le site du groupe {$group}
+ {else}
+ la page que vous avez demandée
+ {/if}
+ (<strong>{if t($referer)}{$smarty.server.HTTP_REFERER|truncate:120:"...":false}{else}{$globals->baseurl}/{$platal->pl_self()}{/if}</strong>)
nécessite une authentification.
</p>
{else}
</tr>
<tr style="white-space: nowrap">
<td class="titre">
- Identifiant :
+ Identifiant ou email :
</td>
<td>
- <input type="text" name="username" size="20" maxlength="50" value="{insert name="getUserName"}" />
- <select name="domain">
- <option value="login">@alumni. {#globals.mail.domain#} / {#globals.mail.domain2#}</option>
- <option value="alias" {if t($smarty.cookies.ORGdomain) && $smarty.cookies.ORGdomain eq "alias"}selected="selected"{/if}>
- @ {#globals.mail.alias_dom#} / {#globals.mail.alias_dom2#}
- </option>
- <option value="hruid" {if t($smarty.cookies.ORGdomain) && $smarty.cookies.ORGdomain eq "ax"}selected="selected"{/if}>
- Identifiant
- </option>
- </select>
+ <input type="text" name="username" size="40" maxlength="100" value="{insert name="getUserName"}" />
</td>
</tr>
<tr>
</tr>
<tr>
<td colspan="2">
- <a href="recovery" style="float: left">Mot de passe perdu ?</a>
+ <span style="float: left">
+ Mot de passe perdu :
+ <a href="recovery">Étudiants et diplômés de l'X</a> |
+ <a href="recovery/ext">Extérieurs</a>
+ </span>
+
<input type="submit" name="submitbtn" value="Me connecter" style="float: right" />
</td>
</tr>
<input type="hidden" name="xorpass" value="" />
<input type="hidden" name="username" value="" />
<input type="hidden" name="remember" value="" />
- <input type="hidden" name="domain" value="" />
</div>
</form>
{**************************************************************************}
<tr class="pair">
- <td class="titre">Adresse fournie</td>
+ <td class="titre">Adresse saisie par l'utilisateur</td>
<td>{$valid->given_text}</td>
</tr>
{* *}
{**************************************************************************}
+<p>L'adresse saisie ci-dessous sert uniquement pour la géolocalisation ;
+utiliser le bouton <em>Éditer</em> pour visualiser sur la carte la nouvelle position de l'adresse.</p>
+<p>La case <em>Utiliser la version modifiée</em> va remplacer l'adresse saisie par l'utilisateur par l'adresse modifiée ci-dessous.
+À n'utiliser qu'en cas d'adresse manifestement invalide, ou pour corriger une faute d'orthographe.</p>
+
{include file="geoloc/form.address.tpl" prefname="valid" prefid=0 address=$valid->address validation=1}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
<td>raison (pour les refus) :
<textarea cols='50' rows='10' name='reason' id='raison'>
--
-{profile user=$smarty.session.user promo=true directory=false link=false sex=false}
+{profile user=$smarty.session.user promo=true directory=false link=false sex=false raw=true}
</textarea>
</td>
</tr>
<tr class="{cycle values="pair,impair"}">
<td class="titre">{$nl->id}</td>
<td>{$nl->group}</td>
- <td>{$nl->name}</td>
+ <td><a href="http://www.polytechnique.net/{$nl->group}/admin/nl">{$nl->name}</a></td>
<td>{if $nl->hasCustomCss()}Oui{else}Non{/if}</td>
<td>{$nl->criteria->flags()}</td>
</tr>
</td>
<td>
{if $issue->isEditable()}
- Le {valid_date name="send_before_date" value=$issue->getSendBeforeDate() from=3 to=15} vers {html_select_time prefix="send_before_time_" time=$issue->getSendBeforeTime() display_hours=true display_minutes=false display_seconds=false display_meridian=false use_24_hours=true} heures
+ Le {valid_date name="send_before_date" value=$issue->getSendBeforeDate() from=1 to=15} vers {html_select_time prefix="send_before_time_" time=$issue->getSendBeforeTime() display_hours=true display_minutes=false display_seconds=false display_meridian=false use_24_hours=true} heures
{else}
Le {$issue->send_before|date_format:"%d/%m/%Y vers %Hh"}
{/if}
{if $is_mail}
archives : <https://www.polytechnique.org/ax>
-ne plus recevoir : <https://www.polytechnique.org/ax/out/{if $hash}{$hash}{else}nohash{/if}/issue/{$issue->id}>
+ne plus recevoir : <https://www.polytechnique.org/ax/out/{if $hash}{$hash}{else}nohash{/if}/{$issue->id}>
{else}
archives : <https://www.polytechnique.org/ax>
-ne plus recevoir : <https://www.polytechnique.org/ax/out/{if $hash}{$hash}{else}nohash{/if}/issue/{$issue->id}>
+ne plus recevoir : <https://www.polytechnique.org/ax/out/{if $hash}{$hash}{else}nohash{/if}/{$issue->id}>
{/if}
{if !$is_mail}
</tr>
<tr>
<td>
- <input type="hidden" name="username" value="{$email}" />
+ <input type="hidden" name="username" value="{$hruid}" />
<input type="hidden" name="password" value="" />
<input type="hidden" name="domain" value="email" />
</td>
--- /dev/null
+{**************************************************************************}
+{* *}
+{* Copyright (C) 2003-2011 Polytechnique.org *}
+{* http://opensource.polytechnique.org/ *}
+{* *}
+{* This program 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. *}
+{* *}
+{* 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 Software *}
+{* Foundation, Inc., *}
+{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *}
+{* *}
+{**************************************************************************}
+
+{config_load file="mails.conf" section="password_recovery_xnet"}
+{if $mail_part eq 'head'}
+{subject text="Votre certificat d'authentification"}
+{from full=#from#}
+{elseif $mail_part eq 'text'}
+
+Visitez la page suivante qui expire dans six heures :
+{$globals->baseurl}/tmpPWD/{$hash}
+
+Si en cliquant dessus vous n'y arrivez pas, copiez intégralement l'adresse dans la barre de votre navigateur. Si vous n'avez pas utilisé ce lien dans six heures, vous pouvez tout simplement recommencer cette procédure.
+
+{include file="include/signature.mail.tpl"}
+
+Email envoyé à {$email}
+{/if}
<form action="prefs" method="post" id="form">
{xsrf_token_field}
<dl>
+ {if hasPerm('user')}
<dt>Apparence du site</dt>
<dd>
Tu peux changer l'apparence du site en choisissant une autre skin.<br />
<a href="prefs/skin">Changer de skin</a>
</dd>
+ {/if}
<dt>Format des emails envoyés par le site</dt>
<dd>
Lorsque le site t'envoie des emails (lettre mensuelle, carnet, ...) ceux-ci peuvent
</td>
<td><input type="text" {if $errors.deathdate}class="error"{/if} name="deathdate" value="{$deathdate}" /></td>
</tr>
+ <tr>
+ <td>
+ <span class="titre">Date de naissance de référence</span>
+ </td>
+ <td>
+ {if $birthdate_ref eq 0}
+ <input type="text" {if $errors.birthdate_ref}class="error"{/if} name="birthdate_ref" value="{$birthdate_ref}" />
+ {else}
+ {$birthdate_ref}
+ {/if}
+ </td>
+ </tr>
{/if}
<tr>
<td>
//]]></script>
{/literal}
-
<div id="fiche">
<div id="photo" class="part">
{assign var=photo value=$profile->getPhoto(false)}
{if $photo}<img alt="Photo de {$profile->fullName()}" src="photo/{$profile->hrid()}{if $with_pending_pic}/req{/if}" width="{$photo->width()}"/>{/if}
- {if $logged && $view eq 'private' && ( $profile->section|smarty:nodefaults || $profile->getBinets()|smarty:nodefaults || ($owner && $owner->groups(true,true)|smarty:nodefaults))}
+ {if $logged && $view->isVisible(#Visibility::EXPORT_AX#) && ( $profile->section|smarty:nodefaults || $profile->getBinets()|smarty:nodefaults || ($owner && $owner->groups(true,true)|smarty:nodefaults))}
<h2>À l'X…</h2>
{if $profile->section}<div><em class="intitule">Section : </em><span>{$profile->section}</span></div>{/if}
{if $binets|@count}<div><em class="intitule">Binet{if count($binets) > 1}s{/if} : </em>
<span>{', '|implode:$profile->getBinetsNames()}</span></div>{/if}
- {if $owner && $view eq 'private'}
+ {if $owner && $view->isVisible(#Visibility::EXPORT_AX#)}
{assign var=groups value=$owner->groups(true,true)}
{if $groups|@count}<div><em class="intitule">Groupe{if count($groups) > 1}s{/if} et institution{if count($groups) > 1}s{/if} X : </em>
<span><br/>
{/if}
- {* 458752 stands for 0x70000 = Profile::NETWORKING_ALL *}
- {assign var=networking value=$profile->getNetworking(458752)}
+ {assign var=networking value=$profile->getNetworking(#Profile::NETWORKING_ALL#)}
{if count($networking) > 0}
<h2>Sur le web...</h2>
{foreach from=$networking item=network}
<div id="fiche_identite" class="part">
<div class="civilite">
{if $profile->isFemale()}•{/if}
- {if $view eq 'private'}{$profile->private_name}{else}{$profile->public_name}{/if}
+ {if $view->isVisible(#Visibility::EXPORT_PRIVATE#)}{$profile->private_name}{else}{$profile->public_name}{/if}
{if $logged}
{if !$profile->isDead()}<a href="vcard/{$owner->login()}.vcf">{*
{/if}
</div>
- {if $logged && $view eq 'private' && $owner && $owner->state eq 'active'}
+ {if $logged && $view->isVisible(#Visibility::EXPORT_AX#) && $owner && $owner->state eq 'active'}
<div class='maj'>
Fiche mise à jour<br />
le {$profile->last_change|date_format}
{* 121634816 is Profile::PHONE_LINK_PROFILE | Profile::PHONE_TYPE_ANY = 0x7400000 *}
{assign var=phones value=$profile->getPhones(121634816)}
- {if ($logged && $view eq 'private') || count($phones) > 0}
+ {if ($logged && $view->isVisible(#Visibility::EXPORT_AX#)) || count($phones) > 0}
<div class="contact">
- {if $logged && $view eq 'private'}
+ {if $logged && $view->isVisible(#Visibility::EXPORT_AX#)}
<div class='email'>
{if $profile->isDead()}
Décédé{if $profile->isFemale()}e{/if} le {$profile->deathdate|date_format}
Cette personne n'est pas inscrite à Polytechnique.org,<br />
<a href="marketing/public/{$owner->login()}" class="popup">clique ici si tu connais son adresse email !</a>
{else}
- {if $virtualalias}
+ {if $virtualalias && $view->isVisible(#Visibility::EXPORT_PRIVATE#)}
<a href="mailto:{$virtualalias}">{$virtualalias}</a><br />
{/if}
<a href="mailto:{$owner->bestEmail()}">{$owner->bestEmail()}</a>
{$profile->promo('details')}
- {if $logged && $view eq 'private' && $profile->mentor_expertise}
+ {if $logged && $view->isVisible(#Visibility::EXPORT_AX#) && $profile->mentor_expertise}
[<a href="referent/{$profile->hrid()}" class='popup2'>Ma fiche référent</a>]
{/if}
</div>
{/if}
- {if $view eq 'public'}
+ {if $view->level() eq #Visibility::VIEW_PUBLIC#}
<div class="part">
<small>
Cette fiche est publique et visible par tout internaute,<br />
vous pouvez aussi voir <a href="profile/private/{$profile->hrid()}?display=light">celle réservée aux X</a>.
</small>
</div>
- {elseif $view eq 'ax'}
+ {elseif $view->level() eq #Visibility::VIEW_AX#}
<div class="part">
<small>
Cette fiche est privée et ne recense que les informations transmises à l'AX.
{if $smarty.session.user->googleapps}
<div class="menu_item"><a href="http://gmail.polytechnique.org/">Emails Google Apps</a></div>
{/if}
+{if hasPerm('user')}
<div class="menu_item"><a href="lists">Listes de diffusion</a></div>
+{/if}
{if hasPerm('payment')}
<div class="menu_item"><a href="payment">Télépaiements</a></div>
{/if}
--- /dev/null
+{**************************************************************************}
+{* *}
+{* Copyright (C) 2003-2011 Polytechnique.org *}
+{* http://opensource.polytechnique.org/ *}
+{* *}
+{* This program 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. *}
+{* *}
+{* 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 Software *}
+{* Foundation, Inc., *}
+{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *}
+{* *}
+{**************************************************************************}
+
+{include file=skin/common.doctype.tpl}
+ <link rel="stylesheet" type="text/css" href="css/default.css" media="all" />
+ {include file=skin/common.header.tpl}
+ </head>
+ <body>
+ {include core=plpage.devel.tpl}
+ {if !$simple}
+ {include file=skin/common.bandeau.tpl}
+ {/if}
+ {if t($smarty.session.suid)}
+ <div id="suid">
+ <a href="exit">
+ Quitter le SU sur {$smarty.session.hruid} ({$smarty.session.perms->flags()})
+ </a>
+ </div>
+ {/if}
+
+ {if $simple}
+ <div id="content">
+ {include core=plpage.content.tpl}
+ </div>
+ {else}
+ <table id="body" cellpadding="0" cellspacing="0">
+ <tr>
+ <td id="body-top">
+ <img src="images/skins/default_headlogo.jpg" alt="[ LOGO ]" style="display: block; float: left;" />
+ <img src="images/skins/default_ban.jpg" alt="[ Polytechnique.org ]" /><br />
+ <img src="images/skins/default_lesX.gif" alt="[LES X SUR LE WEB]" style="padding-top: 0.3em" />
+ </td>
+ </tr>
+ <tr>
+ <td id="content">
+ {include core=plpage.content.tpl}
+ </td>
+ </tr>
+ </table>
+ {/if}
+ </body>
+</html>
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
{assign var="has_cs" value="true"}
{/if}
{/iterate}
+ {if hasPerm('user')}
<tr class="impair">
<td colspan="3" style="text-align: right">
{if $smarty.session.auth}<a href="survey/edit/new">{icon name=page_edit} Proposer un sondage</a>{/if}
</td>
</tr>
+ {/if}
</table>
{/if}
+++ /dev/null
-{**************************************************************************}
-{* *}
-{* Copyright (C) 2003-2011 Polytechnique.org *}
-{* http://opensource.polytechnique.org/ *}
-{* *}
-{* This program 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. *}
-{* *}
-{* 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 Software *}
-{* Foundation, Inc., *}
-{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *}
-{* *}
-{**************************************************************************}
-
-<h1>Identification</h1>
-
-<form action="{$smarty.server.REQUEST_URI}" method="post" id="login" onsubmit='doChallengeResponse(); return false;'>
- <table class="bicol">
- <tr>
- <td class="titre">Identifiant (adresse email) :</td>
- <td>
- <input type="text" name="username" />
- <input type="hidden" name="domain" value="email" />
- </td>
- </tr>
- <tr>
- <td class="titre">Mot de passe :</td>
- <td><input type="password" name="password" size="10" maxlength="256" /></td>
- </tr>
- <tr>
- <td {popup caption='Connexion permanente' width='300' text='Décocher cette case pour que le site oublie ce navigateur.<br />
- Il est conseillé de décocher la case si cette machine n\'est pas <b>strictement</b> personnelle'} colspan="2">
- <label><input type="checkbox" name="remember" checked="checked" />
- Garder l'accès aux services après déconnexion.
- </label>
- <br />
- <a href="recovery/ext">Mot de passe perdu ?</a>
- </td>
- </tr>
- <tr>
- <td colspan="2" class="center"><input type="submit" name="submitbtn" value="Envoyer" /></td>
- </tr>
- </table>
-</form>
-
-<form action="{$smarty.server.REQUEST_URI}" method="post" id="loginsub">
- <div>
- <input type="hidden" name="challenge" value="{$smarty.session.challenge}" />
- <input type="hidden" name="username" value="" />
- <input type="hidden" name="remember" value="" />
- <input type="hidden" name="response" value="" />
- <input type="hidden" name="xorpass" value="" />
- <input type="hidden" name="domain" value="" />
- <input type="hidden" name="auth_type" value="xnet" />
- </div>
-</form>
-
-{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
</p>
<p>
Votre compte est maintenant activé et votre passe créé. Vous pouvez donc
- profiter dès à présent des multiples fonctionnalités de Polytechnique.net.
+ profiter dès à présent des multiples fonctionnalités de <a href="http://www.polytechnique.net/">Polytechnique.net</a>.
</p>
<p>
Pour rappel, votre identifiant est : <strong>{$email}</strong>
<td id="perso">
{list_all_my_groups}
{if !$smarty.session.auth}
- <div>Me connecter :</div>
- <table style="margin-left: 1em">
- <tr>
- <td>
- <a class="gp" href="login/{if $platal->pl_self() eq 'exit'}index{else}{$platal->pl_self()}{/if}">X, masters, doctorants…</a>
- </td>
- </tr>
- <tr>
- <td><a class="gp" href="login/ext">Extérieurs</a></td>
- </tr>
- </table>
+ <div>
+ <a href="login/{if $platal->pl_self() eq 'exit'}index{else}{$platal->pl_self()}{/if}">Connexion</a>
+ </div>
{/if}
</td>
<td class="right" style="vertical-align: middle">
--- /dev/null
+UPDATE email_source_account
+ SET flags = REPLACE(flags, 'marital', 'usage')
+ WHERE FIND_IN_SET('marital', flags);
+
+-- vim:set syntax=mysql:
--- /dev/null
+UPDATE profile_public_names
+ SET lastname_main = REPLACE(lastname_main, ' ', ' ')
+ WHERE lastname_main LIKE '% %';
+
+ UPDATE accounts AS a
+INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms))
+INNER JOIN profile_public_names AS ppn ON (ppn.pid = ap.pid)
+INNER JOIN profile_display AS pd ON (pd.pid = ap.pid)
+ SET a.lastname = IF(ppn.lastname_ordinary = '', ppn.lastname_main, ppn.lastname_ordinary)
+ WHERE a.type IN ('x', 'master', 'phd');
+
+-- vim:set syntax=mysql:
--- /dev/null
+ALTER TABLE profile_addresses CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profile_corps CHANGE COLUMN corps_pub corps_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profile_job CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profile_job CHANGE COLUMN email_pub email_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profile_networking CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profile_photos CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profile_phones CHANGE COLUMN pub pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profiles CHANGE COLUMN freetext_pub freetext_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profiles CHANGE COLUMN medals_pub medals_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+ALTER TABLE profiles CHANGE COLUMN alias_pub alias_pub ENUM('hidden', 'private', 'ax', 'public') NOT NULL DEFAULT 'private';
+
+DROP TABLE IF EXISTS profile_visibility_enum;
+CREATE TABLE profile_visibility_enum (
+ access_level ENUM('admin', 'private', 'ax', 'public', 'none'),
+ best_display_level ENUM('hidden', 'private', 'ax', 'public') NULL,
+ display_levels SET('hidden', 'private', 'ax', 'public')
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO profile_visibility_enum (access_level, best_display_level, display_levels) VALUES
+ ('admin', 'hidden', 'hidden,private,ax,public'),
+ ('private', 'private', 'private,ax,public'),
+ ('ax', 'ax', 'ax,public'),
+ ('public', 'public', 'public'),
+ ('none', NULL, '');
--- /dev/null
+CREATE TABLE IF NOT EXISTS profile_partnersharing_enum (
+ id int(6) unsigned NOT NULL,
+ api_uid int(11) unsigned NULL,
+ shortname varchar(64) NOT NULL DEFAULT '',
+ name varchar(255) NOT NULL DEFAULT '',
+ url varchar(255) NOT NULL DEFAULT '',
+ default_sharing_level enum('admin', 'private', 'ax', 'public', 'none') DEFAULT 'none',
+ has_directory int(1) unsigned NOT NULL DEFAULT 0,
+ has_bulkmail int(1) unsigned NOT NULL DEFAULT 0,
+ PRIMARY KEY (id),
+ FOREIGN KEY (api_uid) REFERENCES accounts (uid) ON DELETE SET NULL ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO profile_partnersharing_enum
+ SET shortname = 'pta', name = 'ParisTech Alumni', url = 'http://www.paristech-alumni.org', default_sharing_level = 'public', has_directory = 1, has_bulkmail = 1;
+
+CREATE TABLE IF NOT EXISTS profile_partnersharing_settings (
+ pid int(11) unsigned NOT NULL,
+ partner_id int(6) unsigned NOT NULL,
+ exposed_uid varchar(255) NOT NULL,
+ sharing_level enum('admin', 'private', 'ax', 'public', 'none') DEFAULT 'none',
+ allow_email enum('none', 'digest', 'direct') DEFAULT 'direct',
+ last_connection datetime NULL,
+ PRIMARY KEY (pid, partner_id),
+ KEY (partner_id, exposed_uid),
+ FOREIGN KEY (pid) REFERENCES profiles (pid) ON DELETE CASCADE ON UPDATE CASCADE,
+ FOREIGN KEY (partner_id) REFERENCES profile_partnersharing_enum (id) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS profile_photo_tokens (
+ pid int(11) unsigned NOT NULL,
+ token varchar(255) NOT NULL,
+ expires datetime NOT NULL,
+ PRIMARY KEY (pid),
+ KEY (token),
+ FOREIGN KEY (pid) REFERENCES profiles (pid) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--- /dev/null
+ALTER TABLE account_types
+CHANGE perms perms SET('groups','mail','directory_ax','directory_private','edit_directory','forums','lists','payment','api_user_readonly','gapps', 'user') NOT NULL DEFAULT '';
+
+UPDATE account_types SET perms = CONCAT(perms, ',user') WHERE type IN ('ax', 'fx', 'master', 'phd', 'pi', 'school', 'x');
--- /dev/null
+ALTER TABLE group_auth
+ADD COLUMN group_id SMALLINT(5) UNSIGNED NULL DEFAULT NULL;
+ALTER TABLE group_auth
+ADD INDEX (group_id);
+ALTER TABLE group_auth
+ADD FOREIGN KEY (group_id) REFERENCES groups (id) ON UPDATE CASCADE ON DELETE CASCADE;
+
+ALTER TABLE group_auth
+ADD COLUMN flags SET('allow_xnet', 'group_only') DEFAULT '';
+
+UPDATE group_auth SET flags = 'allow_xnet' WHERE name = 'Polytechnique.net';
--- /dev/null
+#!/bin/bash
+
+. ../inc/pervasive.sh
+
+###########################################################
+[ "$DATABASE" != "x4dat" ] || die "Cannot target x4dat"
+
+confirm "* Running database upgrade scripts"
+mysql_run_directory .