This commit is contained in:
laodaming 2023-11-10 16:31:10 +08:00
parent ad9d89a1bb
commit 41e650488d
30 changed files with 1 additions and 774 deletions

View File

@ -1,25 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
"time"
)
// ldap_apis
type LdapApis struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
Method *string `gorm:"default:'';" json:"method"` //
Path *string `gorm:"default:'';" json:"path"` //
Category *string `gorm:"default:'';" json:"category"` //
Remark *string `gorm:"default:'';" json:"remark"` //
Creator *string `gorm:"default:'';" json:"creator"` //
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
Dtime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"dtime"` //
}
type LdapApisModel struct {
db *gorm.DB
name string
}
func NewLdapApisModel(db *gorm.DB) *LdapApisModel { return &LdapApisModel{db: db, name: "ldap_apis"} }

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,25 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
)
// ldap_casbin_rule 规则权限表
type LdapCasbinRule struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
Ptype *string `gorm:"default:'';" json:"ptype"` //
V0 *string `gorm:"default:'';" json:"v0"` //
V1 *string `gorm:"default:'';" json:"v1"` //
V2 *string `gorm:"default:'';" json:"v2"` //
V3 *string `gorm:"default:'';" json:"v3"` //
V4 *string `gorm:"default:'';" json:"v4"` //
V5 *string `gorm:"default:'';" json:"v5"` //
}
type LdapCasbinRuleModel struct {
db *gorm.DB
name string
}
func NewLdapCasbinRuleModel(db *gorm.DB) *LdapCasbinRuleModel {
return &LdapCasbinRuleModel{db: db, name: "ldap_casbin_rule"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,22 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
)
// ldap_department 部门表
type LdapDepartment struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
Source *string `gorm:"default:'';" json:"source"` //
AppId *string `gorm:"default:'';" json:"app_id"` //
Name *string `gorm:"default:'';" json:"name"` //
DepartmentId *string `gorm:"default:'';" json:"department_id"` //
}
type LdapDepartmentModel struct {
db *gorm.DB
name string
}
func NewLdapDepartmentModel(db *gorm.DB) *LdapDepartmentModel {
return &LdapDepartmentModel{db: db, name: "ldap_department"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,19 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
)
// ldap_group_users
type LdapGroupUsers struct {
GroupId *int64 `gorm:"default:0;" json:"group_id"` // 分组id
UserId *int64 `gorm:"default:0;" json:"user_id"` // user表id
}
type LdapGroupUsersModel struct {
db *gorm.DB
name string
}
func NewLdapGroupUsersModel(db *gorm.DB) *LdapGroupUsersModel {
return &LdapGroupUsersModel{db: db, name: "ldap_group_users"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,31 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
"time"
)
// ldap_groups
type LdapGroups struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
GroupName *string `gorm:"default:'';" json:"group_name"` //
Remark *string `gorm:"default:'';" json:"remark"` //
Creator *string `gorm:"default:'';" json:"creator"` //
GroupType *string `gorm:"default:'';" json:"group_type"` //
ParentId *int64 `gorm:"default:0;" json:"parent_id"` //
DeptId *string `gorm:"default:'';" json:"dept_id"` //
DeptParentId *string `gorm:"default:'';" json:"dept_parent_id"` //
GroupDn *string `gorm:"default:'';" json:"group_dn"` //
SyncState *int64 `gorm:"default:0;" json:"sync_state"` //
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
Dtime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"dtime"` //
}
type LdapGroupsModel struct {
db *gorm.DB
name string
}
func NewLdapGroupsModel(db *gorm.DB) *LdapGroupsModel {
return &LdapGroupsModel{db: db, name: "ldap_groups"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,29 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
"time"
)
// ldap_menus
type LdapMenus struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
Name *string `gorm:"default:'';" json:"name"` //
Title *string `gorm:"default:'';" json:"title"` //
Icon *string `gorm:"default:'';" json:"icon"` //
Path *string `gorm:"default:'';" json:"path"` //
Sort *int64 `gorm:"default:999;" json:"sort"` //
Status *int64 `gorm:"default:1;" json:"status"` //
Creator *string `gorm:"default:'';" json:"creator"` //
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
Dtime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"dtime"` //
}
type LdapMenusModel struct {
db *gorm.DB
name string
}
func NewLdapMenusModel(db *gorm.DB) *LdapMenusModel {
return &LdapMenusModel{db: db, name: "ldap_menus"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,19 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
)
// ldap_role_menus
type LdapRoleMenus struct {
MenuId *int64 `gorm:"default:0;" json:"menu_id"` // 菜单id
RoleId *int64 `gorm:"default:0;" json:"role_id"` // 角色id
}
type LdapRoleMenusModel struct {
db *gorm.DB
name string
}
func NewLdapRoleMenusModel(db *gorm.DB) *LdapRoleMenusModel {
return &LdapRoleMenusModel{db: db, name: "ldap_role_menus"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,28 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
"time"
)
// ldap_roles
type LdapRoles struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
Name *string `gorm:"unique_key;default:'';" json:"name"` //
Keyword *string `gorm:"unique_key;default:'';" json:"keyword"` //
Remark *string `gorm:"default:'';" json:"remark"` //
Status *int64 `gorm:"default:1;" json:"status"` //
Sort *int64 `gorm:"default:999;" json:"sort"` //
Creator *string `gorm:"default:'';" json:"creator"` //
Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` //
Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` //
Dtime *time.Time `gorm:"index;default:'0000-00-00 00:00:00';" json:"dtime"` //
}
type LdapRolesModel struct {
db *gorm.DB
name string
}
func NewLdapRolesModel(db *gorm.DB) *LdapRolesModel {
return &LdapRolesModel{db: db, name: "ldap_roles"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -1,19 +0,0 @@
package gmodel
import (
"gorm.io/gorm"
)
// ldap_user_roles
type LdapUserRoles struct {
RoleId *int64 `gorm:"default:0;" json:"role_id"` // 角色id
UserId *int64 `gorm:"default:0;" json:"user_id"` // 用户id
}
type LdapUserRolesModel struct {
db *gorm.DB
name string
}
func NewLdapUserRolesModel(db *gorm.DB) *LdapUserRolesModel {
return &LdapUserRolesModel{db: db, name: "ldap_user_roles"}
}

View File

@ -1,2 +0,0 @@
package gmodel
// TODO: 使用model的属性做你想做的

View File

@ -8,11 +8,7 @@ import (
// ldap_users
type LdapUsers struct {
Id int64 `gorm:"primary_key;default:0;auto_increment;" json:"id"` //
UserId *string `gorm:"default:'';" json:"user_id"` //
OpenId *string `gorm:"default:'';" json:"open_id"` //
UnionId *string `gorm:"default:'';" json:"union_id"` //
Name *string `gorm:"default:'';" json:"name"` //
EnName *string `gorm:"default:'';" json:"en_name"` //
Nickname *string `gorm:"default:'';" json:"nickname"` //
Email *string `gorm:"default:'';" json:"email"` //
EnterpriseEmail *string `gorm:"default:'';" json:"enterprise_email"` //
@ -20,14 +16,8 @@ type LdapUsers struct {
Mobile *string `gorm:"default:'';" json:"mobile"` //
Gender *int64 `gorm:"default:0;" json:"gender"` // 性别 0未知 1男 2女
Avatar *string `gorm:"default:'';" json:"avatar"` //
IsFrozen *int64 `gorm:"default:0;" json:"is_frozen"` // 是否冻结 0否1是
IsResigned *int64 `gorm:"default:0;" json:"is_resigned"` // 是否离职 0否 1是
IsActivated *int64 `gorm:"default:0;" json:"is_activated"` // 是否激活 0否1是
IsExited *int64 `gorm:"default:0;" json:"is_exited"` // 是否退出 0否1是
IsUnjoin *int64 `gorm:"default:0;" json:"is_unjoin"` // 是否未加入 0否1是
Status *int64 `gorm:"default:1;" json:"status"` // 状态 0禁止 1正常
Departmentids *string `gorm:"default:'';" json:"departmentIds"` //
WorkStation *string `gorm:"default:'';" json:"work_station"` //
EmployeeNo *string `gorm:"default:'';" json:"employee_no"` //
EmployeeType *int64 `gorm:"default:0;" json:"employee_type"` // 1正式员工 2实习生 3外包4劳务 5顾问
UserDn *string `gorm:"default:'';" json:"user_dn"` //
JoinTime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"join_time"` //

View File

@ -121,13 +121,7 @@ type AllModelsGen struct {
FsZipCode *FsZipCodeModel // fs_zip_code 邮编表
LdapApis *LdapApisModel // ldap_apis
LdapCasbinRule *LdapCasbinRuleModel // ldap_casbin_rule 规则权限表
LdapDepartment *LdapDepartmentModel // ldap_department 部门表
LdapGroupUsers *LdapGroupUsersModel // ldap_group_users
LdapGroups *LdapGroupsModel // ldap_groups
LdapMenus *LdapMenusModel // ldap_menus
LdapRoleMenus *LdapRoleMenusModel // ldap_role_menus
LdapRoles *LdapRolesModel // ldap_roles
LdapUserRoles *LdapUserRolesModel // ldap_user_roles
LdapUsers *LdapUsersModel // ldap_users
}
@ -251,13 +245,7 @@ func NewAllModels(gdb *gorm.DB) *AllModelsGen {
FsZipCode: NewFsZipCodeModel(gdb),
LdapApis: NewLdapApisModel(gdb),
LdapCasbinRule: NewLdapCasbinRuleModel(gdb),
LdapDepartment: NewLdapDepartmentModel(gdb),
LdapGroupUsers: NewLdapGroupUsersModel(gdb),
LdapGroups: NewLdapGroupsModel(gdb),
LdapMenus: NewLdapMenusModel(gdb),
LdapRoleMenus: NewLdapRoleMenusModel(gdb),
LdapRoles: NewLdapRolesModel(gdb),
LdapUserRoles: NewLdapUserRolesModel(gdb),
LdapUsers: NewLdapUsersModel(gdb),
}
return models

View File

@ -1,10 +0,0 @@
Name: feishu-sync
Host: 0.0.0.0
Port: 9925
Timeout: 15000 #服务超时时间(毫秒)
SourceMysql: fsreaderwriter:XErSYmLELKMnf3Dh@tcp(fusen.cdmigcvz3rle.us-east-2.rds.amazonaws.com:3306)/fusen
SourceRabbitMq: ""
Auth:
AccessSecret: fusen2023
AccessExpire: 2592000
RefreshAfter: 1592000

View File

@ -1,37 +0,0 @@
package main
import (
"flag"
"fmt"
"net/http"
"time"
"fusenapi/utils/auth"
"fusenapi/utils/fsconfig"
"fusenapi/server/feishu-sync/internal/config"
"fusenapi/server/feishu-sync/internal/handler"
"fusenapi/server/feishu-sync/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
var configFile = flag.String("f", "etc/feishu-sync.yaml", "the config file")
func main() {
flag.Parse()
var c config.Config
fsconfig.StartNacosConfig(*configFile, &c, nil)
c.Timeout = int64(time.Second * 15)
server := rest.MustNewServer(c.RestConf, rest.WithCustomCors(auth.FsCors, func(w http.ResponseWriter) {
}))
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}

View File

@ -1,20 +0,0 @@
package config
import (
"fusenapi/server/feishu-sync/internal/types"
"github.com/zeromicro/go-zero/rest"
)
type Config struct {
rest.RestConf
SourceMysql string
Auth types.Auth
SourceRabbitMq string
FeiShu struct {
ApiHost string
EncryptKey string
VerificationToken string
AppId string
AppSecret string
}
}

View File

@ -1,22 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"fusenapi/server/feishu-sync/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/api/feishu/webhook",
Handler: WebhookHandler(serverCtx),
},
},
)
}

View File

@ -1,15 +0,0 @@
package handler
import (
"fusenapi/server/feishu-sync/internal/logic"
"fusenapi/server/feishu-sync/internal/svc"
"net/http"
)
func WebhookHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 创建一个业务逻辑层实例
l := logic.NewWebhookLogic(r.Context(), svcCtx)
l.Webhook(w, r)
}
}

View File

@ -1,144 +0,0 @@
package logic
import (
"encoding/json"
"fusenapi/model/gmodel"
"strconv"
"strings"
"time"
)
type UserWebhookMsg struct {
Schema string `json:"schema"`
Header struct {
EventId string `json:"event_id"`
EventType string `json:"event_type"`
CreateTime string `json:"create_time"`
Token string `json:"token"`
AppId string `json:"app_id"`
TenantKey string `json:"tenant_key"`
} `json:"header"`
Event struct {
Object struct {
OpenId string `json:"open_id"`
UnionId string `json:"union_id"`
UserId string `json:"user_id"`
Name string `json:"name"`
EnName string `json:"en_name"`
Nickname string `json:"nickname"`
Email string `json:"email"`
EnterpriseEmail string `json:"enterprise_email"`
JobTitle string `json:"job_title"`
Mobile string `json:"mobile"`
Gender int64 `json:"gender"`
Avatar struct {
Avatar72 string `json:"avatar_72"`
Avatar240 string `json:"avatar_240"`
Avatar640 string `json:"avatar_640"`
AvatarOrigin string `json:"avatar_origin"`
} `json:"avatar"`
Status struct {
IsFrozen bool `json:"is_frozen"`
IsResigned bool `json:"is_resigned"`
IsActivated bool `json:"is_activated"`
IsExited bool `json:"is_exited"`
IsUnjoin bool `json:"is_unjoin"`
} `json:"status"`
DepartmentIds []string `json:"department_ids"`
LeaderUserId string `json:"leader_user_id"`
City string `json:"city"`
Country string `json:"country"`
WorkStation string `json:"work_station"`
Joint64ime int64 `json:"join_time"`
EmployeeNo string `json:"employee_no"`
EmployeeType int64 `json:"employee_type"`
Orders []struct {
DepartmentId string `json:"department_id"`
UserOrder int64 `json:"user_order"`
DepartmentOrder int64 `json:"department_order"`
IsPrimaryDept bool `json:"is_primary_dept"`
} `json:"orders"`
CustomAttrs []struct {
Type string `json:"type"`
Id string `json:"id"`
Value struct {
Text string `json:"text"`
Url string `json:"url"`
PcUrl string `json:"pc_url"`
OptionId string `json:"option_id"`
OptionValue string `json:"option_value"`
Name string `json:"name"`
PictureUrl string `json:"picture_url"`
GenericUser struct {
Id string `json:"id"`
Type int64 `json:"type"`
} `json:"generic_user"`
} `json:"value"`
} `json:"custom_attrs"`
JobLevelId string `json:"job_level_id"`
JobFamilyId string `json:"job_family_id"`
DottedLineLeaderUserIds []string `json:"dotted_line_leader_user_ids"`
} `json:"object"`
} `json:"event"`
}
// 员工增删改信息
func (l *WebhookLogic) OnUserChange(data []byte) error {
var msg UserWebhookMsg
if err := json.Unmarshal(data, &msg); err != nil {
return err
}
isFrozen := int64(0)
if msg.Event.Object.Status.IsFrozen {
isFrozen = 1
}
isResigned := int64(0)
if msg.Event.Object.Status.IsResigned {
isResigned = 1
}
isActivated := int64(0)
if msg.Event.Object.Status.IsActivated {
isActivated = 1
}
isExited := int64(0)
if msg.Event.Object.Status.IsExited {
isExited = 1
}
isUnjoin := int64(0)
if msg.Event.Object.Status.IsUnjoin {
isUnjoin = 1
}
feiShuMsgCreateTimeInt64, err := strconv.ParseInt(msg.Header.CreateTime, 10, 64)
if err != nil {
return err
}
feiShuMsgCreateTime := time.UnixMilli(feiShuMsgCreateTimeInt64)
departmentIds := strings.Join(msg.Event.Object.DepartmentIds, ",")
joinTime := time.Unix(msg.Event.Object.Joint64ime, 0)
return l.svcCtx.AllModels.LdapUsers.CreateOrUpdate(l.ctx, msg.Event.Object.OpenId, &gmodel.LdapUsers{
UserId: &msg.Event.Object.UserId,
OpenId: &msg.Event.Object.OpenId,
UnionId: &msg.Event.Object.UnionId,
Name: &msg.Event.Object.Name,
EnName: &msg.Event.Object.EnName,
Nickname: &msg.Event.Object.Nickname,
Email: &msg.Event.Object.Email,
EnterpriseEmail: &msg.Event.Object.EnterpriseEmail,
JobTitle: &msg.Event.Object.JobTitle,
Mobile: &msg.Event.Object.Mobile,
Gender: &msg.Event.Object.Gender,
Avatar: &msg.Event.Object.Avatar.AvatarOrigin,
IsFrozen: &isFrozen,
IsResigned: &isResigned,
IsActivated: &isActivated,
IsExited: &isExited,
IsUnjoin: &isUnjoin,
Departmentids: &departmentIds,
WorkStation: &msg.Event.Object.WorkStation,
EmployeeNo: &msg.Event.Object.EmployeeNo,
EmployeeType: &msg.Event.Object.EmployeeType,
JoinTime: &joinTime,
Ctime: &feiShuMsgCreateTime,
Utime: &feiShuMsgCreateTime,
})
}

View File

@ -1,150 +0,0 @@
package logic
import (
"context"
"encoding/json"
"fusenapi/model/gmodel"
"fusenapi/server/feishu-sync/internal/svc"
"fusenapi/utils/feishu"
"github.com/zeromicro/go-zero/core/logx"
"io"
"net/http"
"strconv"
"time"
)
type WebhookLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewWebhookLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WebhookLogic {
return &WebhookLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
type EncryptWebhookMsg struct {
Encrypt string `json:"encrypt"` //加密的消息
}
type WebhookMsg struct {
Type string `json:"type"`
Challenge string `json:"challenge"`
Header map[string]interface{} `json:"header"`
}
// webhook消息事件header(body参数)基础信息
type BaseWebhookMsgHeaderType struct {
EventId string `json:"event_id"` //事件id(可作为消息唯一性确认)
EventType string `json:"event_type"` //事件类型
CreateTime string `json:"create_time"` //创建时间
Token string `json:"token"` //事件token
AppId string `json:"app_id"` //app id
TenantKey string `json:"tenant_key"` //租户key
}
func (l *WebhookLogic) Webhook(w http.ResponseWriter, r *http.Request) {
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
logx.Error("读取请求body失败", err)
return
}
defer r.Body.Close()
//计算签名
timestamp := r.Header.Get("X-Lark-Request-Timestamp")
nonce := r.Header.Get("X-Lark-Request-Nonce")
signature := r.Header.Get("X-Lark-Signature")
sign := feishu.CalculateFeiShuWebhookSignature(timestamp, nonce, l.svcCtx.Config.FeiShu.EncryptKey, bodyBytes)
if signature != sign {
logx.Error("非法的消息,签名验证不通过", sign, "====", signature)
return
}
var encryptMsg EncryptWebhookMsg
if err = json.Unmarshal(bodyBytes, &encryptMsg); err != nil {
logx.Error("反序列化body失败", err, "body数据:", string(bodyBytes))
return
}
if encryptMsg.Encrypt == "" {
logx.Error("消息加密信息是空的")
return
}
//解密
realMsgBytes, err := feishu.DecryptFeiShuWebhookMsg(encryptMsg.Encrypt, l.svcCtx.Config.FeiShu.EncryptKey)
if err != nil {
logx.Error(err)
return
}
//如果只是验证http连接的消息
var webhookMsg WebhookMsg
if err = json.Unmarshal(realMsgBytes, &webhookMsg); err != nil {
logx.Error("反序列化请求body失败", err, "解密数据:", string(realMsgBytes))
return
}
//验证连接(直接返回)
if webhookMsg.Type == "url_verification" {
challengeRsp := map[string]string{
"challenge": webhookMsg.Challenge,
}
b, _ := json.Marshal(challengeRsp)
w.Write(b)
return
}
bodyHeaderByte, err := json.Marshal(webhookMsg.Header)
if err != nil {
logx.Error("序列化请求体header失败:", err)
return
}
var msgHeader BaseWebhookMsgHeaderType
if err = json.Unmarshal(bodyHeaderByte, &msgHeader); err != nil {
logx.Error("反序列化请求体中的header失败", err)
return
}
httpHeaderBytes, _ := json.Marshal(r.Header)
httpHeaderStr := string(httpHeaderBytes)
//解密后的数据
decryptMsgStr := string(realMsgBytes)
feiShuMsgCreateTimeInt64, err := strconv.ParseInt(msgHeader.CreateTime, 10, 64)
if err != nil {
logx.Error("解析消息时间错误:", err)
return
}
feiShuMsgCreateTime := time.UnixMilli(feiShuMsgCreateTimeInt64)
now := time.Now().UTC()
//把事件加入日志
err = l.svcCtx.AllModels.FsFeishuWebhookLog.Create(l.ctx, &gmodel.FsFeishuWebhookLog{
AppId: &msgHeader.AppId,
EventId: &msgHeader.EventId,
EventType: &msgHeader.EventType,
HttpHeader: &httpHeaderStr,
Data: &encryptMsg.Encrypt,
DecryptData: &decryptMsgStr,
MsgCtime: &feiShuMsgCreateTime,
Ctime: &now,
})
if err != nil {
logx.Error("保存webhook消息日志失败:", err)
}
switch msgHeader.EventType {
case "contact.department.created_v3": //部门新建
case "contact.department.deleted_v3": //部门删除
case "contact.department.updated_v3": //部门信息变化
case "contact.employee_type_enum.actived_v3": //启动人员类型事件
case "contact.employee_type_enum.created_v3": //新建人员类型事件
case "contact.employee_type_enum.deactivated_v3": //停用人员类型事件
case "contact.employee_type_enum.deleted_v3": //删除人员类型事件
case "contact.employee_type_enum.updated_v3": //修改人员类型名称事件
case "contact.user.created_v3": //员工入职
err = l.OnUserChange(realMsgBytes)
case "contact.user.deleted_v3": //员工离职
err = l.OnUserChange(realMsgBytes)
case "contact.user.updated_v3": //员工信息变化
err = l.OnUserChange(realMsgBytes)
}
if err != nil {
logx.Error("处理事件错误:", err)
}
return
}

View File

@ -1,27 +0,0 @@
package svc
import (
"fusenapi/initalize"
"fusenapi/model/gmodel"
"fusenapi/server/feishu-sync/internal/config"
"gorm.io/gorm"
)
type ServiceContext struct {
Config config.Config
MysqlConn *gorm.DB
AllModels *gmodel.AllModelsGen
RabbitMq *initalize.RabbitMqHandle
}
func NewServiceContext(c config.Config) *ServiceContext {
conn := initalize.InitMysql(c.SourceMysql)
return &ServiceContext{
Config: c,
MysqlConn: conn,
AllModels: gmodel.NewAllModels(initalize.InitMysql(c.SourceMysql)),
RabbitMq: initalize.InitRabbitMq(c.SourceRabbitMq, nil),
}
}

View File

@ -1,75 +0,0 @@
// Code generated by goctl. DO NOT EDIT.
package types
import (
"fusenapi/utils/basic"
)
type Request struct {
}
type Response struct {
Code int `json:"code"`
Message string `json:"msg"`
Data interface{} `json:"data"`
}
type Auth struct {
AccessSecret string `json:"accessSecret"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type File struct {
Filename string `fsfile:"filename"`
Header map[string][]string `fsfile:"header"`
Size int64 `fsfile:"size"`
Data []byte `fsfile:"data"`
}
type Meta struct {
TotalCount int64 `json:"total_count"`
PageCount int64 `json:"page_count"`
CurrentPage int `json:"current_page"`
PerPage int `json:"per_page"`
}
// Set 设置Response的Code和Message值
func (resp *Response) Set(Code int, Message string) *Response {
return &Response{
Code: Code,
Message: Message,
}
}
// Set 设置整个Response
func (resp *Response) SetWithData(Code int, Message string, Data interface{}) *Response {
return &Response{
Code: Code,
Message: Message,
Data: Data,
}
}
// SetStatus 设置默认StatusResponse(内部自定义) 默认msg, 可以带data, data只使用一个参数
func (resp *Response) SetStatus(sr *basic.StatusResponse, data ...interface{}) *Response {
newResp := &Response{
Code: sr.Code,
}
if len(data) == 1 {
newResp.Data = data[0]
}
return newResp
}
// SetStatusWithMessage 设置默认StatusResponse(内部自定义) 非默认msg, 可以带data, data只使用一个参数
func (resp *Response) SetStatusWithMessage(sr *basic.StatusResponse, msg string, data ...interface{}) *Response {
newResp := &Response{
Code: sr.Code,
Message: msg,
}
if len(data) == 1 {
newResp.Data = data[0]
}
return newResp
}

View File

@ -1,16 +0,0 @@
syntax = "v1"
info (
title: "飞书同步服务"// TODO: add title
desc: // TODO: add description
author: ""
email: ""
)
import "basic.api"
service feishu-sync {
//飞书ticket webhook事件接口
@handler WebhookHandler
post /api/feishu/webhook(request) returns (response);
}