看板初始化提交

This commit is contained in:
zephyr
2026-06-01 21:23:12 -07:00
commit 54a842f4ab
2104 changed files with 241695 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
<?php
namespace Kanboard\User\Avatar;
use Kanboard\Core\Base;
use Kanboard\Core\User\Avatar\AvatarProviderInterface;
/**
* Avatar Local Image File Provider
*
* @package avatar
* @author Frederic Guillot
*/
class AvatarFileProvider extends Base implements AvatarProviderInterface
{
/**
* Render avatar html
*
* @access public
* @param array $user
* @param int $size
* @return string
*/
public function render(array $user, $size)
{
$url = $this->helper->url->href('AvatarFileController', 'image', array('user_id' => $user['id'], 'hash' => md5($user['avatar_path'].$size), 'size' => $size));
$title = $this->helper->text->e($user['name'] ?: $user['username']);
return '<img src="' . $url . '" alt="' . $title . '" title="' . $title . '">';
}
/**
* Determine if the provider is active
*
* @access public
* @param array $user
* @return boolean
*/
public function isActive(array $user)
{
return !empty($user['avatar_path']);
}
}
+172
View File
@@ -0,0 +1,172 @@
<?php
namespace Kanboard\User\Avatar;
use Kanboard\Core\Base;
use Kanboard\Core\User\Avatar\AvatarProviderInterface;
/**
* Letter Avatar Provider
*
* The color hash algorithm is backported from the Javascript library color-hash
* Source: https://github.com/zenozeng/color-hash
* Author: Zeno Zeng (MIT License)
*
* @package avatar
* @author Frederic Guillot
*/
class LetterAvatarProvider extends Base implements AvatarProviderInterface
{
protected $lightness = array(0.35, 0.5, 0.65);
protected $saturation = array(0.35, 0.5, 0.65);
/**
* Render avatar html
*
* @access public
* @param array $user
* @param int $size
* @return string
*/
public function render(array $user, $size)
{
$initials = $this->helper->user->getInitials($user['name'] ?: $user['username']);
$rgb = $this->getBackgroundColor($user['name'] ?: $user['username']);
$name = $this->helper->text->e($user['name'] ?: $user['username']);
return sprintf(
'<div class="avatar-letter" style="background-color: rgb(%d, %d, %d)" title="%s" role="img" aria-label="%s">%s</div>',
$rgb[0],
$rgb[1],
$rgb[2],
$name,
$name,
$this->helper->text->e($initials)
);
}
/**
* Determine if the provider is active
*
* @access public
* @param array $user
* @return boolean
*/
public function isActive(array $user)
{
return true;
}
/**
* Get background color based on a string
*
* @param string $str
* @return array
*/
public function getBackgroundColor($str)
{
$hsl = $this->getHSL($str);
return $this->getRGB($hsl[0], $hsl[1], $hsl[2]);
}
/**
* Convert HSL to RGB
*
* @access protected
* @param integer $hue Hue ∈ [0, 360)
* @param integer $saturation Saturation ∈ [0, 1]
* @param integer $lightness Lightness ∈ [0, 1]
* @return array
*/
protected function getRGB($hue, $saturation, $lightness)
{
$hue /= 360;
$q = $lightness < 0.5 ? $lightness * (1 + $saturation) : $lightness + $saturation - $lightness * $saturation;
$p = 2 * $lightness - $q;
return array_map(function ($color) use ($q, $p) {
if ($color < 0) {
$color++;
}
if ($color > 1) {
$color--;
}
if ($color < 1/6) {
$color = $p + ($q - $p) * 6 * $color;
} elseif ($color < 0.5) {
$color = $q;
} elseif ($color < 2/3) {
$color = $p + ($q - $p) * 6 * (2/3 - $color);
} else {
$color = $p;
}
return round($color * 255);
}, array($hue + 1/3, $hue, $hue - 1/3));
}
/**
* Returns the hash in [h, s, l].
* Note that H ∈ [0, 360); S ∈ [0, 1]; L ∈ [0, 1];
*
* @access protected
* @param string $str
* @return array
*/
protected function getHSL($str)
{
$hash = $this->hash($str);
$hue = $hash % 359;
$hash = intval($hash / 360);
$saturation = $this->saturation[$hash % count($this->saturation)];
$hash = intval($hash / count($this->saturation));
$lightness = $this->lightness[$hash % count($this->lightness)];
return array($hue, $saturation, $lightness);
}
/**
* BKDR Hash (modified version)
*
* @access protected
* @param string $str
* @return integer
*/
protected function hash($str)
{
$seed = 131;
$seed2 = 137;
$hash = 0;
// Make hash more sensitive for short string like 'a', 'b', 'c'
$str .= 'x';
$max = intval(PHP_INT_MAX / $seed2);
for ($i = 0, $ilen = mb_strlen($str, 'UTF-8'); $i < $ilen; $i++) {
if ($hash > $max) {
$hash = intval($hash / $seed2);
}
$hash = $hash * $seed + $this->getCharCode(mb_substr($str, $i, 1, 'UTF-8'));
}
return $hash;
}
/**
* Backport of Javascript function charCodeAt()
*
* @access protected
* @param string $c
* @return integer
*/
protected function getCharCode($c)
{
list(, $ord) = unpack('N', mb_convert_encoding($c, 'UCS-4BE', 'UTF-8'));
return $ord;
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace Kanboard\User;
use Kanboard\Core\Base;
use Kanboard\Core\User\UserBackendProviderInterface;
use Kanboard\Filter\UserNameFilter;
use Kanboard\Model\UserModel;
/**
* Database Backend User Provider
*
* @package Kanboard\User
* @author Frederic Guillot
*/
class DatabaseBackendUserProvider extends Base implements UserBackendProviderInterface
{
/**
* Find a group from a search query
*
* @access public
* @param string $input
* @return DatabaseUserProvider[]
*/
public function find($input)
{
$result = array();
$users = $this->userQuery->withFilter(new UserNameFilter($input))
->getQuery()
->columns(UserModel::TABLE.'.id', UserModel::TABLE.'.username', UserModel::TABLE.'.name')
->eq(UserModel::TABLE.'.is_active', 1)
->asc(UserModel::TABLE.'.name')
->asc(UserModel::TABLE.'.username')
->findAll();
foreach ($users as $user) {
$result[] = new DatabaseUserProvider($user);
}
return $result;
}
}
+143
View File
@@ -0,0 +1,143 @@
<?php
namespace Kanboard\User;
use Kanboard\Core\User\UserProviderInterface;
/**
* Database User Provider
*
* @package user
* @author Frederic Guillot
*/
class DatabaseUserProvider implements UserProviderInterface
{
/**
* User properties
*
* @access protected
* @var array
*/
protected $user = array();
/**
* Constructor
*
* @access public
* @param array $user
*/
public function __construct(array $user)
{
$this->user = $user;
}
/**
* Return true to allow automatic user creation
*
* @access public
* @return boolean
*/
public function isUserCreationAllowed()
{
return false;
}
/**
* Get internal id
*
* @access public
* @return integer
*/
public function getInternalId()
{
return $this->user['id'];
}
/**
* Get external id column name
*
* @access public
* @return string
*/
public function getExternalIdColumn()
{
return '';
}
/**
* Get external id
*
* @access public
* @return string
*/
public function getExternalId()
{
return '';
}
/**
* Get user role
*
* @access public
* @return string
*/
public function getRole()
{
return empty($this->user['role']) ? '' : $this->user['role'];
}
/**
* Get username
*
* @access public
* @return string
*/
public function getUsername()
{
return empty($this->user['username']) ? '' : $this->user['username'];
}
/**
* Get full name
*
* @access public
* @return string
*/
public function getName()
{
return empty($this->user['name']) ? '' : $this->user['name'];
}
/**
* Get user email
*
* @access public
* @return string
*/
public function getEmail()
{
return empty($this->user['email']) ? '' : $this->user['email'];
}
/**
* Get external group ids
*
* @access public
* @return array
*/
public function getExternalGroupIds()
{
return array();
}
/**
* Get extra user attributes
*
* @access public
* @return array
*/
public function getExtraAttributes()
{
return array();
}
}
+242
View File
@@ -0,0 +1,242 @@
<?php
namespace Kanboard\User;
use Kanboard\Core\User\UserProviderInterface;
use Kanboard\Model\LanguageModel;
/**
* LDAP User Provider
*
* @package user
* @author Frederic Guillot
*/
class LdapUserProvider implements UserProviderInterface
{
/**
* LDAP DN
*
* @access protected
* @var string
*/
protected $dn;
/**
* LDAP username
*
* @access protected
* @var string
*/
protected $username;
/**
* User name
*
* @access protected
* @var string
*/
protected $name;
/**
* Email
*
* @access protected
* @var string
*/
protected $email;
/**
* User role
*
* @access protected
* @var string
*/
protected $role;
/**
* Group LDAP DNs
*
* @access protected
* @var string[]
*/
protected $groupIds;
/**
* User photo
*
* @access protected
* @var string
*/
protected $photo = '';
/**
* User language
*
* @access protected
* @var string
*/
protected $language = '';
/**
* Constructor
*
* @access public
* @param string $dn
* @param string $username
* @param string $name
* @param string $email
* @param string $role
* @param string[] $groupIds
* @param string $photo
* @param string $language
*/
public function __construct($dn, $username, $name, $email, $role, array $groupIds, $photo = '', $language = '')
{
$this->dn = $dn;
$this->username = $username;
$this->name = $name;
$this->email = $email;
$this->role = $role;
$this->groupIds = $groupIds;
$this->photo = $photo;
$this->language = $language;
}
/**
* Return true to allow automatic user creation
*
* @access public
* @return boolean
*/
public function isUserCreationAllowed()
{
return LDAP_USER_CREATION;
}
/**
* Get internal id
*
* @access public
* @return integer
*/
public function getInternalId()
{
return 0;
}
/**
* Get external id column name
*
* @access public
* @return string
*/
public function getExternalIdColumn()
{
return 'username';
}
/**
* Get external id
*
* @access public
* @return string
*/
public function getExternalId()
{
return $this->getUsername();
}
/**
* Get user role
*
* @access public
* @return string
*/
public function getRole()
{
return $this->role;
}
/**
* Get username
*
* @access public
* @return string
*/
public function getUsername()
{
return LDAP_USERNAME_CASE_SENSITIVE ? $this->username : strtolower($this->username);
}
/**
* Get full name
*
* @access public
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Get user email
*
* @access public
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Get groups DN
*
* @access public
* @return string[]
*/
public function getExternalGroupIds()
{
return $this->groupIds;
}
/**
* Get extra user attributes
*
* @access public
* @return array
*/
public function getExtraAttributes()
{
$attributes = array('is_ldap_user' => 1);
if (! empty($this->language)) {
$attributes['language'] = LanguageModel::findCode($this->language);
}
return $attributes;
}
/**
* Get User DN
*
* @access public
* @return string
*/
public function getDn()
{
return $this->dn;
}
/**
* Get user photo
*
* @access public
* @return string
*/
public function getPhoto()
{
return $this->photo;
}
}
+132
View File
@@ -0,0 +1,132 @@
<?php
namespace Kanboard\User;
use Kanboard\Core\User\UserProviderInterface;
/**
* OAuth User Provider
*
* @package user
* @author Frederic Guillot
*/
abstract class OAuthUserProvider implements UserProviderInterface
{
/**
* User properties
*
* @access protected
* @var array
*/
protected $user = array();
/**
* Constructor
*
* @access public
* @param array $user
*/
public function __construct(array $user)
{
$this->user = $user;
}
/**
* Return true to allow automatic user creation
*
* @access public
* @return boolean
*/
public function isUserCreationAllowed()
{
return false;
}
/**
* Get internal id
*
* @access public
* @return integer
*/
public function getInternalId()
{
return 0;
}
/**
* Get external id
*
* @access public
* @return string
*/
public function getExternalId()
{
return isset($this->user['id']) ? $this->user['id'] : '';
}
/**
* Get user role
*
* @access public
* @return string
*/
public function getRole()
{
return '';
}
/**
* Get username
*
* @access public
* @return string
*/
public function getUsername()
{
return '';
}
/**
* Get full name
*
* @access public
* @return string
*/
public function getName()
{
return isset($this->user['name']) ? $this->user['name'] : '';
}
/**
* Get user email
*
* @access public
* @return string
*/
public function getEmail()
{
return isset($this->user['email']) ? $this->user['email'] : '';
}
/**
* Get external group ids
*
* @access public
* @return array
*/
public function getExternalGroupIds()
{
return array();
}
/**
* Get extra user attributes
*
* @access public
* @return array
*/
public function getExtraAttributes()
{
return array();
}
}
+188
View File
@@ -0,0 +1,188 @@
<?php
namespace Kanboard\User;
use Kanboard\Core\User\UserProviderInterface;
use Kanboard\Core\Security\Role;
/**
* Reverse Proxy User Provider
*
* @package user
* @author Frederic Guillot
*/
class ReverseProxyUserProvider implements UserProviderInterface
{
/**
* Username
*
* @access protected
* @var string
*/
protected $username = '';
/**
* Email
*
* @access protected
* @var string
*/
protected $email = '';
/**
* Full name
*
* @access protected
* @var string
*/
protected $fullname= '';
/**
* User profile if the user already exists
*
* @access protected
* @var array
*/
private $userProfile = array();
/**
* Constructor
*
* @access public
* @param string $username
* @param string $email
* @param string $fullname
*/
public function __construct($username, $email, $fullname, array $userProfile = array())
{
$this->username = $username;
$this->email = $email;
$this->fullname = $fullname;
$this->userProfile = $userProfile;
}
/**
* Return true to allow automatic user creation
*
* @access public
* @return boolean
*/
public function isUserCreationAllowed()
{
return true;
}
/**
* Get internal id
*
* @access public
* @return integer
*/
public function getInternalId()
{
return 0;
}
/**
* Get external id column name
*
* @access public
* @return string
*/
public function getExternalIdColumn()
{
return 'username';
}
/**
* Get external id
*
* @access public
* @return string
*/
public function getExternalId()
{
return $this->username;
}
/**
* Get user role
*
* @access public
* @return string
*/
public function getRole()
{
if (REVERSE_PROXY_DEFAULT_ADMIN === $this->username) {
return Role::APP_ADMIN;
}
if (isset($this->userProfile['role'])) {
return $this->userProfile['role'];
}
return Role::APP_USER;
}
/**
* Get username
*
* @access public
* @return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Get full name
*
* @access public
* @return string
*/
public function getName()
{
return $this->fullname;
}
/**
* Get user email
*
* @access public
* @return string
*/
public function getEmail()
{
if (REVERSE_PROXY_DEFAULT_DOMAIN !== '' && $this->email === '') {
return $this->username.'@'.REVERSE_PROXY_DEFAULT_DOMAIN;
}
return $this->email;
}
/**
* Get external group ids
*
* @access public
* @return array
*/
public function getExternalGroupIds()
{
return array();
}
/**
* Get extra user attributes
*
* @access public
* @return array
*/
public function getExtraAttributes()
{
return array(
'is_ldap_user' => 1,
'disable_login_form' => 1,
);
}
}