Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion conf/email-template/cla-updated.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Dear {{.AdminName}},

A new version of CLA is published. Please login to the CLA management system to see the details.

The CLA management system login URL is {{.URLOfCLAPlatform}}.
The CLA management system login URL is {{.URLOfCLAPlatform}}

Have questions or need help? Just reply to this email and the {{.Org}} Community Support Team will help you sort it out.

Expand Down
4 changes: 0 additions & 4 deletions models/individual_signing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ func TestIndividualSignedJSONSerialization(t *testing.T) {
Type: "corporation",
Signed: true,
VersionMatched: true,
Status: "valid",
},
want: map[string]interface{}{
"type": "corporation",
Expand All @@ -42,7 +41,6 @@ func TestIndividualSignedJSONSerialization(t *testing.T) {
Type: "corporation",
Signed: true,
VersionMatched: false,
Status: "expired",
},
want: map[string]interface{}{
"type": "corporation",
Expand All @@ -57,7 +55,6 @@ func TestIndividualSignedJSONSerialization(t *testing.T) {
Type: "individual",
Signed: false,
VersionMatched: false,
Status: "not_signed",
},
want: map[string]interface{}{
"type": "individual",
Expand Down Expand Up @@ -106,7 +103,6 @@ func TestIndividualSignedDebugInfoOmittedWhenNil(t *testing.T) {
Type: "individual",
Signed: true,
VersionMatched: true,
Status: "valid",
}

raw, err := json.Marshal(in)
Expand Down
8 changes: 5 additions & 3 deletions signing/app/cla.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ func (s *claService) Update(cmd *CmdToUpdateCLA) error {
return err
}

if err = s.cs.SetPendingCLAForLink(cmd.LinkId, cla.Id); err != nil {
logs.Error("set pending CLA for link failed: %s, err: %v", cmd.LinkId, err)
if !dp.IsCLATypeIndividual(cla.Type) {
if err = s.cs.SetPendingCLAForLink(cmd.LinkId, cla.Id); err != nil {
logs.Error("set pending CLA for link failed: %s, err: %v", cmd.LinkId, err)
}
}

watch.TriggerNotify()
watch.TriggerNotify(cla.Type)

return nil
}
Expand Down
11 changes: 6 additions & 5 deletions signing/app/individual_signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,17 @@ func (s *individualSigningService) AgreeNewCLA(cmd *CmdToSignIndividualCLA) erro
return err
}

if !s.cla.ContainsCla(cmd.Link.Id, cmd.Link.CLAId) {
return domain.NewDomainError(domain.ErrorCodeCLANotExists)
}

sign, err := s.repo.Find(cmd.Link.Id, cmd.Rep.EmailAddr)
if err != nil {
return err
}

if err = sign.AgreeNewCLA(cmd.Link.CLAId); err != nil {
latestClaId := s.cla.GetClaId(sign.Link.Id, dp.CLATypeIndividual, sign.Link.Language)
if latestClaId == "" {
return domain.NewDomainError(domain.ErrorCodeCLANotExists)
}

if err = sign.AgreeNewCLA(latestClaId); err != nil {
return err
}

Expand Down
18 changes: 10 additions & 8 deletions signing/watch/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ type NotifyAdminConfig struct {
SendEmailInterval int `json:"send_email_interval"`
NotifyCorpAdminInterval int `json:"notify_corp_admin_interval"`
NotifyIndividualInterval int `json:"notify_individual_interval"`
NotifyIndividualRemindDays int `json:"notify_individual_remind_days"`
NotifyCorpAdminRemindDays int `json:"notify_corp_admin_remind_days"`
NotifyIndividualRemindDays *int `json:"notify_individual_remind_days"`
NotifyCorpAdminRemindDays *int `json:"notify_corp_admin_remind_days"`
NotifyBatchSize int `json:"notify_batch_size"`
EnabledCommunityOrgs []string `json:"enabled_community_orgs"`
NotifyEmailTo string `json:"notify_email_to"`
Expand All @@ -74,12 +74,14 @@ func (cfg *NotifyAdminConfig) SetDefault() {
cfg.NotifyIndividualInterval = 86400
}

if cfg.NotifyIndividualRemindDays <= 0 {
cfg.NotifyIndividualRemindDays = 90
if cfg.NotifyIndividualRemindDays == nil {
v := 90
cfg.NotifyIndividualRemindDays = &v
}

if cfg.NotifyCorpAdminRemindDays <= 0 {
cfg.NotifyCorpAdminRemindDays = 90
if cfg.NotifyCorpAdminRemindDays == nil {
v := 90
cfg.NotifyCorpAdminRemindDays = &v
}

if cfg.NotifyBatchSize <= 0 {
Expand All @@ -100,11 +102,11 @@ func (cfg *NotifyAdminConfig) genNotifyIndividualInterval() time.Duration {
}

func (cfg *NotifyAdminConfig) genNotifyIndividualRemindDays() int {
return cfg.NotifyIndividualRemindDays
return *cfg.NotifyIndividualRemindDays
}

func (cfg *NotifyAdminConfig) genNotifyCorpAdminRemindDays() int {
return cfg.NotifyCorpAdminRemindDays
return *cfg.NotifyCorpAdminRemindDays
}

func (cfg *NotifyAdminConfig) genNotifyBatchSize() int {
Expand Down
156 changes: 73 additions & 83 deletions signing/watch/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,34 @@ import (
"github.com/opensourceways/app-cla-server/signing/domain/repository"
)

func TestGetEffectiveGracePeriodDays(t *testing.T) {
impl := &notifyAdminWatchImpl{defaultGracePeriodDays: 30}
intPtr := func(v int) *int { return &v }

tests := []struct {
name string
linkDays *int
defaultDay int
want int
}{
{"link nil (字段缺失) uses default", nil, 30, 30},
{"link override positive", intPtr(15), 30, 15},
{"link zero returns zero", intPtr(0), 30, 0},
{"link negative uses default", intPtr(-1), 30, 30},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
link := &repository.LinkCLA{GracePeriodDays: tt.linkDays}
impl.defaultGracePeriodDays = tt.defaultDay
got := impl.getEffectiveGracePeriodDays(link)
if got != tt.want {
t.Errorf("got %d, want %d", got, tt.want)
}
})
}
}

func TestIsCorpSigningLatest(t *testing.T) {
impl := &notifyAdminWatchImpl{}

Expand All @@ -28,68 +56,47 @@ func TestIsCorpSigningLatest(t *testing.T) {
}
}

func TestGetLatestIndividualCLA(t *testing.T) {
func TestGetLatestCorpClaId(t *testing.T) {
impl := &notifyAdminWatchImpl{}

clas := []domain.CLA{
{Id: "10", Type: dp.CLATypeCorp, Language: dp.CreateLanguage("en")},
{Id: "11", Type: dp.CLATypeIndividual, Language: dp.CreateLanguage("en")},
{Id: "12", Type: dp.CLATypeIndividual, Language: dp.CreateLanguage("zh")},
link := &repository.LinkCLA{
Clas: []domain.CLA{
{Id: "10", Type: dp.CLATypeCorp, Language: dp.CreateLanguage("en")},
{Id: "11", Type: dp.CLATypeIndividual, Language: dp.CreateLanguage("en")},
{Id: "12", Type: dp.CLATypeCorp, Language: dp.CreateLanguage("zh")},
},
}

if cla := impl.getLatestIndividualCLA(clas, dp.CreateLanguage("en")); cla == nil || cla.Id != "11" {
t.Errorf("getLatestIndividualCLA en: got %v, want id=11", cla)
if id := impl.getLatestCorpClaId(link, dp.CreateLanguage("en")); id != "10" {
t.Errorf("getLatestCorpClaId en: got %s, want 10", id)
}
if cla := impl.getLatestIndividualCLA(clas, dp.CreateLanguage("zh")); cla == nil || cla.Id != "12" {
t.Errorf("getLatestIndividualCLA zh: got %v, want id=12", cla)
if id := impl.getLatestCorpClaId(link, dp.CreateLanguage("zh")); id != "12" {
t.Errorf("getLatestCorpClaId zh: got %s, want 12", id)
}
if cla := impl.getLatestIndividualCLA(clas, dp.CreateLanguage("fr")); cla != nil {
t.Errorf("getLatestIndividualCLA fr: got %v, want nil", cla)
if id := impl.getLatestCorpClaId(link, dp.CreateLanguage("fr")); id != "" {
t.Errorf("getLatestCorpClaId fr: got %s, want empty", id)
}
}

func TestIsIndividualSigningLatest(t *testing.T) {
func TestGetLatestIndividualClaId(t *testing.T) {
impl := &notifyAdminWatchImpl{}

clas := []domain.CLA{
{Id: "10", Type: dp.CLATypeIndividual, Language: dp.CreateLanguage("en")},
{Id: "11", Type: dp.CLATypeCorp, Language: dp.CreateLanguage("en")},
link := &repository.LinkCLA{
Clas: []domain.CLA{
{Id: "10", Type: dp.CLATypeCorp, Language: dp.CreateLanguage("en")},
{Id: "11", Type: dp.CLATypeIndividual, Language: dp.CreateLanguage("en")},
{Id: "12", Type: dp.CLATypeIndividual, Language: dp.CreateLanguage("zh")},
},
}

signedInfo := domain.CLAInfo{CLAId: "10", Language: dp.CreateLanguage("en")}
if !impl.isIndividualSigningLatest(clas, signedInfo) {
t.Error("isIndividualSigningLatest should return true for matching CLA")
}

signedInfo2 := domain.CLAInfo{CLAId: "9", Language: dp.CreateLanguage("en")}
if impl.isIndividualSigningLatest(clas, signedInfo2) {
t.Error("isIndividualSigningLatest should return false for outdated CLA")
if id := impl.getLatestIndividualClaId(link, dp.CreateLanguage("en")); id != "11" {
t.Errorf("getLatestIndividualClaId en: got %s, want 11", id)
}
}

func TestGetEffectiveGracePeriodDays(t *testing.T) {
intPtr := func(v int) *int { return &v }

tests := []struct {
name string
linkDays *int
defaultDay int
want int
}{
{"link nil uses default", nil, 30, 30},
{"link override positive", intPtr(15), 30, 15},
{"link zero returns zero", intPtr(0), 30, 0},
{"link negative uses default", intPtr(-1), 30, 30},
if id := impl.getLatestIndividualClaId(link, dp.CreateLanguage("zh")); id != "12" {
t.Errorf("getLatestIndividualClaId zh: got %s, want 12", id)
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
link := &repository.LinkCLA{GracePeriodDays: tt.linkDays}
got := link.GetEffectiveGracePeriodDays(tt.defaultDay)
if got != tt.want {
t.Errorf("got %d, want %d", got, tt.want)
}
})
if id := impl.getLatestIndividualClaId(link, dp.CreateLanguage("fr")); id != "" {
t.Errorf("getLatestIndividualClaId fr: got %s, want empty", id)
}
}

Expand All @@ -100,24 +107,13 @@ func TestNotifyAdminConfigSetDefault(t *testing.T) {
if cfg.SendEmailInterval != 10 {
t.Errorf("SendEmailInterval: got %d, want 10", cfg.SendEmailInterval)
}
if cfg.NotifyCorpAdminInterval != 1200 {
t.Errorf("NotifyCorpAdminInterval: got %d, want 1200", cfg.NotifyCorpAdminInterval)
}
if cfg.NotifyIndividualInterval != 86400 {
t.Errorf("NotifyIndividualInterval: got %d, want 86400", cfg.NotifyIndividualInterval)
}
if cfg.NotifyIndividualRemindDays != 90 {
t.Errorf("NotifyIndividualRemindDays: got %d, want 90", cfg.NotifyIndividualRemindDays)
if cfg.NotifyCorpAdminInterval != 86400 {
t.Errorf("NotifyCorpAdminInterval: got %d, want 86400", cfg.NotifyCorpAdminInterval)
}
}

func TestNotifyAdminConfigSetDefaultPreserves(t *testing.T) {
cfg := NotifyAdminConfig{
SendEmailInterval: 20,
NotifyCorpAdminInterval: 600,
NotifyIndividualInterval: 43200,
NotifyIndividualRemindDays: 45,
}
cfg := NotifyAdminConfig{SendEmailInterval: 20, NotifyCorpAdminInterval: 600}
cfg.SetDefault()

if cfg.SendEmailInterval != 20 {
Expand All @@ -126,12 +122,6 @@ func TestNotifyAdminConfigSetDefaultPreserves(t *testing.T) {
if cfg.NotifyCorpAdminInterval != 600 {
t.Errorf("NotifyCorpAdminInterval should be preserved: got %d, want 600", cfg.NotifyCorpAdminInterval)
}
if cfg.NotifyIndividualInterval != 43200 {
t.Errorf("NotifyIndividualInterval should be preserved: got %d, want 43200", cfg.NotifyIndividualInterval)
}
if cfg.NotifyIndividualRemindDays != 45 {
t.Errorf("NotifyIndividualRemindDays should be preserved: got %d, want 45", cfg.NotifyIndividualRemindDays)
}
}

func TestNotifyAdminConfigGenSendEmailInterval(t *testing.T) {
Expand All @@ -150,22 +140,6 @@ func TestNotifyAdminConfigGenNotifyCorpAdminInterval(t *testing.T) {
}
}

func TestNotifyAdminConfigGenNotifyIndividualInterval(t *testing.T) {
cfg := NotifyAdminConfig{NotifyIndividualInterval: 200}
d := cfg.genNotifyIndividualInterval()
if d != 200*time.Second {
t.Errorf("genNotifyIndividualInterval: got %v, want 200s", d)
}
}

func TestNotifyAdminConfigGenNotifyIndividualRemindDays(t *testing.T) {
cfg := NotifyAdminConfig{NotifyIndividualRemindDays: 7}
d := cfg.genNotifyIndividualRemindDays()
if d != 7 {
t.Errorf("genNotifyIndividualRemindDays: got %d, want 7", d)
}
}

func TestCLAUpdateConfigSetDefault(t *testing.T) {
cfg := CLAUpdateConfig{}
cfg.SetDefault()
Expand Down Expand Up @@ -221,3 +195,19 @@ func TestWatchConfigSetDefaultPreserves(t *testing.T) {
t.Errorf("Interval preserved: got %d, want 7200", cfg.Interval)
}
}

func TestWatchConfigConfigItems(t *testing.T) {
cfg := Config{}
items := cfg.ConfigItems()
if len(items) != 2 {
t.Errorf("ConfigItems length: got %d, want 2", len(items))
}
}

func TestWatchConfigIntervalDuration(t *testing.T) {
cfg := Config{Interval: 60}
d := cfg.intervalDuration()
if d != 60*time.Second {
t.Errorf("intervalDuration: got %v, want 60s", d)
}
}
Loading
Loading