const ( | const ( | ||||
// Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0) | // Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0) | ||||
COMMENT_TYPE_COMMENT CommentType = iota | |||||
COMMENT_TYPE_REOPEN | |||||
CommentTypeComment CommentType = iota | |||||
CommentTypeReopen | |||||
COMMENT_TYPE_CLOSE | COMMENT_TYPE_CLOSE | ||||
// References. | // References. | ||||
// Reference from a commit (not part of a pull request) | // Reference from a commit (not part of a pull request) | ||||
COMMENT_TYPE_COMMIT_REF | COMMENT_TYPE_COMMIT_REF | ||||
// Reference from a comment | // Reference from a comment | ||||
COMMENT_TYPE_COMMENT_REF | |||||
CommentTypeComment_REF | |||||
// Reference from a pull request | // Reference from a pull request | ||||
COMMENT_TYPE_PULL_REF | COMMENT_TYPE_PULL_REF | ||||
) | ) | ||||
type CommentTag int | type CommentTag int | ||||
const ( | const ( | ||||
COMMENT_TAG_NONE CommentTag = iota | |||||
COMMENT_TAG_POSTER | |||||
COMMENT_TAG_WRITER | |||||
CommentTagNone CommentTag = iota | |||||
CommentTagPoster | |||||
CommentTagWriter | |||||
COMMENT_TAG_OWNER | COMMENT_TAG_OWNER | ||||
) | ) | ||||
// Check comment type. | // Check comment type. | ||||
switch opts.Type { | switch opts.Type { | ||||
case COMMENT_TYPE_COMMENT: | |||||
case CommentTypeComment: | |||||
act.OpType = ActionCommentIssue | act.OpType = ActionCommentIssue | ||||
if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", opts.Issue.ID); err != nil { | if _, err = e.Exec("UPDATE `issue` SET num_comments=num_comments+1 WHERE id=?", opts.Issue.ID); err != nil { | ||||
} | } | ||||
} | } | ||||
case COMMENT_TYPE_REOPEN: | |||||
case CommentTypeReopen: | |||||
act.OpType = ActionReopenIssue | act.OpType = ActionReopenIssue | ||||
if opts.Issue.IsPull { | if opts.Issue.IsPull { | ||||
act.OpType = ActionReopenPullRequest | act.OpType = ActionReopenPullRequest | ||||
func createStatusComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue) (*Comment, error) { | func createStatusComment(e *xorm.Session, doer *User, repo *Repository, issue *Issue) (*Comment, error) { | ||||
cmtType := COMMENT_TYPE_CLOSE | cmtType := COMMENT_TYPE_CLOSE | ||||
if !issue.IsClosed { | if !issue.IsClosed { | ||||
cmtType = COMMENT_TYPE_REOPEN | |||||
cmtType = CommentTypeReopen | |||||
} | } | ||||
return createComment(e, &CreateCommentOptions{ | return createComment(e, &CreateCommentOptions{ | ||||
Type: cmtType, | Type: cmtType, | ||||
// CreateIssueComment creates a plain issue comment. | // CreateIssueComment creates a plain issue comment. | ||||
func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) { | func CreateIssueComment(doer *User, repo *Repository, issue *Issue, content string, attachments []string) (*Comment, error) { | ||||
return CreateComment(&CreateCommentOptions{ | return CreateComment(&CreateCommentOptions{ | ||||
Type: COMMENT_TYPE_COMMENT, | |||||
Type: CommentTypeComment, | |||||
Doer: doer, | Doer: doer, | ||||
Repo: repo, | Repo: repo, | ||||
Issue: issue, | Issue: issue, | ||||
return err | return err | ||||
} | } | ||||
if comment.Type == COMMENT_TYPE_COMMENT { | |||||
if comment.Type == CommentTypeComment { | |||||
if _, err = sess.Exec("UPDATE `issue` SET num_comments = num_comments - 1 WHERE id = ?", comment.IssueID); err != nil { | if _, err = sess.Exec("UPDATE `issue` SET num_comments = num_comments - 1 WHERE id = ?", comment.IssueID); err != nil { | ||||
return err | return err | ||||
} | } |
// Note: new type must append to the end of list to maintain compatibility. | // Note: new type must append to the end of list to maintain compatibility. | ||||
const ( | const ( | ||||
LOGIN_NOTYPE LoginType = iota | |||||
LOGIN_PLAIN // 1 | |||||
LOGIN_LDAP // 2 | |||||
LoginNotype LoginType = iota | |||||
LoginPlain // 1 | |||||
LoginLdap // 2 | |||||
LOGIN_SMTP // 3 | LOGIN_SMTP // 3 | ||||
LOGIN_PAM // 4 | LOGIN_PAM // 4 | ||||
LOGIN_DLDAP // 5 | LOGIN_DLDAP // 5 | ||||
) | ) | ||||
var LoginNames = map[LoginType]string{ | var LoginNames = map[LoginType]string{ | ||||
LOGIN_LDAP: "LDAP (via BindDN)", | |||||
LoginLdap: "LDAP (via BindDN)", | |||||
LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind | LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind | ||||
LOGIN_SMTP: "SMTP", | LOGIN_SMTP: "SMTP", | ||||
LOGIN_PAM: "PAM", | LOGIN_PAM: "PAM", | ||||
switch colName { | switch colName { | ||||
case "type": | case "type": | ||||
switch LoginType(Cell2Int64(val)) { | switch LoginType(Cell2Int64(val)) { | ||||
case LOGIN_LDAP, LOGIN_DLDAP: | |||||
case LoginLdap, LOGIN_DLDAP: | |||||
source.Cfg = new(LDAPConfig) | source.Cfg = new(LDAPConfig) | ||||
case LOGIN_SMTP: | case LOGIN_SMTP: | ||||
source.Cfg = new(SMTPConfig) | source.Cfg = new(SMTPConfig) | ||||
} | } | ||||
func (source *LoginSource) IsLDAP() bool { | func (source *LoginSource) IsLDAP() bool { | ||||
return source.Type == LOGIN_LDAP | |||||
return source.Type == LoginLdap | |||||
} | } | ||||
func (source *LoginSource) IsDLDAP() bool { | func (source *LoginSource) IsDLDAP() bool { | ||||
func (source *LoginSource) UseTLS() bool { | func (source *LoginSource) UseTLS() bool { | ||||
switch source.Type { | switch source.Type { | ||||
case LOGIN_LDAP, LOGIN_DLDAP: | |||||
case LoginLdap, LOGIN_DLDAP: | |||||
return source.LDAP().SecurityProtocol != ldap.SECURITY_PROTOCOL_UNENCRYPTED | return source.LDAP().SecurityProtocol != ldap.SECURITY_PROTOCOL_UNENCRYPTED | ||||
case LOGIN_SMTP: | case LOGIN_SMTP: | ||||
return source.SMTP().TLS | return source.SMTP().TLS | ||||
func (source *LoginSource) SkipVerify() bool { | func (source *LoginSource) SkipVerify() bool { | ||||
switch source.Type { | switch source.Type { | ||||
case LOGIN_LDAP, LOGIN_DLDAP: | |||||
case LoginLdap, LOGIN_DLDAP: | |||||
return source.LDAP().SkipVerify | return source.LDAP().SkipVerify | ||||
case LOGIN_SMTP: | case LOGIN_SMTP: | ||||
return source.SMTP().SkipVerify | return source.SMTP().SkipVerify | ||||
} | } | ||||
const ( | const ( | ||||
SMTP_PLAIN = "PLAIN" | |||||
SMTP_LOGIN = "LOGIN" | |||||
SmtpPlain = "PLAIN" | |||||
SmtpLogin = "LOGIN" | |||||
) | ) | ||||
var SMTPAuths = []string{SMTP_PLAIN, SMTP_LOGIN} | |||||
var SMTPAuths = []string{SmtpPlain, SmtpLogin} | |||||
func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error { | func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error { | ||||
c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) | c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) | ||||
} | } | ||||
var auth smtp.Auth | var auth smtp.Auth | ||||
if cfg.Auth == SMTP_PLAIN { | |||||
if cfg.Auth == SmtpPlain { | |||||
auth = smtp.PlainAuth("", login, password, cfg.Host) | auth = smtp.PlainAuth("", login, password, cfg.Host) | ||||
} else if cfg.Auth == SMTP_LOGIN { | |||||
} else if cfg.Auth == SmtpLogin { | |||||
auth = &smtpLoginAuth{login, password} | auth = &smtpLoginAuth{login, password} | ||||
} else { | } else { | ||||
return nil, errors.New("Unsupported SMTP auth type") | return nil, errors.New("Unsupported SMTP auth type") | ||||
} | } | ||||
switch source.Type { | switch source.Type { | ||||
case LOGIN_LDAP, LOGIN_DLDAP: | |||||
case LoginLdap, LOGIN_DLDAP: | |||||
return LoginViaLDAP(user, login, password, source, autoRegister) | return LoginViaLDAP(user, login, password, source, autoRegister) | ||||
case LOGIN_SMTP: | case LOGIN_SMTP: | ||||
return LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig), autoRegister) | return LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig), autoRegister) | ||||
if hasUser { | if hasUser { | ||||
switch user.LoginType { | switch user.LoginType { | ||||
case LOGIN_NOTYPE, LOGIN_PLAIN: | |||||
case LoginNotype, LoginPlain: | |||||
if user.ValidatePassword(passowrd) { | if user.ValidatePassword(passowrd) { | ||||
return user, nil | return user, nil | ||||
} | } |
) | ) | ||||
const ( | const ( | ||||
MAIL_AUTH_ACTIVATE base.TplName = "auth/activate" | |||||
MAIL_AUTH_ACTIVATE_EMAIL base.TplName = "auth/activate_email" | |||||
MAIL_AUTH_RESET_PASSWORD base.TplName = "auth/reset_passwd" | |||||
MailAuthActivate base.TplName = "auth/activate" | |||||
MailAuthActivateEmail base.TplName = "auth/activate_email" | |||||
MailAuthResetPassword base.TplName = "auth/reset_passwd" | |||||
MAIL_AUTH_REGISTER_NOTIFY base.TplName = "auth/register_notify" | MAIL_AUTH_REGISTER_NOTIFY base.TplName = "auth/register_notify" | ||||
MAIL_ISSUE_COMMENT base.TplName = "issue/comment" | MAIL_ISSUE_COMMENT base.TplName = "issue/comment" | ||||
} | } | ||||
func SendActivateAccountMail(c *macaron.Context, u *User) { | func SendActivateAccountMail(c *macaron.Context, u *User) { | ||||
SendUserMail(c, u, MAIL_AUTH_ACTIVATE, u.GenerateActivateCode(), c.Tr("mail.activate_account"), "activate account") | |||||
SendUserMail(c, u, MailAuthActivate, u.GenerateActivateCode(), c.Tr("mail.activate_account"), "activate account") | |||||
} | } | ||||
func SendResetPasswordMail(c *macaron.Context, u *User) { | func SendResetPasswordMail(c *macaron.Context, u *User) { | ||||
SendUserMail(c, u, MAIL_AUTH_RESET_PASSWORD, u.GenerateActivateCode(), c.Tr("mail.reset_password"), "reset password") | |||||
SendUserMail(c, u, MailAuthResetPassword, u.GenerateActivateCode(), c.Tr("mail.reset_password"), "reset password") | |||||
} | } | ||||
// SendActivateAccountMail sends confirmation email. | // SendActivateAccountMail sends confirmation email. | ||||
"Code": u.GenerateEmailActivateCode(email.Email), | "Code": u.GenerateEmailActivateCode(email.Email), | ||||
"Email": email.Email, | "Email": email.Email, | ||||
} | } | ||||
body, err := mailRender.HTMLString(string(MAIL_AUTH_ACTIVATE_EMAIL), data) | |||||
body, err := mailRender.HTMLString(string(MailAuthActivateEmail), data) | |||||
if err != nil { | if err != nil { | ||||
log.Error(3, "HTMLString: %v", err) | log.Error(3, "HTMLString: %v", err) | ||||
return | return |
} | } | ||||
} | } | ||||
// returns true if user login type is LOGIN_PLAIN. | |||||
// returns true if user login type is LoginPlain. | |||||
func (u *User) IsLocal() bool { | func (u *User) IsLocal() bool { | ||||
return u.LoginType <= LOGIN_PLAIN | |||||
return u.LoginType <= LoginPlain | |||||
} | } | ||||
// HasForkedRepo checks if user has already forked a repository with given ID. | // HasForkedRepo checks if user has already forked a repository with given ID. |
var ( | var ( | ||||
authSources = []dropdownItem{ | authSources = []dropdownItem{ | ||||
{models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP}, | |||||
{models.LoginNames[models.LoginLdap], models.LoginLdap}, | |||||
{models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP}, | {models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP}, | ||||
{models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP}, | {models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP}, | ||||
{models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM}, | {models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM}, | ||||
ctx.Data["PageIsAdmin"] = true | ctx.Data["PageIsAdmin"] = true | ||||
ctx.Data["PageIsAdminAuthentications"] = true | ctx.Data["PageIsAdminAuthentications"] = true | ||||
ctx.Data["type"] = models.LOGIN_LDAP | |||||
ctx.Data["CurrentTypeName"] = models.LoginNames[models.LOGIN_LDAP] | |||||
ctx.Data["type"] = models.LoginLdap | |||||
ctx.Data["CurrentTypeName"] = models.LoginNames[models.LoginLdap] | |||||
ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED] | ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED] | ||||
ctx.Data["smtp_auth"] = "PLAIN" | ctx.Data["smtp_auth"] = "PLAIN" | ||||
ctx.Data["is_active"] = true | ctx.Data["is_active"] = true | ||||
hasTLS := false | hasTLS := false | ||||
var config core.Conversion | var config core.Conversion | ||||
switch models.LoginType(form.Type) { | switch models.LoginType(form.Type) { | ||||
case models.LOGIN_LDAP, models.LOGIN_DLDAP: | |||||
case models.LoginLdap, models.LOGIN_DLDAP: | |||||
config = parseLDAPConfig(form) | config = parseLDAPConfig(form) | ||||
hasTLS = ldap.SecurityProtocol(form.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED | hasTLS = ldap.SecurityProtocol(form.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED | ||||
case models.LOGIN_SMTP: | case models.LOGIN_SMTP: | ||||
var config core.Conversion | var config core.Conversion | ||||
switch models.LoginType(form.Type) { | switch models.LoginType(form.Type) { | ||||
case models.LOGIN_LDAP, models.LOGIN_DLDAP: | |||||
case models.LoginLdap, models.LOGIN_DLDAP: | |||||
config = parseLDAPConfig(form) | config = parseLDAPConfig(form) | ||||
case models.LOGIN_SMTP: | case models.LOGIN_SMTP: | ||||
config = parseSMTPConfig(form) | config = parseSMTPConfig(form) |
Email: form.Email, | Email: form.Email, | ||||
Passwd: form.Password, | Passwd: form.Password, | ||||
IsActive: true, | IsActive: true, | ||||
LoginType: models.LOGIN_PLAIN, | |||||
LoginType: models.LoginPlain, | |||||
} | } | ||||
if len(form.LoginType) > 0 { | if len(form.LoginType) > 0 { |
Email: form.Email, | Email: form.Email, | ||||
Passwd: form.Password, | Passwd: form.Password, | ||||
IsActive: true, | IsActive: true, | ||||
LoginType: models.LOGIN_PLAIN, | |||||
LoginType: models.LoginPlain, | |||||
} | } | ||||
parseLoginSource(ctx, u, form.SourceID, form.LoginName) | parseLoginSource(ctx, u, form.SourceID, form.LoginName) |
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | ||||
ctx.Status(403) | ctx.Status(403) | ||||
return | return | ||||
} else if comment.Type != models.COMMENT_TYPE_COMMENT { | |||||
} else if comment.Type != models.CommentTypeComment { | |||||
ctx.Status(204) | ctx.Status(204) | ||||
return | return | ||||
} | } |
// Render comments and and fetch participants. | // Render comments and and fetch participants. | ||||
participants[0] = issue.Poster | participants[0] = issue.Poster | ||||
for _, comment = range issue.Comments { | for _, comment = range issue.Comments { | ||||
if comment.Type == models.COMMENT_TYPE_COMMENT { | |||||
if comment.Type == models.CommentTypeComment { | |||||
comment.RenderedContent = string(markdown.Render([]byte(comment.Content), ctx.Repo.RepoLink, | comment.RenderedContent = string(markdown.Render([]byte(comment.Content), ctx.Repo.RepoLink, | ||||
ctx.Repo.Repository.ComposeMetas())) | ctx.Repo.Repository.ComposeMetas())) | ||||
(repo.Owner.IsOrganization() && repo.Owner.IsOwnedBy(comment.PosterID)) { | (repo.Owner.IsOrganization() && repo.Owner.IsOwnedBy(comment.PosterID)) { | ||||
comment.ShowTag = models.COMMENT_TAG_OWNER | comment.ShowTag = models.COMMENT_TAG_OWNER | ||||
} else if comment.Poster.IsWriterOfRepo(repo) { | } else if comment.Poster.IsWriterOfRepo(repo) { | ||||
comment.ShowTag = models.COMMENT_TAG_WRITER | |||||
comment.ShowTag = models.CommentTagWriter | |||||
} else if comment.PosterID == issue.PosterID { | } else if comment.PosterID == issue.PosterID { | ||||
comment.ShowTag = models.COMMENT_TAG_POSTER | |||||
comment.ShowTag = models.CommentTagPoster | |||||
} | } | ||||
marked[comment.PosterID] = comment.ShowTag | marked[comment.PosterID] = comment.ShowTag | ||||
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | ||||
ctx.Error(403) | ctx.Error(403) | ||||
return | return | ||||
} else if comment.Type != models.COMMENT_TYPE_COMMENT { | |||||
} else if comment.Type != models.CommentTypeComment { | |||||
ctx.Error(204) | ctx.Error(204) | ||||
return | return | ||||
} | } | ||||
if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) { | ||||
ctx.Error(403) | ctx.Error(403) | ||||
return | return | ||||
} else if comment.Type != models.COMMENT_TYPE_COMMENT { | |||||
} else if comment.Type != models.CommentTypeComment { | |||||
ctx.Error(204) | ctx.Error(204) | ||||
return | return | ||||
} | } |