- 后端
- 前端
- 协同办公
- 即时通讯
- 企业应用
【免费下载链接】dootask
DooTask是一款开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具;同时消息功能使用非对称加密技术让你的沟通更安全。
导读
本文围绕 DooTask 的用户自助注册流程展开,覆盖从登录页入口、三种注册方式(开放 / 邀请码 / 关闭)的前端展示与后端判定,到完整操作步骤、注册后自动创建个人项目与邮箱验证行为的全过程。通过本文你将掌握:如何判断当前系统是否开放注册、邀请码注册的后端比对机制、api/users/reg/needinvite注册状态接口的返回语义,以及注册后系统自动触发的一系列初始化动作(个人项目、全员群、索引同步等)。文中所有结论均可在当前开源仓库的源码、路由与测试用例中找到对应依据。
注册入口
DooTask 的注册入口有两个:
- 登录页底部「注册账号」链接:登录页会在注册开放时显示「还没有帐号?注册帐号」的切换链接,点击后切换到注册表单;
- URL 直达:访问
/login?type=reg可直接定位到注册表单。
前端登录页实现在 resources/assets/js/pages/login.vue,其中loginType在'reg'与'login'之间切换,注册表单会额外渲染「确认密码」「邀请码(需要时)」等输入项,提交时向users/login接口发送type / email / password / code / code_key / invite等参数。
需要特别说明的是:URL 直达并不代表一定能注册。当系统注册方式为「关闭」时,即使通过/login?type=reg直达,页面也会停留在登录表单,不会展示注册 tab。
注册方式三档:open / invite / close
注册方式由系统管理员在「系统设置 → 注册设置」中控制,底层对应system.reg配置项,共三档取值:
| 取值 | 行为 | 前端表现 |
|---|---|---|
open(开放) | 任何人填邮箱 + 密码即可注册 | 登录页显示注册入口,无需邀请码 |
invite(邀请码) | 除邮箱 + 密码外,还必须填写正确的邀请码 | 登录页显示注册入口,且注册表单展示「邀请码」输入框 |
close(关闭) | 完全关闭自助注册 | 登录页隐藏注册入口,直达/login?type=reg也停留在登录表单 |
仓库证据:
system.reg的默认值为open,见种子数据 database/seeders/SettingsTableSeeder.php 中的'{"reg":"open","project_invite":"open","login_code":"auto"}'。
邀请码是什么
当注册方式为invite时,管理员在系统设置中配置一个字符串作为reg_invite:
- 只有一个全局值:所有想注册的人共用同一个邀请码;
- 不限次数、不过期:邀请码不区分用户、不限制使用次数、也没有有效期;
- 严格比对:注册时后端将提交的
Request.invite与配置的setting.reg_invite做直接比对,不通过则直接拒绝,且没有「错几次锁定」之类的限制。
注意区分:这里的「邀请码」是系统级开放注册的密钥,与「邀请同事加入项目」完全是两回事。前者决定能否成为 DooTask 用户(账号级别),后者是成为用户后加入某个项目(项目级别)。系统管理员是注册阶段的守门人,项目负责人是项目阶段的守门人。更完整的说明见 注册是否需要邀请码。
后端判定逻辑(源码级)
注册判定实现在 app/Http/Controllers/Api/UsersController.php 的login()方法中(注册分支):
if ($type == 'reg') { if (mb_strlen($email) > 32 || mb_strlen($password) > 32) { return Base::retError('账号密码最多可输入32位字符'); } $setting = Base::setting('system'); if ($setting['reg'] == 'close') { return Base::retError('未开放注册'); } elseif ($setting['reg'] == 'invite') { $invite = trim(Request::input('invite')); if (empty($invite) || $invite != $setting['reg_invite']) { return Base::retError('请输入正确的邀请码'); } } $user = User::reg($email, $password); ... }由此可以确认几个关键行为:
close模式下直接调用注册接口会返回「未开放注册」;invite模式下邀请码为空或不匹配都会返回「请输入正确的邀请码」;- 邮箱、密码任一超过 32 个字符(按
mb_strlen多字节长度计)都会返回「账号密码最多可输入32位字符」。
注册状态判定接口:api/users/reg/needinvite
前端在进入登录页时会先调用GET api/users/reg/needinvite来判断是否显示注册入口以及是否展示邀请码输入框。该接口的实现位于 app/Http/Controllers/Api/UsersController.php 的reg__needinvite()方法:
public function reg__needinvite() { $reg = Base::settingFind('system', 'reg', 'open'); return Base::retSuccess('success', [ 'enabled' => $reg !== 'close', 'need' => $reg === 'invite', ]); }返回的 JSON 数据包含两个布尔字段,语义如下:
| 字段 | 取值 | 含义 | 前端行为 |
|---|---|---|---|
enabled | false | reg=close,关闭注册 | 隐藏注册入口;即使/login?type=reg直达也停留在登录表单 |
enabled | true | reg=open或reg=invite | 显示注册入口 |
need | true | reg=invite | 注册表单显示「邀请码」输入框 |
need | false | reg=open或reg=close | 以enabled为准 |
前端逻辑位于 resources/assets/js/pages/login.vue 的refreshRegistrationSetting()方法:调用users/reg/needinvite后,用data.need设置needInvite(是否显示邀请码框),用data.enabled设置registrationAvailable(是否显示注册入口);兼容旧版本只返回need字段的情况。该接口在路由表中登记为「注册状态」,见 routes/api-map.md。
这一行为还有自动化测试保障:测试文件 tests/Feature/RegistrationAvailabilityTest.php 分别验证了reg=close时接口返回enabled=false, need=false,以及reg=invite时返回enabled=true, need=true,可作为回归验证参考。
注册操作步骤
以 Web 端为例,完整注册流程如下:
- 进入登录页(
/login),点击「注册帐号」切换到注册 tab,或直接访问/login?type=reg; - 输入邮箱:要求是合法邮箱地址,长度不超过 32 个字符;
- 输入密码:长度 6~32 个字符,且需满足管理员配置的密码策略;
- 确认密码:与密码保持一致;
- 若注册方式为
invite,在「邀请码」输入框填写管理员下发的全局邀请码; - 点击提交,等待注册结果。
密码策略说明(源码级)
密码校验实现在 app/Models/User.php 的passwordPolicy()方法中:
- 密码长度不得小于 6 位(否则报「密码设置不能小于6位数」);
- 密码长度不得超过 32 位(否则报「密码最多只能设置32位数」);
- 当系统开启复杂密码策略(
system.password_policy = complex)时,还有额外约束:不能是纯数字、不能是纯字母、不能是纯数字+大写字母、不能是纯数字+小写字母,即必须包含数字、字母大小写或特殊字符的组合。
注册后行为
注册成功后,DooTask 会自动执行一系列初始化动作,本节结合源码逐一说明。
1. 自动创建「个人项目」
注册(或登录)成功后会为没有个人项目的用户自动创建一个「📝 个人项目」,实现位于 app/Http/Controllers/Api/UsersController.php:
if (!Project::withTrashed()->whereUserid($user->userid)->wherePersonal(1)->exists()) { Project::createProject([ 'name' => "📝 " . Doo::translate('个人项目'), 'desc' => Doo::translate('注册时系统自动创建项目,你可以自由删除。'), 'personal' => 1, ], $user->userid); }要点:
- 每个用户最多只有 1 个个人项目,重复创建会返回「个人项目已存在,无须重复创建」(见 app/Models/Project.php 的
createProject()); - 个人项目由系统自动创建,不受项目创建权限限制;
- 注册失败或注册后未登录的情况下,个人项目会在登录成功时补建。
2. 邮箱验证(可选开启)
若管理员开启了「注册需邮箱验证」(emailSetting.reg_verify = open),注册接口会走验证分支:
if ($isRegVerify) { UserEmailVerification::userEmailSend($user); return Base::retError('注册成功,请验证邮箱后登录', ['code' => 'email']); }此时注册不会直接登录成功,而是返回提示「注册成功,请验证邮箱后登录」并附带code: 'email'标记,同时向用户邮箱发送一封验证邮件。前端收到该标记后会切回登录表单(见 resources/assets/js/pages/login.vue 中data.code === 'email'的处理分支)。
验证邮件的发送逻辑在 app/Models/UserEmailVerification.php 的userEmailSend()方法中:生成一个 64 位随机 code,邮件中的验证链接形如single/valid/email?code=...,链接 30 分钟内有效、且一次性使用。验证流程的完整说明见 邮箱验证。
3. 注册数据初始化与后置动作
User::reg()方法(app/Models/User.php)在账号创建后还会执行:
- 设置
az(昵称首字母)与pinyin(昵称拼音)用于检索排序; - 记录注册 IP(
created_ip); - 若管理员配置了注册临时身份(
reg_identity = temp),给新用户打上temp身份; - 若开启了全员群自动加入(
all_group_autoin = yes,默认开启),自动将新用户拉入全员群组(WebSocketDialog的all群); - 触发 Manticore 索引同步(
ManticoreSyncTask('user_sync', ...)),保证新用户可被全局搜索命中; - 触发
user_onboard钩子(Apps::dispatchUserHook),供应用市场应用在新用户注册时执行 onboarding 流程。
4. 未开启邮箱验证时
当emailSetting.reg_verify未开启时,注册成功后直接返回 token,前端调用handleClearCache完成登录态写入并跳转到工作台(manage-dashboard),即「注册即登录」。
注册校验链路:从接口到账号落库
完整的一条注册请求,其服务端调用链可以概括为:
POST/GET api/users/login (type=reg) └─ UsersController::login() // 长度、reg 模式、邀请码校验 └─ User::reg() // 邮箱格式、查重、密码策略、license 校验 └─ Doo::userCreate() // 底层账号创建(经 DooSo 接口层)其中User::reg()内部的核心校验顺序如下(app/Models/User.php):
- 邮箱格式:
Base::isEmail($email)不通过则抛「请输入正确的邮箱地址」; - 邮箱查重:已存在同邮箱账号时返回「邮箱地址已存在」;若该账号此前注册过但未验证邮箱,且当前开启了邮箱验证,则会重新发送验证邮件并提示「您的帐号已注册过,请验证邮箱」;
- 密码策略:
passwordPolicy(),见上文; - License 校验:
Doo::licenseBindingError(Doo::license()),商业授权受限时会阻止注册; - 账号创建:
Doo::userCreate()经 app/Module/Interface/DooSo.php 的接口层落库,并处理事务边界。
常见错误提示与含义对照
| 提示文案 | 触发条件 | 处理建议 |
|---|---|---|
| 未开放注册 | system.reg = close,直接调用注册接口 | 联系管理员手动创建账号,或让管理员开放注册 |
| 请输入正确的邀请码 | reg=invite且邀请码为空或不匹配 | 向管理员确认正确的全局邀请码 |
| 账号密码最多可输入32位字符 | 邮箱或密码超过 32 字符 | 缩短输入 |
| 请输入正确的邮箱地址 | 邮箱格式非法 | 检查邮箱拼写 |
| 邮箱地址已存在 | 该邮箱已注册 | 直接去登录;若提示验证邮箱,先完成邮箱验证 |
| 密码设置不能小于6位数 / 密码最多只能设置32位数 | 密码长度不满足 6~32 | 调整密码长度 |
| 密码不能全是数字/字母… | 开启复杂密码策略后密码太简单 | 使用数字、字母大小写、特殊字符的组合 |
注册的边界与限制
- 不支持用户名注册:账号必须是邮箱,没有单独的「用户名」注册方式;
- 不支持第三方账号(微信/手机号)直接注册:扫码登录、SSO 是登录方式而非注册方式,注册阶段的守门机制仍以邮箱 + 系统注册方式为准;
- 注册 ≠ 登录:开启邮箱验证时,注册后必须先完成邮箱验证才能登录;验证链接 30 分钟内有效、一次性使用,过期或使用过后需重新触发邮件(重新注册或登录触发,见 邮箱验证);
- 注册关闭时的替代路径:
reg=close时所有人无法自助注册,此时只能由管理员在后台手动创建账号(管理员创建账号复用同一套注册逻辑,并支持强制首登改密、指定部门与职位,见User::createByAdmin())。
管理员侧配置入口
系统管理员(userIsAdmin)调整注册方式与邀请码的路径为:
「系统设置」→「注册设置」→ 切换
reg模式(open / invite / close)或修改reg_invite字符串。
修改即时生效,无需重启服务。因为注册判定每次请求都会实时读取system设置(通过Base::settingFind('system', 'reg', 'open')读取),不存在缓存延迟;这也是为什么前端每次进入登录页都会重新调用reg/needinvite的原因。
小结
DooTask 的注册体系由「系统设置驱动的三档模式 + 前置状态接口 + 后端多重校验 + 注册后自动初始化」四层构成:前端通过api/users/reg/needinvite动态渲染注册入口与邀请码输入框,后端在api/users/login(type=reg)中对长度、注册开关、邀请码、邮箱格式与查重、密码策略、license 逐层把关,注册成功后自动创建个人项目、可选触发邮箱验证、加入全员群并同步搜索索引。理解这套链路,无论是普通用户完成注册、管理员开放/关闭自助注册,还是开发者接入注册相关流程,都能有的放矢。
- 后端
- 前端
- 协同办公
- 即时通讯
- 企业应用
【免费下载链接】dootask
DooTask是一款开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具;同时消息功能使用非对称加密技术让你的沟通更安全。
相关推荐
注册策略设置:DooTask 开放注册、邀请码与临时帐号配置全解析
注册策略设置:DooTask 开放注册、邀请码与临时帐号配置全解析 本文基于仓库内 resources/ai kb/zh/howto/system settin
后端前端协同办公即时通讯企业应用DooTask 注册邀请码机制全解:`system.reg` 三档注册策略与 `api/users/reg/needinvite` 前端判定
DooTask 注册邀请码机制全解: system.reg 三档注册策略与 api/users/reg/needinvite 前端判定 本篇技术指南围绕 Doo
后端前端协同办公即时通讯企业应用DooTask 邮箱验证机制全解析:从注册触发、邮件投递到链接校验的完整流程
DooTask 邮箱验证机制全解析:从注册触发、邮件投递到链接校验的完整流程 本文基于 DooTask 官方知识库「邮箱验证」文档 https://link.g
后端前端协同办公即时通讯企业应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考