-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 892a549
Showing
138 changed files
with
40,265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
end_of_line = lf | ||
insert_final_newline = true | ||
indent_style = space | ||
indent_size = 2 | ||
trim_trailing_whitespace = true | ||
|
||
[*.md] | ||
trim_trailing_whitespace = false | ||
|
||
[*.yml] | ||
indent_size = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.js linguist-language=go |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, build with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out | ||
.DS_Store | ||
# ide | ||
/.idea | ||
/.vscode | ||
|
||
/tmp | ||
/storage/fresh_tmp | ||
/storage/logs | ||
/node_modules | ||
npm-debug.log | ||
yarn-error.log | ||
config.yaml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
APP_NAME = "gin_bbs" | ||
|
||
default: | ||
go build -o ${APP_NAME} | ||
# env GOOS=linux GOARCH=amd64 go build -o ${APP_NAME} | ||
|
||
install: | ||
go mod download | ||
|
||
dev: | ||
fresh -c ./fresh.conf | ||
|
||
mock: | ||
go run ./main.go -m | ||
|
||
clean: | ||
if [ -f ${APP_NAME} ]; then rm ${APP_NAME}; fi | ||
|
||
help: | ||
@echo "make - compile the source code" | ||
@echo "make install - install dep" | ||
@echo "make dev - run go fresh" | ||
@echo "make mock - mock data" | ||
@echo "make clean - remove binary file" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Gin Weibo App | ||
参考 [L01 Laravel 教程 - Web 开发实战入门](https://learnku.com/courses/laravel-essential-training/5.8),使用 Golang (Gin、Gorm) 改写。 | ||
|
||
项目结构和风格模仿 Laravel。 | ||
|
||
## 项目目录结构 | ||
<details> | ||
<summary>展开查看</summary> | ||
<pre><code> | ||
├── app 项目核心逻辑代码 | ||
│ ├── auth 用户相关 | ||
│ ├── controllers 控制器 | ||
│ ├── helpers 工具方法 | ||
│ ├── models 模型 | ||
│ ├── policies 权限校验 | ||
│ ├── requests 参数校验 | ||
│ ├── services 复杂查询 | ||
│ └── view_models 数据转换 | ||
│ | ||
├── config 配置中心 | ||
│ | ||
├── database 数据库 | ||
│ └── factory 数据 mock | ||
│ | ||
├── middleware 中间件 | ||
│ └── wrapper controller 包裹函数 | ||
│ | ||
├── pkg 项目依赖 | ||
│ | ||
├── public 项目静态文件 | ||
│ | ||
├── resources 前端源码 | ||
│ └── view go 模板文件 | ||
│ | ||
├── routes 路由 | ||
│ └── routes.go 路由注册 | ||
│ └── api.go api 路由注册 | ||
│ └── web.go 页面路由注册 | ||
│ └── named 命名路由模块 | ||
│ | ||
├── storage 存放日志等文件 | ||
│ | ||
├── main.go 项目入口 | ||
│ | ||
├── config.yaml 项目配置 | ||
│ | ||
├── deploy.sh 部署脚本 | ||
│ | ||
└── Makefile Makefile 文件 | ||
</code></pre> | ||
</details> | ||
|
||
## 实现功能 | ||
- [x] CSRF 验证 | ||
- [x] flash 消息闪现 | ||
- [x] 记忆上次表单提交的数据 | ||
- [x] 参数校验模块 | ||
- [x] 命名路由 | ||
- [x] 分页 | ||
- [x] 发送邮件 | ||
- [x] 用户权限模块 | ||
- [x] 日志 | ||
- [x] 前端构建 (typescript、sass ...) | ||
|
||
![1](readme/1.png) | ||
|
||
![2](readme/2.png) | ||
|
||
![3](readme/3.png) | ||
|
||
![4](readme/4.png) | ||
|
||
![5](readme/5.png) | ||
|
||
![6](readme/6.png) | ||
|
||
![7](readme/7.png) | ||
|
||
![8](readme/8.png) | ||
|
||
![9](readme/9.png) | ||
|
||
*** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package auth | ||
|
||
import ( | ||
"errors" | ||
userModel "gin_weibo/app/models/user" | ||
"gin_weibo/config" | ||
|
||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
// SaveCurrentUserToContext : 保存用户数据到 context 中 | ||
func SaveCurrentUserToContext(c *gin.Context) { | ||
user, err := getCurrentUserFromSession(c) | ||
if err != nil { | ||
return | ||
} | ||
|
||
c.Keys[config.AppConfig.ContextCurrentUserDataKey] = user | ||
} | ||
|
||
// GetCurrentUserFromContext : 从 context 中获取用户模型 | ||
func GetCurrentUserFromContext(c *gin.Context) (*userModel.User, error) { | ||
err := errors.New("没有获取到用户数据") | ||
userDataFromContext := c.Keys[config.AppConfig.ContextCurrentUserDataKey] | ||
if userDataFromContext == nil { | ||
return nil, err | ||
} | ||
|
||
user, ok := userDataFromContext.(*userModel.User) | ||
if !ok { | ||
return nil, err | ||
} | ||
|
||
return user, nil | ||
} | ||
|
||
// GetUserFromContextOrDataBase : 从 context 或者从数据库中获取用户模型 | ||
func GetUserFromContextOrDataBase(c *gin.Context, id int) (*userModel.User, error) { | ||
// 当前用户存在并且就是想要获取的那个用户 | ||
currentUser, err := GetCurrentUserFromContext(c) | ||
if currentUser != nil && err == nil { | ||
if int(currentUser.ID) == id { | ||
return currentUser, nil | ||
} | ||
} | ||
|
||
// 获取的是其他指定 id 的用户 | ||
otherUser, err := userModel.Get(id) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return otherUser, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package auth | ||
|
||
import ( | ||
"errors" | ||
userModel "gin_weibo/app/models/user" | ||
"gin_weibo/config" | ||
"gin_weibo/pkg/session" | ||
"gin_weibo/pkg/utils" | ||
"net/url" | ||
"strconv" | ||
|
||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
const ( | ||
rememberFormKey = "remember" // 表单提交时的 form name | ||
rememberCookieName = "remember_me" // 存在 cookie 中的 key name | ||
rememberMaxAge = 88888888 // 过期时间 | ||
) | ||
|
||
// Login 登录 | ||
func Login(c *gin.Context, u *userModel.User) { | ||
session.SetSession(c, config.AppConfig.AuthSessionKey, u.GetIDstring()) | ||
// 记住我 | ||
setRememberTokenInCookie(c, u) | ||
} | ||
|
||
// Logout 登出 | ||
func Logout(c *gin.Context) { | ||
session.DeleteSession(c, config.AppConfig.AuthSessionKey) | ||
delRememberToken(c) | ||
} | ||
|
||
// -------------- private -------------- | ||
// getCurrentUserFromSession : 从 session 中获取用户 | ||
func getCurrentUserFromSession(c *gin.Context) (*userModel.User, error) { | ||
// 从 cookie 中获取 remember me token (如有则自动登录) | ||
rememberMeToken := getRememberTokenFromCookie(c) | ||
if rememberMeToken != "" { | ||
if user, err := userModel.GetByRememberToken(rememberMeToken); err == nil { | ||
Login(c, user) | ||
return user, nil | ||
} | ||
delRememberToken(c) | ||
} | ||
|
||
// 从 session 中获取用户 id | ||
idStr := session.GetSession(c, config.AppConfig.AuthSessionKey) | ||
if idStr == "" { | ||
return nil, errors.New("没有获取到 session") | ||
} | ||
|
||
id, err := strconv.Atoi(idStr) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
user, err := userModel.Get(id) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return user, nil | ||
} | ||
|
||
// -------------- 记住我功能 utils -------------- | ||
func setRememberTokenInCookie(c *gin.Context, u *userModel.User) { | ||
// 记住我 (如果 登录的 PostForm 中有着 remember="on" 说明开启记住我功能) | ||
rememberMe := c.PostForm(rememberFormKey) == "on" | ||
if !rememberMe { | ||
return | ||
} | ||
|
||
// 更新用户的 RememberToken | ||
newToken := string(utils.RandomCreateBytes(10)) | ||
u.RememberToken = newToken | ||
if err := u.Update(false); err != nil { | ||
return | ||
} | ||
|
||
// 写入 cookie | ||
c.SetCookie(rememberCookieName, u.RememberToken, rememberMaxAge, "/", "", false, true) | ||
} | ||
|
||
func getRememberTokenFromCookie(c *gin.Context) string { | ||
if cookie, err := c.Request.Cookie(rememberCookieName); err == nil { | ||
if v, err := url.QueryUnescape(cookie.Value); err == nil { | ||
return v | ||
} | ||
} | ||
|
||
return "" | ||
} | ||
|
||
func delRememberToken(c *gin.Context) { | ||
c.SetCookie(rememberCookieName, "", -1, "/", "", false, true) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
- `resource.go`: 中定义 `create`、`store`、`index`、`show`、`edit`、`update`、`destroy` 系列 controller | ||
- `xx__.go`: 中定义只在当前 `controller package` 中使用的工具方法 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package followers | ||
|
||
import ( | ||
"gin_weibo/app/controllers" | ||
followerModel "gin_weibo/app/models/follower" | ||
userModel "gin_weibo/app/models/user" | ||
"gin_weibo/app/policies" | ||
"gin_weibo/pkg/flash" | ||
"gin_weibo/routes/named" | ||
|
||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
// Store 关注用户 | ||
func Store(c *gin.Context, currentUser *userModel.User) { | ||
id, err := controllers.GetIntParam(c, "id") | ||
if err != nil { | ||
controllers.Render404(c) | ||
return | ||
} | ||
|
||
if ok := policies.UserPolicyFollow(c, currentUser, id); !ok { | ||
return | ||
} | ||
|
||
isFollowing := false | ||
if id != int(currentUser.ID) { | ||
isFollowing = followerModel.IsFollowing(int(currentUser.ID), id) | ||
} | ||
|
||
if !isFollowing { | ||
if err := followerModel.DoFollow(currentUser.ID, uint(id)); err != nil { | ||
flash.NewDangerFlash(c, "关注失败: "+err.Error()) | ||
} | ||
} | ||
|
||
controllers.Redirect(c, named.G("users.show", id)+"?page=1", false) | ||
} | ||
|
||
// Destroy 取消关注用户 | ||
func Destroy(c *gin.Context, currentUser *userModel.User) { | ||
id, err := controllers.GetIntParam(c, "id") | ||
if err != nil { | ||
controllers.Render404(c) | ||
return | ||
} | ||
|
||
if ok := policies.UserPolicyFollow(c, currentUser, id); !ok { | ||
return | ||
} | ||
|
||
isFollowing := false | ||
if id != int(currentUser.ID) { | ||
isFollowing = followerModel.IsFollowing(int(currentUser.ID), id) | ||
} | ||
|
||
if isFollowing { | ||
if err := followerModel.DoUnFollow(currentUser.ID, uint(id)); err != nil { | ||
flash.NewDangerFlash(c, "取消关注失败: "+err.Error()) | ||
} | ||
} | ||
|
||
controllers.Redirect(c, named.G("users.show", id)+"?page=1", false) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package controllers | ||
|
||
import ( | ||
"strconv" | ||
|
||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
// GetIntParam : 从 path params 中获取 int 参数 | ||
// http://a.com/xx/1 => 获取到 int 1 | ||
func GetIntParam(c *gin.Context, key string) (int, error) { | ||
i, err := strconv.Atoi(c.Param(key)) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
return i, nil | ||
} |
Oops, something went wrong.