From 901cbf23bb0cdb7f0909c53c9274b8cce2c5bf9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Tue, 6 Sep 2022 10:45:20 +0800 Subject: [PATCH] =?UTF-8?q?feat(god):=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=A4=A9=E7=A5=9E=E6=A8=A1=E5=BC=8F=E6=89=80=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E6=9C=8D=E5=8A=A1=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/god_mode.go | 20 ++ security/security.go | 13 + service/god_mode.go | 570 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 603 insertions(+) create mode 100644 controller/god_mode.go create mode 100644 service/god_mode.go diff --git a/controller/god_mode.go b/controller/god_mode.go new file mode 100644 index 0000000..7848ba2 --- /dev/null +++ b/controller/god_mode.go @@ -0,0 +1,20 @@ +package controller + +import ( + "electricity_bill_calc/response" + "electricity_bill_calc/security" + + "github.com/gin-gonic/gin" +) + +func InitializeGodModeController(router *gin.Engine) { + gmR := router.Group("/gm") + { + gmR.DELETE("/report/:rid/summary", security.SingularityAuthorize, gmResetReportSummary) + } +} + +func gmResetReportSummary(c *gin.Context) { + result := response.NewResult(c) + result.Success("指定报表的园区总览已经重置。") +} diff --git a/security/security.go b/security/security.go index 7682c3f..c09ac08 100644 --- a/security/security.go +++ b/security/security.go @@ -76,3 +76,16 @@ func OPSAuthorize(c *gin.Context) { } c.Next() } + +// 用于对用户会话进行是否核心运维用户的判断 +// ! 通过该中间件以后,是可以保证上下文中一定具有用户会话信息的。 +func SingularityAuthorize(c *gin.Context) { + session, exists := c.Get("session") + if !exists { + c.AbortWithStatus(http.StatusForbidden) + } + if sess, ok := session.(*model.Session); !ok || sess.Type != model.USER_TYPE_OPS || sess.Uid != "000" { + c.AbortWithStatus(http.StatusForbidden) + } + c.Next() +} diff --git a/service/god_mode.go b/service/god_mode.go new file mode 100644 index 0000000..d1ef283 --- /dev/null +++ b/service/god_mode.go @@ -0,0 +1,570 @@ +package service + +import ( + "electricity_bill_calc/exceptions" + "electricity_bill_calc/global" + "electricity_bill_calc/model" + "time" + + "github.com/samber/lo" + "github.com/shopspring/decimal" + "xorm.io/builder" + "xorm.io/xorm" + "xorm.io/xorm/schemas" +) + +type _GodModeService struct{} + +var GodModeService _GodModeService + +// 从此处开始为删除报表相关的部分 + +func (_GodModeService) resetReportIndex(tx *xorm.Session, reportId string) (bool, error) { + var report = new(model.Report) + has, err := tx.ID(reportId).NoAutoCondition().Get(report) + if err != nil { + tx.Rollback() + return false, err + } + if !has { + tx.Rollback() + return false, exceptions.NewNotFoundError("指定报表索引未找到。") + } + report.StepState.Summary = false + report.StepState.WillDiluted = false + report.StepState.Submeter = false + report.StepState.Calculate = false + report.StepState.Preview = false + report.StepState.Publish = false + report.Published = false + report.PublishedAt = nil + report.Withdraw = model.REPORT_NOT_WITHDRAW + report.LastWithdrawAppliedAt = nil + report.LastWithdrawAuditAt = nil + + affected, err := tx. + ID(reportId). + MustCols( + "step_state", + "published", + "published_at", + "withdraw", + "last_withdraw_applied_at", + "last_withdraw_audit_at", + ). + Update(report) + if err != nil { + tx.Rollback() + return false, err + } + return affected > 0, err +} + +func (_GodModeService) resetReportSummary(tx *xorm.Session, reportId string) (bool, error) { + var summary = &model.ReportSummary{ + ReportId: reportId, + } + rows, err := tx.ID(reportId).AllCols().NoAutoCondition().Update(summary) + if err != nil { + tx.Rollback() + return false, err + } + return rows > 0, err +} + +func (_GodModeService) flushReportMaintenances(tx *xorm.Session, reportId string) (bool, error) { + rows, err := tx. + Where(builder.Eq{"report_id": reportId}). + Delete(new(model.WillDilutedFee)) + if err != nil { + tx.Rollback() + return false, err + } + return rows >= 0, err +} + +func (_GodModeService) resetEndUserRecords(tx *xorm.Session, reportId string) (bool, error) { + var records = make([]*model.EndUserDetail, 0) + err := tx.Where(builder.Eq{"report_id": reportId}).Find(&records) + if err != nil { + tx.Rollback() + return false, err + } + for _, u := range records { + u.CurrentPeriodOverall = decimal.Zero + u.CurrentPeriodCritical = decimal.Zero + u.CurrentPeriodPeak = decimal.Zero + u.CurrentPeriodFlat = decimal.Zero + u.CurrentPeriodValley = decimal.Zero + u.AdjustOverall = decimal.Zero + u.AdjustCritical = decimal.Zero + u.AdjustPeak = decimal.Zero + u.AdjustFlat = decimal.Zero + u.AdjustValley = decimal.Zero + u.Overall.Valid = false + u.OverallFee.Valid = false + u.OverallProportion = decimal.Zero + u.Critical.Valid = false + u.CriticalFee.Valid = false + u.Peak.Valid = false + u.PeakFee.Valid = false + u.Flat.Valid = false + u.FlatFee.Valid = false + u.Valley.Valid = false + u.ValleyFee.Valid = false + u.BasicFeeDiluted.Valid = false + u.AdjustFeeDiluted.Valid = false + u.LossDiluted.Valid = false + u.LossFeeDiluted.Valid = false + u.MaintenanceFeeDiluted.Valid = false + u.FinalDiluted.Valid = false + u.FinalCharge.Valid = false + + affected, err := tx. + ID(schemas.PK{u.ReportId, u.ParkId, u.MeterId}). + MustCols( + "current_period_overall", + "current_period_critical", + "current_period_peak", + "current_period_flat", + "current_period_valley", + "adjust_overall", + "adjust_critical", + "adjust_peak", + "adjust_flat", + "adjust_valley", + "overall", + "overall_fee", + "overall_proportion", + "critical", + "critical_fee", + "peak", + "peak_fee", + "flat", + "flat_fee", + "valley", + "valley_fee", + "baseic_fee_diluted", + "adjust_fee_diluted", + "loss_diluted", + "loss_fee_diluted", + "maintenance_fee_diluted", + "public_consumption_diluted", + "final_diluted", + "final_charge", + ). + Update(&u) + if err != nil { + tx.Rollback() + return false, err + } + if affected == 0 { + tx.Rollback() + return false, err + } + } + + return true, nil +} + +type ReportPeriod struct { + Id string + Period time.Time +} + +func (_GodModeService) isTheLatestReport(reportId string) (bool, error) { + var report = new(model.Report) + has, err := global.DBConn.ID(reportId).NoAutoCondition().Get(report) + if err != nil { + return false, err + } + if !has { + return false, exceptions.NewNotFoundError("指定报表索引未找到。") + } + var reports = make([]ReportPeriod, 0) + err = global.DBConn. + Table(new(model.Report)). + Where(builder.Eq{"park_id": report.ParkId}). + Find(&reports) + if err != nil { + return false, err + } + maxReport := lo.MaxBy(reports, func(a, b ReportPeriod) bool { + return a.Period.After(b.Period) + }) + return maxReport.Id == reportId, nil +} + +func (_GodModeService) forceDeleteReport(tx *xorm.Session, reportId string) (bool, error) { + _, err := tx.Exec("delete from end_user_detail where report_id=?", reportId) + if err != nil { + tx.Rollback() + return false, err + } + _, err = tx.Exec("delete from will_diluted_fee where report_id=?", reportId) + if err != nil { + tx.Rollback() + return false, err + } + _, err = tx.Exec("delete from report_summary where report_id=?", reportId) + if err != nil { + tx.Rollback() + return false, err + } + _, err = tx.Exec("delete from report where report_id=?", reportId) + if err != nil { + tx.Rollback() + return false, err + } + return true, nil +} + +func (g _GodModeService) ClearReportSummary(reportId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.resetReportSummary(tx, reportId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) ClearReportMaintenances(reportId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.flushReportMaintenances(tx, reportId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) ResetEndUserRegisterRecords(reportId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.resetEndUserRecords(tx, reportId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) ResetReport(reportId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + var result = false + r, err := g.resetEndUserRecords(tx, reportId) + if err != nil { + return false, err + } + result = result && r + r, err = g.flushReportMaintenances(tx, reportId) + if err != nil { + return false, err + } + result = result && r + r, err = g.resetReportSummary(tx, reportId) + if err != nil { + return false, err + } + result = result && r + r, err = g.resetReportIndex(tx, reportId) + if err != nil { + return false, err + } + result = result && r + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) DeleteReport(reportId string) (bool, error) { + isLatest, err := g.isTheLatestReport(reportId) + if err != nil { + return false, err + } + if !isLatest { + return false, exceptions.NewImproperOperateError("不能删除非最新期数的报表。") + } + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.forceDeleteReport(tx, reportId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +// 从此处开始为删除园区相关的内容部分 + +func (_GodModeService) deleteSpecificMaintenance(tx *xorm.Session, parkId, maintenanceId string) (bool, error) { + res, err := tx.Exec("delete from maintenance_fee where park_id=? and id=?", parkId, maintenanceId) + if err != nil { + tx.Rollback() + return false, nil + } + if rows, err := res.RowsAffected(); err != nil { + tx.Rollback() + return false, err + } else { + return rows >= 0, err + } +} + +func (_GodModeService) deleteAllMaintenance(tx *xorm.Session, parkId string) (bool, error) { + res, err := tx.Exec("delete from maintenance_fee where park_id=?", parkId) + if err != nil { + tx.Rollback() + return false, nil + } + if rows, err := res.RowsAffected(); err != nil { + tx.Rollback() + return false, err + } else { + return rows >= 0, err + } +} + +func (_GodModeService) deleteAllMeters(tx *xorm.Session, parkId string) (bool, error) { + res, err := tx.Exec("delete from meter_04kv where park_id=?", parkId) + if err != nil { + tx.Rollback() + return false, nil + } + if rows, err := res.RowsAffected(); err != nil { + tx.Rollback() + return false, err + } else { + return rows >= 0, err + } +} + +func (_GodModeService) deletePark(tx *xorm.Session, parkId string) (bool, error) { + res, err := tx.Exec("delete from park where id=?", parkId) + if err != nil { + tx.Rollback() + return false, nil + } + if rows, err := res.RowsAffected(); err != nil { + tx.Rollback() + return false, err + } else { + return rows >= 0, err + } +} + +func (g _GodModeService) RemoveSpecificMaintenance(parkId, maintenanceId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.deleteSpecificMaintenance(tx, parkId, maintenanceId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) RemoveAllMaintenance(parkId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.deleteAllMaintenance(tx, parkId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) RemoveAllMeters(parkId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.deleteAllMeters(tx, parkId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +func (g _GodModeService) erasePark(tx *xorm.Session, parkId string) (bool, error) { + var reportIds = make([]string, 0) + err := tx. + Table(new(model.Report)). + Where(builder.Eq{"park_id": parkId}). + NoAutoCondition(). + Select("id"). + Find(&reportIds) + if err != nil { + tx.Rollback() + return false, err + } + var result = false + for _, id := range reportIds { + r, err := g.forceDeleteReport(tx, id) + if err != nil { + return false, err + } + result = result && r + } + r, err := g.deleteAllMaintenance(tx, parkId) + if err != nil { + return false, err + } + result = result && r + r, err = g.deleteAllMeters(tx, parkId) + if err != nil { + return false, err + } + result = result && r + r, err = g.deletePark(tx, parkId) + if err != nil { + return false, err + } + result = result && r + + return result, err +} + +func (g _GodModeService) RemovePark(parkId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + result, err := g.erasePark(tx, parkId) + if err != nil { + return false, err + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +} + +// 从此处开始为删除用户相关的部分 + +func (g _GodModeService) DeleteUser(userId string) (bool, error) { + tx := global.DBConn.NewSession() + if err := tx.Begin(); err != nil { + return false, err + } + defer tx.Close() + + var parkIds = make([]string, 0) + err := tx. + Table(new(model.Park)). + Where(builder.Eq{"user_id": userId}). + NoAutoCondition(). + Select("id"). + Find(&parkIds) + if err != nil { + tx.Rollback() + return false, err + } + + var result = false + for _, p := range parkIds { + r, err := g.erasePark(tx, p) + if err != nil { + return false, err + } + result = result && r + } + + res, err := tx.Exec("delete from user where id=?", userId) + if err != nil { + tx.Rollback() + return false, err + } + if rows, err := res.RowsAffected(); err != nil { + tx.Rollback() + return false, err + } else { + result = result && (rows >= 0) + } + + err = tx.Commit() + if err != nil { + tx.Rollback() + return false, err + } + return result, nil +}