forked from NYANDEV/forgejo
Finish create organization team
This commit is contained in:
parent
e57aebb316
commit
465dc962b5
13 changed files with 389 additions and 247 deletions
|
@ -195,9 +195,10 @@ func runWeb(*cli.Context) {
|
||||||
r.Get("/:org/dashboard", org.Dashboard)
|
r.Get("/:org/dashboard", org.Dashboard)
|
||||||
r.Get("/:org/members", org.Members)
|
r.Get("/:org/members", org.Members)
|
||||||
|
|
||||||
r.Get("/:org/teams/:team/edit", org.EditTeam)
|
|
||||||
r.Get("/:org/teams/new", org.NewTeam)
|
|
||||||
r.Get("/:org/teams", org.Teams)
|
r.Get("/:org/teams", org.Teams)
|
||||||
|
r.Get("/:org/teams/new", org.NewTeam)
|
||||||
|
r.Post("/:org/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
|
||||||
|
r.Get("/:org/teams/:team/edit", org.EditTeam)
|
||||||
|
|
||||||
r.Get("/:org/settings", org.Settings)
|
r.Get("/:org/settings", org.Settings)
|
||||||
r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost)
|
r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost)
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -17,7 +17,7 @@ import (
|
||||||
"github.com/gogits/gogs/modules/setting"
|
"github.com/gogits/gogs/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APP_VER = "0.4.5.0629 Alpha"
|
const APP_VER = "0.4.5.0702 Alpha"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
|
@ -5,11 +5,17 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrOrgNotExist = errors.New("Organization does not exist")
|
||||||
|
ErrTeamAlreadyExist = errors.New("Team already exist")
|
||||||
|
)
|
||||||
|
|
||||||
// IsOrgOwner returns true if given user is in the owner team.
|
// IsOrgOwner returns true if given user is in the owner team.
|
||||||
func (org *User) IsOrgOwner(uid int64) bool {
|
func (org *User) IsOrgOwner(uid int64) bool {
|
||||||
return IsOrganizationOwner(org.Id, uid)
|
return IsOrganizationOwner(org.Id, uid)
|
||||||
|
@ -156,6 +162,13 @@ func DeleteOrganization(org *User) (err error) {
|
||||||
return sess.Commit()
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ___________
|
||||||
|
// \__ ___/___ _____ _____
|
||||||
|
// | |_/ __ \\__ \ / \
|
||||||
|
// | |\ ___/ / __ \| Y Y \
|
||||||
|
// |____| \___ >____ /__|_| /
|
||||||
|
// \/ \/ \/
|
||||||
|
|
||||||
type AuthorizeType int
|
type AuthorizeType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -192,11 +205,41 @@ func (t *Team) GetMembers() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTeam creates a record of new team.
|
// NewTeam creates a record of new team.
|
||||||
|
// It's caller's responsibility to assign organization ID.
|
||||||
func NewTeam(t *Team) error {
|
func NewTeam(t *Team) error {
|
||||||
// TODO: check if same name team of organization exists.
|
has, err := x.Id(t.OrgId).Get(new(User))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if !has {
|
||||||
|
return ErrOrgNotExist
|
||||||
|
}
|
||||||
|
|
||||||
t.LowerName = strings.ToLower(t.Name)
|
t.LowerName = strings.ToLower(t.Name)
|
||||||
_, err := x.Insert(t)
|
has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team))
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if has {
|
||||||
|
return ErrTeamAlreadyExist
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := x.NewSession()
|
||||||
|
defer sess.Close()
|
||||||
|
if err = sess.Begin(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = sess.Insert(t); err != nil {
|
||||||
|
sess.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update organization number of teams.
|
||||||
|
rawSql := "UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?"
|
||||||
|
if _, err = sess.Exec(rawSql, t.OrgId); err != nil {
|
||||||
|
sess.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return sess.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTeam updates information of team.
|
// UpdateTeam updates information of team.
|
||||||
|
|
|
@ -158,7 +158,7 @@ func IsRepositoryExist(u *User, repoName string) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
illegalEquals = []string{"raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin"}
|
illegalEquals = []string{"raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin", "new"}
|
||||||
illegalSuffixs = []string{".git"}
|
illegalSuffixs = []string{".git"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,183 +7,49 @@ package auth
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/go-martini/martini"
|
"github.com/go-martini/martini"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
"github.com/gogits/gogs/modules/log"
|
|
||||||
"github.com/gogits/gogs/modules/middleware/binding"
|
"github.com/gogits/gogs/modules/middleware/binding"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Web form interface.
|
type AuthenticationForm struct {
|
||||||
type Form interface {
|
Id int64 `form:"id"`
|
||||||
Name(field string) string
|
Type int `form:"type"`
|
||||||
|
AuthName string `form:"name" binding:"Required;MaxSize(50)"`
|
||||||
|
Domain string `form:"domain"`
|
||||||
|
Host string `form:"host"`
|
||||||
|
Port int `form:"port"`
|
||||||
|
UseSSL bool `form:"usessl"`
|
||||||
|
BaseDN string `form:"base_dn"`
|
||||||
|
Attributes string `form:"attributes"`
|
||||||
|
Filter string `form:"filter"`
|
||||||
|
MsAdSA string `form:"ms_ad_sa"`
|
||||||
|
IsActived bool `form:"is_actived"`
|
||||||
|
SmtpAuth string `form:"smtpauth"`
|
||||||
|
SmtpHost string `form:"smtphost"`
|
||||||
|
SmtpPort int `form:"smtpport"`
|
||||||
|
Tls bool `form:"tls"`
|
||||||
|
AllowAutoRegister bool `form:"allowautoregister"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegisterForm struct {
|
func (f *AuthenticationForm) Name(field string) string {
|
||||||
UserName string `form:"username" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
|
||||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
|
||||||
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
|
||||||
RetypePasswd string `form:"retypepasswd"`
|
|
||||||
LoginType string `form:"logintype"`
|
|
||||||
LoginName string `form:"loginname"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *RegisterForm) Name(field string) string {
|
|
||||||
names := map[string]string{
|
names := map[string]string{
|
||||||
"UserName": "Username",
|
"AuthName": "Authentication's name",
|
||||||
"Email": "E-mail address",
|
"Domain": "Domain name",
|
||||||
"Password": "Password",
|
"Host": "Host address",
|
||||||
"RetypePasswd": "Re-type password",
|
"Port": "Port Number",
|
||||||
|
"UseSSL": "Use SSL",
|
||||||
|
"BaseDN": "Base DN",
|
||||||
|
"Attributes": "Search attributes",
|
||||||
|
"Filter": "Search filter",
|
||||||
|
"MsAdSA": "Ms Ad SA",
|
||||||
}
|
}
|
||||||
return names[field]
|
return names[field]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *RegisterForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
|
func (f *AuthenticationForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
|
||||||
data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
|
||||||
validate(errs, data, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
type LogInForm struct {
|
|
||||||
UserName string `form:"username" binding:"Required;MaxSize(35)"`
|
|
||||||
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
|
||||||
Remember bool `form:"remember"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *LogInForm) Name(field string) string {
|
|
||||||
names := map[string]string{
|
|
||||||
"UserName": "Username",
|
|
||||||
"Password": "Password",
|
|
||||||
}
|
|
||||||
return names[field]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *LogInForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
|
|
||||||
data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
|
||||||
validate(errs, data, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetMinMaxSize(field reflect.StructField) string {
|
|
||||||
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
|
|
||||||
if strings.HasPrefix(rule, "MinSize(") || strings.HasPrefix(rule, "MaxSize(") {
|
|
||||||
return rule[8 : len(rule)-1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func validate(errs *binding.Errors, data base.TmplData, f Form) {
|
|
||||||
if errs.Count() == 0 {
|
|
||||||
return
|
|
||||||
} else if len(errs.Overall) > 0 {
|
|
||||||
for _, err := range errs.Overall {
|
|
||||||
log.Error("%s: %v", reflect.TypeOf(f), err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
data["HasError"] = true
|
|
||||||
AssignForm(f, data)
|
|
||||||
|
|
||||||
typ := reflect.TypeOf(f)
|
|
||||||
val := reflect.ValueOf(f)
|
|
||||||
|
|
||||||
if typ.Kind() == reflect.Ptr {
|
|
||||||
typ = typ.Elem()
|
|
||||||
val = val.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < typ.NumField(); i++ {
|
|
||||||
field := typ.Field(i)
|
|
||||||
|
|
||||||
fieldName := field.Tag.Get("form")
|
|
||||||
// Allow ignored fields in the struct
|
|
||||||
if fieldName == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err, ok := errs.Fields[field.Name]; ok {
|
|
||||||
data["Err_"+field.Name] = true
|
|
||||||
switch err {
|
|
||||||
case binding.BindingRequireError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " cannot be empty"
|
|
||||||
case binding.BindingAlphaDashError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters"
|
|
||||||
case binding.BindingAlphaDashDotError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters"
|
|
||||||
case binding.BindingMinSizeError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " must contain at least " + GetMinMaxSize(field) + " characters"
|
|
||||||
case binding.BindingMaxSizeError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " must contain at most " + GetMinMaxSize(field) + " characters"
|
|
||||||
case binding.BindingEmailError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " is not a valid e-mail address"
|
|
||||||
case binding.BindingUrlError:
|
|
||||||
data["ErrorMsg"] = f.Name(field.Name) + " is not a valid URL"
|
|
||||||
default:
|
|
||||||
data["ErrorMsg"] = "Unknown error: " + err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssignForm assign form values back to the template data.
|
|
||||||
func AssignForm(form interface{}, data base.TmplData) {
|
|
||||||
typ := reflect.TypeOf(form)
|
|
||||||
val := reflect.ValueOf(form)
|
|
||||||
|
|
||||||
if typ.Kind() == reflect.Ptr {
|
|
||||||
typ = typ.Elem()
|
|
||||||
val = val.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < typ.NumField(); i++ {
|
|
||||||
field := typ.Field(i)
|
|
||||||
|
|
||||||
fieldName := field.Tag.Get("form")
|
|
||||||
// Allow ignored fields in the struct
|
|
||||||
if fieldName == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
data[fieldName] = val.Field(i).Interface()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InstallForm struct {
|
|
||||||
Database string `form:"database" binding:"Required"`
|
|
||||||
Host string `form:"host"`
|
|
||||||
User string `form:"user"`
|
|
||||||
Passwd string `form:"passwd"`
|
|
||||||
DatabaseName string `form:"database_name"`
|
|
||||||
SslMode string `form:"ssl_mode"`
|
|
||||||
DatabasePath string `form:"database_path"`
|
|
||||||
RepoRootPath string `form:"repo_path"`
|
|
||||||
RunUser string `form:"run_user"`
|
|
||||||
Domain string `form:"domain"`
|
|
||||||
AppUrl string `form:"app_url"`
|
|
||||||
AdminName string `form:"admin_name" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
|
||||||
AdminPasswd string `form:"admin_pwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
|
||||||
AdminEmail string `form:"admin_email" binding:"Required;Email;MaxSize(50)"`
|
|
||||||
SmtpHost string `form:"smtp_host"`
|
|
||||||
SmtpEmail string `form:"mailer_user"`
|
|
||||||
SmtpPasswd string `form:"mailer_pwd"`
|
|
||||||
RegisterConfirm string `form:"register_confirm"`
|
|
||||||
MailNotify string `form:"mail_notify"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *InstallForm) Name(field string) string {
|
|
||||||
names := map[string]string{
|
|
||||||
"Database": "Database name",
|
|
||||||
"AdminName": "Admin user name",
|
|
||||||
"AdminPasswd": "Admin password",
|
|
||||||
"AdminEmail": "Admin e-maill address",
|
|
||||||
}
|
|
||||||
return names[field]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *InstallForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
|
|
||||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
||||||
validate(errors, data, f)
|
validate(errors, data, f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/go-martini/martini"
|
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/base"
|
|
||||||
"github.com/gogits/gogs/modules/middleware/binding"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AuthenticationForm struct {
|
|
||||||
Id int64 `form:"id"`
|
|
||||||
Type int `form:"type"`
|
|
||||||
AuthName string `form:"name" binding:"Required;MaxSize(50)"`
|
|
||||||
Domain string `form:"domain"`
|
|
||||||
Host string `form:"host"`
|
|
||||||
Port int `form:"port"`
|
|
||||||
UseSSL bool `form:"usessl"`
|
|
||||||
BaseDN string `form:"base_dn"`
|
|
||||||
Attributes string `form:"attributes"`
|
|
||||||
Filter string `form:"filter"`
|
|
||||||
MsAdSA string `form:"ms_ad_sa"`
|
|
||||||
IsActived bool `form:"is_actived"`
|
|
||||||
SmtpAuth string `form:"smtpauth"`
|
|
||||||
SmtpHost string `form:"smtphost"`
|
|
||||||
SmtpPort int `form:"smtpport"`
|
|
||||||
Tls bool `form:"tls"`
|
|
||||||
AllowAutoRegister bool `form:"allowautoregister"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *AuthenticationForm) Name(field string) string {
|
|
||||||
names := map[string]string{
|
|
||||||
"AuthName": "Authentication's name",
|
|
||||||
"Domain": "Domain name",
|
|
||||||
"Host": "Host address",
|
|
||||||
"Port": "Port Number",
|
|
||||||
"UseSSL": "Use SSL",
|
|
||||||
"BaseDN": "Base DN",
|
|
||||||
"Attributes": "Search attributes",
|
|
||||||
"Filter": "Search filter",
|
|
||||||
"MsAdSA": "Ms Ad SA",
|
|
||||||
}
|
|
||||||
return names[field]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *AuthenticationForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
|
|
||||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
|
||||||
validate(errors, data, f)
|
|
||||||
}
|
|
|
@ -14,6 +14,13 @@ import (
|
||||||
"github.com/gogits/gogs/modules/middleware/binding"
|
"github.com/gogits/gogs/modules/middleware/binding"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ________ .__ __ .__
|
||||||
|
// \_____ \_______ _________ ____ |__|____________ _/ |_|__| ____ ____
|
||||||
|
// / | \_ __ \/ ___\__ \ / \| \___ /\__ \\ __\ |/ _ \ / \
|
||||||
|
// / | \ | \/ /_/ > __ \| | \ |/ / / __ \| | | ( <_> ) | \
|
||||||
|
// \_______ /__| \___ (____ /___| /__/_____ \(____ /__| |__|\____/|___| /
|
||||||
|
// \/ /_____/ \/ \/ \/ \/ \/
|
||||||
|
|
||||||
type CreateOrgForm struct {
|
type CreateOrgForm struct {
|
||||||
OrgName string `form:"orgname" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
OrgName string `form:"orgname" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||||
|
@ -55,3 +62,29 @@ func (f *OrgSettingForm) Validate(errors *binding.Errors, req *http.Request, con
|
||||||
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
||||||
validate(errors, data, f)
|
validate(errors, data, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ___________
|
||||||
|
// \__ ___/___ _____ _____
|
||||||
|
// | |_/ __ \\__ \ / \
|
||||||
|
// | |\ ___/ / __ \| Y Y \
|
||||||
|
// |____| \___ >____ /__|_| /
|
||||||
|
// \/ \/ \/
|
||||||
|
|
||||||
|
type CreateTeamForm struct {
|
||||||
|
TeamName string `form:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||||
|
Description string `form:"desc" binding:"MaxSize(255)"`
|
||||||
|
Permission string `form:"permission"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CreateTeamForm) Name(field string) string {
|
||||||
|
names := map[string]string{
|
||||||
|
"TeamName": "Team name",
|
||||||
|
"Description": "Team description",
|
||||||
|
}
|
||||||
|
return names[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CreateTeamForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
|
||||||
|
data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
||||||
|
validate(errs, data, f)
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ package auth
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/go-martini/martini"
|
"github.com/go-martini/martini"
|
||||||
|
|
||||||
|
@ -19,6 +20,178 @@ import (
|
||||||
"github.com/gogits/gogs/modules/setting"
|
"github.com/gogits/gogs/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Web form interface.
|
||||||
|
type Form interface {
|
||||||
|
Name(field string) string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RegisterForm struct {
|
||||||
|
UserName string `form:"username" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||||
|
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||||
|
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
||||||
|
RetypePasswd string `form:"retypepasswd"`
|
||||||
|
LoginType string `form:"logintype"`
|
||||||
|
LoginName string `form:"loginname"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RegisterForm) Name(field string) string {
|
||||||
|
names := map[string]string{
|
||||||
|
"UserName": "Username",
|
||||||
|
"Email": "E-mail address",
|
||||||
|
"Password": "Password",
|
||||||
|
"RetypePasswd": "Re-type password",
|
||||||
|
}
|
||||||
|
return names[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *RegisterForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
|
||||||
|
data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
||||||
|
validate(errs, data, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogInForm struct {
|
||||||
|
UserName string `form:"username" binding:"Required;MaxSize(35)"`
|
||||||
|
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
||||||
|
Remember bool `form:"remember"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *LogInForm) Name(field string) string {
|
||||||
|
names := map[string]string{
|
||||||
|
"UserName": "Username",
|
||||||
|
"Password": "Password",
|
||||||
|
}
|
||||||
|
return names[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *LogInForm) Validate(errs *binding.Errors, req *http.Request, ctx martini.Context) {
|
||||||
|
data := ctx.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
||||||
|
validate(errs, data, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMinMaxSize(field reflect.StructField) string {
|
||||||
|
for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
|
||||||
|
if strings.HasPrefix(rule, "MinSize(") || strings.HasPrefix(rule, "MaxSize(") {
|
||||||
|
return rule[8 : len(rule)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func validate(errs *binding.Errors, data base.TmplData, f Form) {
|
||||||
|
if errs.Count() == 0 {
|
||||||
|
return
|
||||||
|
} else if len(errs.Overall) > 0 {
|
||||||
|
for _, err := range errs.Overall {
|
||||||
|
log.Error("%s: %v", reflect.TypeOf(f), err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data["HasError"] = true
|
||||||
|
AssignForm(f, data)
|
||||||
|
|
||||||
|
typ := reflect.TypeOf(f)
|
||||||
|
val := reflect.ValueOf(f)
|
||||||
|
|
||||||
|
if typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
field := typ.Field(i)
|
||||||
|
|
||||||
|
fieldName := field.Tag.Get("form")
|
||||||
|
// Allow ignored fields in the struct
|
||||||
|
if fieldName == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, ok := errs.Fields[field.Name]; ok {
|
||||||
|
data["Err_"+field.Name] = true
|
||||||
|
switch err {
|
||||||
|
case binding.BindingRequireError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " cannot be empty"
|
||||||
|
case binding.BindingAlphaDashError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) characters"
|
||||||
|
case binding.BindingAlphaDashDotError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " must be valid alpha or numeric or dash(-_) or dot characters"
|
||||||
|
case binding.BindingMinSizeError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " must contain at least " + GetMinMaxSize(field) + " characters"
|
||||||
|
case binding.BindingMaxSizeError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " must contain at most " + GetMinMaxSize(field) + " characters"
|
||||||
|
case binding.BindingEmailError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " is not a valid e-mail address"
|
||||||
|
case binding.BindingUrlError:
|
||||||
|
data["ErrorMsg"] = f.Name(field.Name) + " is not a valid URL"
|
||||||
|
default:
|
||||||
|
data["ErrorMsg"] = "Unknown error: " + err
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssignForm assign form values back to the template data.
|
||||||
|
func AssignForm(form interface{}, data base.TmplData) {
|
||||||
|
typ := reflect.TypeOf(form)
|
||||||
|
val := reflect.ValueOf(form)
|
||||||
|
|
||||||
|
if typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < typ.NumField(); i++ {
|
||||||
|
field := typ.Field(i)
|
||||||
|
|
||||||
|
fieldName := field.Tag.Get("form")
|
||||||
|
// Allow ignored fields in the struct
|
||||||
|
if fieldName == "-" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
data[fieldName] = val.Field(i).Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type InstallForm struct {
|
||||||
|
Database string `form:"database" binding:"Required"`
|
||||||
|
Host string `form:"host"`
|
||||||
|
User string `form:"user"`
|
||||||
|
Passwd string `form:"passwd"`
|
||||||
|
DatabaseName string `form:"database_name"`
|
||||||
|
SslMode string `form:"ssl_mode"`
|
||||||
|
DatabasePath string `form:"database_path"`
|
||||||
|
RepoRootPath string `form:"repo_path"`
|
||||||
|
RunUser string `form:"run_user"`
|
||||||
|
Domain string `form:"domain"`
|
||||||
|
AppUrl string `form:"app_url"`
|
||||||
|
AdminName string `form:"admin_name" binding:"Required;AlphaDashDot;MaxSize(30)"`
|
||||||
|
AdminPasswd string `form:"admin_pwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
||||||
|
AdminEmail string `form:"admin_email" binding:"Required;Email;MaxSize(50)"`
|
||||||
|
SmtpHost string `form:"smtp_host"`
|
||||||
|
SmtpEmail string `form:"mailer_user"`
|
||||||
|
SmtpPasswd string `form:"mailer_pwd"`
|
||||||
|
RegisterConfirm string `form:"register_confirm"`
|
||||||
|
MailNotify string `form:"mail_notify"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *InstallForm) Name(field string) string {
|
||||||
|
names := map[string]string{
|
||||||
|
"Database": "Database name",
|
||||||
|
"AdminName": "Admin user name",
|
||||||
|
"AdminPasswd": "Admin password",
|
||||||
|
"AdminEmail": "Admin e-maill address",
|
||||||
|
}
|
||||||
|
return names[field]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *InstallForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
|
||||||
|
data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
|
||||||
|
validate(errors, data, f)
|
||||||
|
}
|
||||||
|
|
||||||
// SignedInId returns the id of signed in user.
|
// SignedInId returns the id of signed in user.
|
||||||
func SignedInId(header http.Header, sess session.SessionStore) int64 {
|
func SignedInId(header http.Header, sess session.SessionStore) int64 {
|
||||||
if !models.HasEngine {
|
if !models.HasEngine {
|
||||||
|
|
|
@ -8,12 +8,15 @@ import (
|
||||||
"github.com/go-martini/martini"
|
"github.com/go-martini/martini"
|
||||||
|
|
||||||
"github.com/gogits/gogs/models"
|
"github.com/gogits/gogs/models"
|
||||||
|
"github.com/gogits/gogs/modules/auth"
|
||||||
"github.com/gogits/gogs/modules/base"
|
"github.com/gogits/gogs/modules/base"
|
||||||
|
"github.com/gogits/gogs/modules/log"
|
||||||
"github.com/gogits/gogs/modules/middleware"
|
"github.com/gogits/gogs/modules/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TEAMS base.TplName = "org/teams"
|
TEAMS base.TplName = "org/teams"
|
||||||
|
TEAM_NEW base.TplName = "org/team_new"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Teams(ctx *middleware.Context, params martini.Params) {
|
func Teams(ctx *middleware.Context, params martini.Params) {
|
||||||
|
@ -46,8 +49,80 @@ func Teams(ctx *middleware.Context, params martini.Params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTeam(ctx *middleware.Context, params martini.Params) {
|
func NewTeam(ctx *middleware.Context, params martini.Params) {
|
||||||
ctx.Data["Title"] = "Organization " + params["org"] + " New Team"
|
org, err := models.GetUserByName(params["org"])
|
||||||
ctx.HTML(200, "org/new_team")
|
if err != nil {
|
||||||
|
if err == models.ErrUserNotExist {
|
||||||
|
ctx.Handle(404, "org.NewTeam(GetUserByName)", err)
|
||||||
|
} else {
|
||||||
|
ctx.Handle(500, "org.NewTeam(GetUserByName)", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["Org"] = org
|
||||||
|
|
||||||
|
// Check ownership of organization.
|
||||||
|
if !org.IsOrgOwner(ctx.User.Id) {
|
||||||
|
ctx.Error(403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.HTML(200, TEAM_NEW)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTeamPost(ctx *middleware.Context, params martini.Params, form auth.CreateTeamForm) {
|
||||||
|
org, err := models.GetUserByName(params["org"])
|
||||||
|
if err != nil {
|
||||||
|
if err == models.ErrUserNotExist {
|
||||||
|
ctx.Handle(404, "org.NewTeamPost(GetUserByName)", err)
|
||||||
|
} else {
|
||||||
|
ctx.Handle(500, "org.NewTeamPost(GetUserByName)", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["Org"] = org
|
||||||
|
|
||||||
|
// Check ownership of organization.
|
||||||
|
if !org.IsOrgOwner(ctx.User.Id) {
|
||||||
|
ctx.Error(403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.HasError() {
|
||||||
|
ctx.HTML(200, TEAM_NEW)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate permission level.
|
||||||
|
var auth models.AuthorizeType
|
||||||
|
switch form.Permission {
|
||||||
|
case "read":
|
||||||
|
auth = models.ORG_READABLE
|
||||||
|
case "write":
|
||||||
|
auth = models.ORG_WRITABLE
|
||||||
|
case "admin":
|
||||||
|
auth = models.ORG_ADMIN
|
||||||
|
default:
|
||||||
|
ctx.Error(401)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &models.Team{
|
||||||
|
OrgId: org.Id,
|
||||||
|
Name: form.TeamName,
|
||||||
|
Description: form.Description,
|
||||||
|
Authorize: auth,
|
||||||
|
}
|
||||||
|
if err = models.NewTeam(t); err != nil {
|
||||||
|
if err == models.ErrTeamAlreadyExist {
|
||||||
|
ctx.Data["Err_TeamName"] = true
|
||||||
|
ctx.RenderWithErr("Team name has already been used", TEAM_NEW, &form)
|
||||||
|
} else {
|
||||||
|
ctx.Handle(500, "org.NewTeamPost(NewTeam)", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Trace("%s Team created: %s/%s", ctx.Req.RequestURI, org.Name, t.Name)
|
||||||
|
ctx.Redirect("/org/" + org.LowerName + "/teams/" + t.LowerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func EditTeam(ctx *middleware.Context, params martini.Params) {
|
func EditTeam(ctx *middleware.Context, params martini.Params) {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.4.5.0629 Alpha
|
0.4.5.0702 Alpha
|
|
@ -13,7 +13,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}">
|
<div class="form-group{{if .Err_Email}} has-error has-feedback{{end}}">
|
||||||
<label class="col-md-2 control-label">Email<strong class="text-danger">*</strong></label>
|
<label class="col-md-2 control-label">Email<strong class="text-danger">*</strong></label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="email" type="text" class="form-control" placeholder="Type organization's email" value="{{.email}}" required="required">
|
<input name="email" type="text" class="form-control" placeholder="Type organization's email" value="{{.email}}" required="required">
|
||||||
|
|
|
@ -4,58 +4,63 @@
|
||||||
<div class="container clearfix">
|
<div class="container clearfix">
|
||||||
<div id="org-nav-wrapper">
|
<div id="org-nav-wrapper">
|
||||||
<ul class="nav nav-pills pull-right">
|
<ul class="nav nav-pills pull-right">
|
||||||
<li><a href="#"><i class="fa fa-users"></i>Members
|
<li><a href="/org/{{.Org.Name}}/members"><i class="fa fa-users"></i>Members
|
||||||
<span class="label label-default">5</span></a>
|
<span class="label label-default">{{.Org.NumMembers}}</span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="active"><a href="#"><i class="fa fa-tags"></i>Teams
|
<li class="active"><a href="/org/{{.Org.Name}}/teams"><i class="fa fa-tags"></i>Teams
|
||||||
<span class="label label-default">2</span></a>
|
<span class="label label-default">{{.Org.NumTeams}}</span></a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<img class="pull-left org-small-logo" src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt="" width="60"/>
|
<img class="pull-left org-small-logo" src="{{.Org.AvatarLink}}?s=140" alt="" width="60"/>
|
||||||
<div id="org-nav-info">
|
<div id="org-nav-info">
|
||||||
<h2 class="org-name">Organization Name</h2>
|
<h2 class="org-name">{{.Org.FullName}}</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="body" class="container">
|
<div id="body" class="container">
|
||||||
<div id="org">
|
<div id="org">
|
||||||
<form id="org-teams-create" class="form-horizontal card">
|
<form action="/org/{{.Org.Name}}/teams/new" method="post" id="org-teams-create" class="form-horizontal card">
|
||||||
|
{{.CsrfTokenHtml}}
|
||||||
<h3>Create new team</h3>
|
<h3>Create new team</h3>
|
||||||
<div class="form-group">
|
{{template "base/alert" .}}
|
||||||
|
<div class="form-group{{if .Err_TeamName}} has-error has-feedback{{end}}">
|
||||||
<label class="col-md-2 control-label">Team Name<strong class="text-danger">*</strong></label>
|
<label class="col-md-2 control-label">Team Name<strong class="text-danger">*</strong></label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="team" type="text" class="form-control" placeholder="Type your team name" value="" required="required">
|
<input name="name" type="text" class="form-control" placeholder="Type your team name" value="{{.name}}" required="required">
|
||||||
<span class="help-block">You'll use this name to mention this team in conversations.</span>
|
<span class="help-block">You'll use this name to mention this team in conversations.</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
|
<div class="form-group{{if .Err_Description}} has-error has-feedback{{end}}">
|
||||||
<label class="col-md-2 control-label">Description</label>
|
<label class="col-md-2 control-label">Description</label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<input name="desc" type="text" class="form-control" placeholder="Type your team description (optional)" value="">
|
<input name="desc" type="text" class="form-control" placeholder="Type your team description (optional)" value="{{.desc}}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
|
<div class="form-group{{if .Err_Permission}} has-error has-feedback{{end}}">
|
||||||
<label class="col-md-2 control-label">Permission</label>
|
<label class="col-md-2 control-label">Permission</label>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="radio">
|
<div class="radio">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="permission" value="pull" checked="">
|
<input type="radio" name="permission" value="read" checked="">
|
||||||
<strong>Read & Clone</strong>
|
<strong>Read Access</strong>
|
||||||
</label>
|
</label>
|
||||||
<p>This team will be able to view and clone its repositories.</p>
|
<p>This team will be able to view and clone its repositories.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="radio">
|
<div class="radio">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="permission" value="push">
|
<input type="radio" name="permission" value="write">
|
||||||
<strong>Push, Read & Clone</strong>
|
<strong>Write Access</strong>
|
||||||
</label>
|
</label>
|
||||||
<p>This team will be able to read its repositories, as well as push to them.</p>
|
<p>This team will be able to read its repositories, as well as push to them.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="radio">
|
<div class="radio">
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="permission" value="admin">
|
<input type="radio" name="permission" value="admin">
|
||||||
<strong>Collaboration, Push, Read & Clone</strong>
|
<strong>Admin Access</strong>
|
||||||
</label>
|
</label>
|
||||||
<p>This team will be able to push/pull to its repositories, as well as add other collaborators to them.</p>
|
<p>This team will be able to push/pull to its repositories, as well as add other collaborators to them.</p>
|
||||||
</div>
|
</div>
|
|
@ -18,6 +18,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="body" class="container">
|
<div id="body" class="container">
|
||||||
<div id="org">
|
<div id="org">
|
||||||
<div id="org-teams">
|
<div id="org-teams">
|
||||||
|
|
Loading…
Reference in a new issue