Git Product home page Git Product logo

webook's Introduction

webook

该网站原本是为了我在极客时间上的课程而服务的,但是现在我决定将它重构为一个专注于提供面试方案的网站。

这一次我会尝试一些新的写法,所以和你们在我课程上讲述的内容会有一些出入。

但是指导**是一致的。

此外,作为一个小应用,所以还有一些和课程内容有出入,因为我希望进一步提高研发效率。具体的点:

  • 在初始阶段,摒弃定义一些没有多个实现的接口,确保研发效率。在需要的时候,再引入接口;
  • 受制于 wire 的功能有限,所以一些和 ioc 有关的代码,奇丑无比

一点点设计原则

  • 药医不死病,佛渡有缘人
  • 不需要考虑攻击者的用户体验

缓存的 key 设计

基本上遵循了:webook:$module:xxxxxxx 的形式。即第一段是 webook,代表本体;第二段是 webook 内部的 module,代表模块。后面的就是 key,可以进一步细分。

HTTP 响应码

  • 大多数情况下是 200
  • 未登录是 401
  • 没有权限是 403

这里比较蛋疼的是 401 和 403 的语义。所以我也没什么好纠结的,只是做一个简单的区分

商品SPU类别说明

从标准的电商结构上来说,类别是一个独立的模块,并且会做比较复杂的关系型数据库的设计。但是目前我们在这个项目里面,并不需要这么复杂的东西,所以只需要搞一个粗糙的二级目录就可以了。

  • category0表示SPU顶级类别,可选值有product表示商品,code表示兑换码
  • category1表示SPU次级类别,可选值有member/project等

两者组合语义如下:

  • category0=product, category1=member 表示会员商品
  • category0=code, category1=project 表示项目兑换码
  • category0=product, category1=credit 表示积分(积分本身也可以购买)

营销模块说明

  1. 营销模块中兑换码相关业务为了保持独立,没有采用商品模块中的业务术语. 比如兑换码本事就蕴含了商品SPU类别category0=code这个含义,兑换码的type的值也就是商品SPU类别category1的值.

错误码

  • user - 01
  • question - 02
  • cos - 03
  • product - 04
  • case - 05
  • order - 06
  • skill - 07
  • label - 08
  • feedback -09
  • credit - 10
  • project - 11
  • marketing - 12
  • roadmap - 13 # 路线图
  • bff - 14
  • resume - 15

内部 APP ID

因为整个后台会被用于所有的 APP(我们会有很多 AI 应用)

  • 0 或者不存在:八股文网站本体
  • 1:AI 雅思

webook's People

Contributors

chenmingyong0423 avatar flycash avatar frankiejun avatar juniaoshaonian avatar l0slaker avatar longyue0521 avatar pyxy avatar wendy2560 avatar wenzu-zhou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

webook's Issues

重写 check permission 的测试

仅限中文

在提之前请先查找已有 issues,避免重复上报。

并且确保自己已经:

  • 阅读过文档
  • 阅读过注释
  • 阅读过例子

问题简要描述

已有的 check permission builder 的单元测试里面,模拟数据的时候是直接返回了 map[string]string

但是这其实并不符合 redis session 的形态,主要是因为这个:

https://github.com/ecodeclub/webook/pull/179/files#diff-c0b6b75f761fe9fe34a5186d64ad8f075d0a02a64fe65907eb4d632bd4ec1a8b

不过目前这个 builder 并没有被用到,等我们真正启用之前修复了就可以。

复现步骤

如果涉及到数据库表,你必须提供模型定义和表结构定义

错误日志或者截图

你期望的结果

你排查的结果,或者你觉得可行的修复方案

可选。我们希望你能够尽量先排查问题,帮助我们减轻维护负担。这对于你个人能力提升同样是有帮助的。

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

绑定微信账号

仅限中文

使用场景

如题。

绑定微信账号的基本流程和微信扫码登录是一样的,都是请求授权,在授权之后,就在数据库中写入该微信的信息。

该功能要求必须先实现手机号码登录。

注意:

  1. 如果该用户已经绑定了微信,则不允许替换。也就是 Union ID 不为 NULL。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

email 重试的装饰器实现

类似于 #14 中的设计思路,你需要提供一个装饰器来实现重试策略。

  1. 定义一个 retry 子包,提供一个 RetryEmailService。
  2. 创建一个初始化方法,NewRetryEmailService(svc email.Service, fac func()retry.Strategy)。其中第二个参数,是一个工厂,也是函数式编程。retry.Strategy 是我在 ekit 中提供的 https://github.com/ecodeclub/ekit/blob/dev/retry/types.go
  3. 定义一个代表重试次数耗尽的错误,但是先做成私有的

提供单元测试就可以。

JWT + 长短 token 登录验证

在完成用户注册之后,现在可以开始登录功能。

但是用户登录,我们直接采用长短 token + JWT 的机制。

在登录成功的时候,返回两个 token,一个 access_token,一个 refresh_token。其中 access_token 被用来正常访问数据,refresh_token 用来刷新 token。其中 access_token 被放到响应 header x-access-token 中,refresh token 被放到 x-refresh-token 中。

登录的时候,你假定前端会传过来三个字段:

  • email
  • password
  • fingerprint:你可以认为这是一个前端采集了用户的登录环境生成的一个码,你编码进去 JWT acccess_token 中。

提供完整的单元测试和集成测试。

注意:此时你只需要提供 Login 接口,登录校验以及对应的刷新接口,我会创建另外的 issue。

GetMembershipInfo 中如果没有记录,不应该返回 error

仅限中文

使用场景

如果一个用户刚注册的时候,是咩有会员信息的,此时是一个正常的现象,所以不应该返回 error。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

微信支付回调地址改成可配置的

仅限中文

使用场景

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

在 payment 里面的微信支付实现里面,我们的回调地址是直接写死的。

现在需要你修改为从配置文件中读取,可以参考其它部分的读取配置代码。

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

实现用户注册功能

允许用户注册账号。

需求要点:

  • 使用邮箱进行注册。
  • 密码至少六位,无其他要求。
  • 如果邮箱冲突了,后端接口返回特定的错误码。前端提示邮箱已注册,请登录。

数据库中不直接存储时间,存储毫秒数。

你需要提供:

  • 代码实现
  • 单元测试
  • 集成测试

publish project 的时候,同步上架到 spu 和 sku

仅限中文

使用场景

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

注意点:

  • 如果是第一次 publish,那么需要插入对应的 product_spu 和 code_spu
  • 如果是后续更新之后 publish,那么对应的 product_spu 和 code_spu 不需要修改。对应的 SPU 数据,需要修改的是 name 等文本、描述性字段

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

Project 支持额外字段

仅限中文

使用场景

考虑到用户需要对整个项目建立一个基本的认知之后,会更加有助于理解其它内容,所以我们需要增加一些额外的字段:

  • Overview,也就是概览
  • SystemDesign,也就是系统设计

暂时增加这两个字段。这两个字段对应的内容就是大量的

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

email service 简单的 failvover 策略:轮询

为 EmailService 提供一个实现,该实现是一个装饰器模式。在该装饰器内部,会轮询每一个 EmailService 的实例(初始化的时候用户传入)。

为此:

  1. 将现有的 EmailSevice 挪到 gomail 这个子包里面。
  2. 创建一个 failover 包,提供该 failover 实现,暂定叫做 FailoverEmailService。如果你有更好的名字也可以
  3. 提供一个初始化函数,用户会传入具体的可用的 svcs,也就是不同的 Email 服务的实现

同时,对于 failover 的策略来说:

  • 如果轮询到的服务返回了 error,
    • 如果 error 是 context.Canceled 或者 context.DeadlineXX(忘了),说明被取消,或者超时,直接返回,不需要继续了
    • 否则,取下一个 svc 尝试
  • 没有返回 error,说明发送成功

用户个人信息

提供一个编辑接口,晚上用户的个人信息。暂时考虑以下字段:

  • 个性签名
  • 生日
  • 昵称

头像暂时不需要搞。

验证用户邮箱

正常来说,当用户使用了邮箱注册之后,其实这个时候我们并不是这个邮箱究竟是不是用户的邮箱。

比如说,我完全可以编造一个邮箱,然后注册。所以,一个关键点是要对邮箱进行验证。

验证分两种验证:

  • 事前验证,也就是在注册之前,直接给邮箱发一个验证码,要求用户拿着验证码来注册
  • 事后验证,注册成功之后,给邮箱发一个验证连接,提醒用户去验证。

那么你现在需要完成第一步:事后验证。也即是 SignUp 成功之后,你立刻发一封邮件出去。里面带上一个链接,这个链接就是验证的链接。

正常来说,验证了链接里面会带有 token。你可以考虑使用 JWT 来生成 token。这个 token 解析之后就能得到邮箱,那么你就知道是哪个邮箱验证了。而后在数据库里面标记一下这个邮箱是已经验证过了。

支持手机号码登录

仅限中文

使用场景

如题。目前只需要考虑支持国内手机号码。

要做好:

  • 发手机验证码的频率控制
  • 校验是否是合法的国内手机号码(不需要严格校验)

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

点赞、收藏功能

仅限中文

使用场景

实现这个接口 https://github.com/ecodeclub/webook/blob/main/internal/interactive/internal/web/handler.go

image image

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

DAO 中 Project 和 PubProject 分离

仅限中文

使用场景

在现在的代码里面,Project 和 PubProject 其实是同一个定义。但是在将 Project 上架到 SPU 的时候,需要 product_spu 和 code_spu 两个字段。可是这两个字段,只对 PubProject 有意义。

因此:

  • 重新定义 PubProject,让 PubProject 组合 Project,并且额外添加 ProductSPU 和 CodeSPU 字段,原本在 Project 中的这两个字段删除
  • domain 的定义不需要修改。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

绑定手机号码

仅限中文

使用场景

如果一个用户最开始是用微信登录的,那么应该允许这个用户绑定手机号码。

注意:

  1. 控制手机验证码的发送频率

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

搜索模块

仅限中文

使用场景

  • 将 case 中的数据同步过去搜索模块
  • 将 question 中的数据同步过去搜索模块
  • 将 skill 中的数据同步过去搜索模块
  • 将 question set 中的数据同步过去搜索模块
  • 暴露搜索接口:如果传入了 biz,那么就按照 biz 来搜索;如果没有传入 biz,则是在前面四个索引中搜索
  • 在含有标签字段的数据中,标题权重 > 标签权重 > 内容权重

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

  • 设计一个通用的 Event,所有的业务都朝这个 topic 里面发消息
  • 所有的发送者要注意保证顺序。也就是说,消息不能失序
  • 各个业务有一个专属的搜索接口(单独的接口,不是单独的方法),而有一个装饰器的模式,会利用各个业务的接口来组合成没有传入 biz 的搜索

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

引入 wire 来初始化项目

仅限中文

使用场景

目前来说,因为代码严格遵循依赖注入的风格,所以后续依旧保持手写初始化过程的代码,会是一个比较重的负担。在这种情况下,使用 wire 会是一个很不错的选择。

更进一步,将来需要借助 wire 的依赖注入功能,做到 webook 本身可以作为单体应用,也可以作为微服务独立部署。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

因为后续的任何修改都可能引发冲突,所以这个 issue 要先解决了

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

将微信支付的配置信息修改为从配置文件中读取

仅限中文

使用场景

我们在这里需要重新设计一下代码。最开始的代码是从环境变量里面读取的:

		AppID:            os.Getenv("WEPAY_APP_ID"),
		MchID:            os.Getenv("WEPAY_MCH_ID"),
		MchKey:           os.Getenv("WEPAY_MCH_KEY"),
		MchSerialNum:     os.Getenv("WEPAY_MCH_SERIAL_NUM"),

这个是之前我录制视频,因为不想暴露设置而写的。现在我们可以将这些全部挪到配置文件里面:

wechat:
    payment:
       xxx

对应的回调地址也修改为这种组织方式。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

搜索接口支持分页

仅限中文

使用场景

目前的搜索接口,是直接返回全部的数据。但是可以预期的时候,如果命中的结果非常多,那么效率会很低。在这种情况下,需要引入分页。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

有两种可行的选择:

  • 直接在查询接口里面加上分页参数,offset 和 limit
  • 在搜索表达式里面加上 offset 和 limit 的语法

我倾向于第一种方案,因为 offset 和 limit 是一个非常通用的选项。

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

case 和 question 支持 status

仅限中文

使用场景

早期我在设计的时候,使用了一种比较简单的策略,也就是数据直接同步,而没有使用状态来控制。现在我需要在 case 和 question 中加入状态的支持。

它们的状态都是:

  • 0:unknown,
  • 1: unpublish 未发表
  • 2: published 已发表

制作库:当调用编辑接口(Save)的时候,将数据标记位 unpublish,当调用(publish)接口的时候,标记为 publish。数据库列的默认值是 1
线上库:默认值是 published。目前还没有设计撤销(下架)等接口,所以永远都是 published 状态。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

模拟面试题支持多个回答

仅限中文

使用场景

我意识到,同一个项目,被不同的拿出去面试,面试官即便问出同一个问题,回答也是不一样的。

举个例子来说,在”你为什么开发一个新的 dbproxy " 的时候,对于项目负责人来说,他需要更加详细解释自己的决策理由;对于一个核心研发来说,就可以比较简单的解释;对于毕设来说,那就更加容易解释,感兴趣或者了解到暂时缺少这么一个东西,都可以。

因此我们要重新调整在 Project 之下的 Question 的设计。

行业分析

如果你知道有框架提供了类似功能,可以在这里描述,并且给出文档或者例子

可行方案

如果你有设计思路或者解决方案,请在这里提供。你可以提供多个方案,并且给出自己的选择

在当下,Question 的设计是:

type Question struct {
	Id       int64
	Title    string
	Analysis string
	Answer   string
	Status   QuestionStatus
	Utime    time.Time
}

那么修改后的设计就是:

type Question struct {
	Id       int64
	Title    string
	Analysis string
        // 这个字段废弃
	Answer   string
	Status   QuestionStatus
	Utime    time.Time
}

type Answer struct {
	Id      int64
// 问题的 id
        Qid int64
// 如果 Role 是 0,那么我们认为是适用于所有角色的回答
       Role uint8 
	Content string
	// 关键字,辅助记忆,提取重点
	Keywords string
	// 速记,口诀
	Shorthand string

	// 亮点
	Highlight string

	// 引导点
	Guidance string
}

提供对应的制作库和线上库接口

其它

任何你觉得有利于解决问题的补充说明

你使用的是 webook 哪个版本?

你设置的的 Go 环境?

上传 go env 的结果

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.