#1692 add user email APIs

This commit is contained in:
Unknwon 2015-12-15 22:57:18 -05:00
parent 7786cb76f3
commit b117befc2b
9 changed files with 131 additions and 16 deletions

View file

@ -3,7 +3,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) ![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
##### Current version: 0.8.6 ##### Current version: 0.8.7
| Web | UI | Preview | | Web | UI | Preview |
|:-------------:|:-------:|:-------:| |:-------------:|:-------:|:-------:|

View file

@ -18,7 +18,7 @@ import (
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
const APP_VER = "0.8.6.1215" const APP_VER = "0.8.7.1215"
func init() { func init() {
runtime.GOMAXPROCS(runtime.NumCPU()) runtime.GOMAXPROCS(runtime.NumCPU())

View file

@ -888,7 +888,7 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) {
} }
func AddEmailAddress(email *EmailAddress) error { func AddEmailAddress(email *EmailAddress) error {
email.Email = strings.ToLower(email.Email) email.Email = strings.ToLower(strings.TrimSpace(email.Email))
used, err := IsEmailUsed(email.Email) used, err := IsEmailUsed(email.Email)
if err != nil { if err != nil {
return err return err
@ -900,6 +900,29 @@ func AddEmailAddress(email *EmailAddress) error {
return err return err
} }
func AddEmailAddresses(emails []*EmailAddress) error {
if len(emails) == 0 {
return nil
}
// Check if any of them has been used
for i := range emails {
emails[i].Email = strings.ToLower(strings.TrimSpace(emails[i].Email))
used, err := IsEmailUsed(emails[i].Email)
if err != nil {
return err
} else if used {
return ErrEmailAlreadyUsed{emails[i].Email}
}
}
if _, err := x.Insert(emails); err != nil {
return fmt.Errorf("Insert: %v", err)
}
return nil
}
func (email *EmailAddress) Activate() error { func (email *EmailAddress) Activate() error {
email.IsActivated = true email.IsActivated = true
if _, err := x.Id(email.ID).AllCols().Update(email); err != nil { if _, err := x.Id(email.ID).AllCols().Update(email); err != nil {
@ -914,20 +937,23 @@ func (email *EmailAddress) Activate() error {
} }
} }
func DeleteEmailAddress(email *EmailAddress) error { func DeleteEmailAddress(email *EmailAddress) (err error) {
has, err := x.Get(email) if email.ID > 0 {
if err != nil { _, err = x.Id(email.ID).Delete(new(EmailAddress))
} else {
_, err = x.Where("email=?", email.Email).Delete(new(EmailAddress))
}
return err return err
} else if !has {
return ErrEmailNotExist
} }
if _, err = x.Id(email.ID).Delete(email); err != nil { func DeleteEmailAddresses(emails []*EmailAddress) (err error) {
for i := range emails {
if err = DeleteEmailAddress(emails[i]); err != nil {
return err return err
} }
}
return nil return nil
} }
func MakeEmailPrimary(email *EmailAddress) error { func MakeEmailPrimary(email *EmailAddress) error {

View file

@ -4304,7 +4304,7 @@ func confLicenseMozillaPublicLicense20() (*asset, error) {
return a, nil return a, nil
} }
var _confLocaleTranslators = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\x54\x4d\x6f\xdb\x46\x10\xbd\xf3\x57\x0c\x90\x73\x8d\xa0\x45\xd1\x06\x20\x04\xc8\x76\x93\x58\xb1\xe4\x02\x52\x53\xf8\x38\x22\x97\xdc\x11\xf7\x43\xd9\x5d\x52\xa2\x6e\xfd\x25\x3d\xf7\x98\x4b\xd1\xbb\xe3\xff\xd5\x19\x52\x56\x85\x5a\x07\x89\xcb\xb7\x6f\x76\x66\xe7\xbd\xe1\x1b\x58\x69\x8a\x50\x91\x51\x60\x28\xa6\x08\x68\x0c\xfc\xfa\xdb\xf5\xfd\xdd\x0d\x90\x2b\xa9\xa3\xb2\x45\x13\x41\x63\x47\xae\x86\xc2\xbb\x14\x68\xdd\x26\x55\x0e\x6b\xe5\x12\x24\x0f\x49\x2b\x48\x01\x5d\x34\x98\xc8\xbb\xab\xec\x0d\xfc\x22\x44\xc5\xe7\x05\xc5\x07\xf1\xb1\x5b\x8d\x6b\x95\xa8\x40\x03\x3e\x94\x2a\x5c\x65\xd9\xb4\x21\x4d\xc1\xc3\xe3\xf4\xc3\x74\x39\xfd\x74\x07\x79\x8f\x75\xdd\xa7\xa4\x02\x4c\x57\x60\xbd\x25\xac\x15\xdc\x3e\xac\x38\x99\x9d\x64\x53\xa3\xf6\xe8\x38\x16\x96\x49\x91\xd3\x4f\x7f\x57\xbc\xce\x1b\x2e\x04\x9b\x24\x21\x66\xff\x5d\x1c\xf8\xa5\x3a\xd1\xb9\x80\x39\xd6\xce\x43\x8e\x27\x40\x28\x76\x6d\x25\xa4\xb6\x48\xe6\x2c\x87\xec\xf7\xb0\x50\x41\xee\x9b\xe3\xf8\xca\x3c\x37\x22\x47\xe2\xf0\x5c\x07\xe6\x87\xa4\x5b\x2e\x97\xaf\xee\x7a\x74\x1c\x31\x02\xb2\x3f\xe6\xc1\x97\xad\xd7\xc9\xae\x31\x7c\xfb\xfa\xfc\x27\x4c\x43\x89\xf0\xf8\xed\xab\xb1\x78\x90\x13\x4a\xec\x49\xd6\x35\xda\xb1\x15\xff\x8b\xbb\xd1\x81\xc5\xf2\x5b\x0d\x9f\x28\x56\xca\x94\x90\x17\x27\x48\x58\xcd\x11\xbe\x10\xda\x47\xf2\x5c\x50\x99\xdd\xa2\x23\x65\x60\xb9\x55\x54\x68\x15\x12\xe4\xe5\x88\x70\x50\x3c\x81\x12\xb8\x35\x93\xec\xd6\x12\x0b\xca\x8d\xf1\x35\xf6\x90\x5b\x25\xb4\x02\xd3\x4e\xfb\xc2\x97\xe3\x4d\x6b\x9c\x64\x1f\x82\xaa\x3d\x0b\x84\x2e\x39\x11\xa7\x2e\x55\x37\x28\x43\x9d\x3a\x29\xf3\x11\x2d\x95\xf0\x5e\xd1\x01\xd7\x58\x12\xe4\x5a\x80\xea\x70\x49\x90\x8f\x2d\x59\x36\xd0\xef\x28\x72\xec\xf8\x5f\xdb\xef\xdf\xbe\x7d\x27\x4c\xed\xd3\x19\x77\x78\x6c\xb6\x93\x8c\x4c\xe3\xb3\x3b\xd3\x23\xeb\xde\x60\xf0\x5d\x76\x8f\x55\xa0\x26\x42\x6e\x8e\x8b\xd7\x69\xee\xb1\x0d\x04\x0f\x1b\x36\x31\x75\x2d\xe4\x7b\xe1\xec\x55\xfa\x69\xa0\xf8\x50\x33\xa5\x2d\xc4\x78\x5b\x6e\xd2\x2e\x36\x5c\xb5\x61\x40\x9a\x75\x86\x09\xb9\x62\x5b\xcc\x31\x30\xb9\xd0\x64\x8c\x74\xc1\xca\xab\x50\x5f\x10\xe1\x11\xa7\x9d\x53\xdd\x72\xcb\xb9\x81\x06\xe1\x26\xb4\x2c\xbf\x1d\x21\x19\x80\x22\xec\x47\xab\x72\xcf\xe6\x3e\xf0\xb8\xc1\xf2\xe9\x9f\xa0\x5c\xe4\x55\xde\x18\xb2\x3f\x5f\xd2\x78\xc1\xd7\xf6\xb0\xe2\x7f\x8b\x11\xd9\x50\xe9\xca\x22\x4f\x95\xbb\xe4\xc1\x05\x26\xf1\xa6\x59\xb7\x5f\x5a\x15\xf8\x07\xb9\x13\x08\xff\x43\x7e\xbc\x10\xf6\x50\x92\xf1\x0e\x66\xad\x23\x96\x3b\xf7\xe3\xeb\x20\xc1\x00\xbd\xfb\xe1\x42\xd0\x4a\x7b\xae\x08\xde\xa3\x73\x3c\x4b\x83\x3d\x7c\x3d\x0e\x6c\x1a\xb7\x38\xa6\x3a\xed\x0e\xd3\x93\x38\x4c\x86\x81\x8b\xbf\xc6\x42\x43\x9e\x8e\x6f\x4c\xf5\x6d\x32\xde\x37\x67\x09\xbc\x23\xf8\x2c\x2d\x76\x08\x33\xb2\x4f\x7f\x39\xc5\x2d\x4d\x0c\x77\x9b\x4b\xd7\xf8\x6c\xd8\x7f\x96\x02\x07\xc5\xe8\x5b\x93\xd8\xf5\x1d\xfb\xec\xcb\x4e\xf1\x77\xed\x35\xff\x71\xb6\xf4\x15\x8f\x4a\xbf\x89\xf2\x64\xc2\x71\x35\xcc\xc9\xe8\xf0\x86\xf5\x7f\xfe\xa3\x6d\x30\x1e\x60\xc6\xbd\x5d\x90\xb2\x24\x97\x35\x23\x26\x1f\x93\x23\xf4\x32\x5d\xff\x06\x00\x00\xff\xff\x63\x49\x8c\x8c\x88\x05\x00\x00") var _confLocaleTranslators = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\x54\x4d\x6f\xdb\x46\x10\xbd\xf3\x57\x0c\x90\x73\x8d\xa0\x45\xd1\x06\x20\x0c\xc8\x76\xe2\xd8\xf1\x47\x51\xab\x29\x7c\x1c\x91\x2b\x72\xc4\xfd\x90\xf7\x83\x16\x75\xeb\x2f\xe9\xb9\xc7\x5c\x8a\xde\x9d\xfc\xaf\xbe\x25\x65\xd5\xa8\x75\x90\x38\xfb\xf6\xcd\xce\xec\xcc\x9b\x7d\x43\xf3\x56\x02\x2d\x45\x2b\xd2\x12\x62\x20\xd6\x9a\x7e\xf9\xed\xe4\xea\xe2\x94\xc4\xd6\xd2\x4b\x9d\x58\x07\x6a\xb9\x17\xdb\x50\xe5\x6c\xf4\xb2\x48\x51\xd5\xa3\xad\x6c\xa4\xe8\x28\xb6\x8a\xa2\x67\x1b\x34\x47\x71\xf6\xa8\x78\x43\xef\x33\x51\xe1\x3c\xaf\x70\x10\x8e\x5d\xb7\xbc\x50\x51\x2a\xd6\xe4\x7c\xad\xfc\x51\x51\xcc\x3a\x69\xc5\x3b\xba\x9f\x9d\xcf\xee\x66\x9f\x2e\xa8\x1c\xb8\x69\x86\x18\x95\xa7\xd9\x9c\x8c\x33\xc2\x8d\xa2\xb3\xdb\x39\x82\x99\xe3\x62\xa6\x55\x17\xd4\x2a\xd0\xb9\x77\x95\xea\x03\x95\xfc\x8c\x80\xde\xec\xc0\x4c\x5f\x7b\x37\xd2\x37\x6c\x11\x8a\xee\xa2\x12\xdb\x3e\xfd\xbd\x84\x5d\x76\xc8\x9b\xbb\x98\x5d\xf4\xe6\xbb\x89\x5f\xab\x3d\x1d\xf9\x5e\x73\x63\xdd\x78\xf8\x0e\xc8\x14\xb3\x30\x63\x14\xc3\xa2\x5f\xa4\x94\xf7\x07\xba\x51\x3e\x97\xa7\xe4\x69\x09\x9e\x9d\x90\x1d\x71\xfc\x2e\x3c\xf8\x3e\xb6\x09\xb7\x43\xa5\xec\xc0\x16\x1e\x13\x90\xf7\xa7\x38\xfc\xbc\xf5\x3a\xd8\x09\xfb\xaf\x5f\xbe\xfd\x49\x33\x5f\x33\xdd\x7f\xfd\xa2\x0d\x6f\xf3\x09\x35\x0f\x92\xed\x86\xcd\x54\xb9\xff\xf9\x9d\xb6\x1e\xbd\x75\xeb\x96\x3e\x49\x58\x2a\x5d\x53\x59\xed\xa1\xcc\xea\x76\xf0\x01\xd7\x21\x88\x43\x42\x75\x71\xc6\x56\x94\xa6\xbb\xb5\x92\xaa\x55\x3e\x52\x59\x4f\x08\x9c\xc2\x1e\x1c\x8b\xaf\x8f\xc1\x86\x72\xe8\x7e\xcb\x4d\x12\x8f\x0a\x96\x75\x5f\x0f\x58\x1d\x08\x71\x66\x04\x52\x41\x0d\x5d\xc3\x03\x95\x46\x65\x4e\xc5\xf1\xb1\x75\x95\xab\xa7\xa2\x34\x7c\x5c\xbc\xdf\xaa\x87\x94\x03\x9e\x3b\xbb\x45\x6f\xb6\xf4\xab\x40\x4c\x65\xe3\xac\xcf\xc6\xeb\x93\xcf\xbd\x6a\x1c\xba\xcf\x36\xda\xdc\xf9\xa6\x56\xfd\xd8\x76\xe9\xd5\xbe\xed\x1f\xd9\x20\xd3\x0f\x4a\xb6\xbc\xe0\x5a\xa8\x6c\x33\xb0\xdc\x1e\xea\xf6\xc7\x24\x06\x62\xfe\x9d\x73\xaf\x1f\xf1\xdf\x9a\xef\xdf\xbe\x7d\x97\x99\xad\x8b\x2f\xb8\xe3\x67\xb5\x3e\x2e\x44\x77\xae\xb8\xd0\x03\x43\x54\x1d\x7b\xd7\x17\x57\xbc\xf4\xd2\x41\xbb\x7a\x67\xbc\x0e\x73\xc5\xc9\x0b\xdd\xae\x30\x50\xd2\x27\x2a\x37\x99\xb3\x51\xf1\xa7\x91\xe2\x7c\x03\x4a\xaa\xb2\xaa\xd7\xe8\xc0\x63\xe8\x90\xb5\x06\x90\x3b\xf1\x02\xcb\xe4\x25\x34\x77\xcd\x1e\xe4\xaa\x15\xad\x73\x15\x4c\x5e\x66\xea\x33\x92\x79\x82\xb0\xd7\xd2\x24\x94\x17\x25\xd7\x4c\xa7\x3e\x41\x5b\x66\x82\xf2\x30\x56\x7e\x33\xcd\x01\x6a\x76\xed\x3c\x46\x9f\xee\x9e\xfe\xf1\xca\x06\x58\x65\xa7\xc5\xfc\x7c\x48\x40\x37\xb8\xb6\xa3\x39\xfe\x0d\x07\x86\x5a\xe3\x91\x61\x4c\xb8\x3d\x24\xf0\x1b\x8e\x59\xf8\x7a\x91\x1e\x92\xf2\xf8\x51\x69\x33\xc4\xff\x21\x3f\x1e\x70\xbb\xad\x45\x3b\x4b\x97\xc9\x0a\xda\x5d\xba\x69\x39\xb6\x60\x84\xde\xfd\x70\xc0\x69\xde\x3a\x64\x44\x1f\xd8\x5a\x0c\xea\x28\x0f\xd7\x4c\xaf\x41\x9c\xb6\xe0\xb3\xdc\xef\x8e\xa3\x19\xe1\x96\x27\x0d\xc9\x9f\x70\xd5\x52\x19\x77\x2b\x50\x5d\x8a\xda\xb9\xee\x45\x00\x67\x85\x3e\xe7\x12\x5b\xa6\x4b\x31\x4f\x7f\x59\x68\xb6\x8c\x80\xfb\xd5\xa1\x6b\x7c\xd6\xd0\x9f\x11\x0f\xa7\x10\x5c\xd2\x11\x23\xd5\x43\x67\x0f\x8f\x0a\x6f\xec\x6b\xfe\xfd\xe5\x9d\x5b\x62\x0e\x87\x55\xc8\x5f\x10\x76\xd6\x38\x84\x93\xc2\x3b\xf4\xff\xdb\x1f\xa9\xe3\xb0\xa5\x4b\xd4\xf6\x46\x94\x91\x7c\x59\x3d\x61\xf9\xa5\xda\x41\xcf\xa3\xfb\x6f\x00\x00\x00\xff\xff\x09\xff\x40\x94\x14\x06\x00\x00")
func confLocaleTranslatorsBytes() ([]byte, error) { func confLocaleTranslatorsBytes() ([]byte, error) {
return bindataRead( return bindataRead(
@ -4319,7 +4319,7 @@ func confLocaleTranslators() (*asset, error) {
return nil, err return nil, err
} }
info := bindataFileInfo{name: "conf/locale/TRANSLATORS", size: 1416, mode: os.FileMode(420), modTime: time.Unix(1450224232, 0)} info := bindataFileInfo{name: "conf/locale/TRANSLATORS", size: 1556, mode: os.FileMode(420), modTime: time.Unix(1450231021, 0)}
a := &asset{bytes: bytes, info: info} a := &asset{bytes: bytes, info: info}
return a, nil return a, nil
} }

View file

@ -144,6 +144,9 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/:id").Get(user.GetPublicKey). m.Combo("/:id").Get(user.GetPublicKey).
Delete(user.DeletePublicKey) Delete(user.DeletePublicKey)
}) })
m.Combo("/emails").Get(user.ListEmails).
Post(bind(api.CreateEmailOption{}), user.AddEmail).
Delete(bind(api.CreateEmailOption{}), user.DeleteEmail)
}, ReqToken()) }, ReqToken())
// Repositories // Repositories

View file

@ -0,0 +1,78 @@
// Copyright 2015 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 user
import (
api "github.com/gogits/go-gogs-client"
"github.com/gogits/gogs/models"
"github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting"
to "github.com/gogits/gogs/routers/api/v1/utils"
)
func ListEmails(ctx *middleware.Context) {
emails, err := models.GetEmailAddresses(ctx.User.Id)
if err != nil {
ctx.Handle(500, "GetEmailAddresses", err)
return
}
apiEmails := make([]*api.Email, len(emails))
for i := range emails {
apiEmails[i] = to.ApiEmail(emails[i])
}
ctx.JSON(200, &apiEmails)
}
func AddEmail(ctx *middleware.Context, form api.CreateEmailOption) {
if len(form.Emails) == 0 {
ctx.Status(422)
return
}
emails := make([]*models.EmailAddress, len(form.Emails))
for i := range form.Emails {
emails[i] = &models.EmailAddress{
UID: ctx.User.Id,
Email: form.Emails[i],
IsActivated: !setting.Service.RegisterEmailConfirm,
}
}
if err := models.AddEmailAddresses(emails); err != nil {
if models.IsErrEmailAlreadyUsed(err) {
ctx.APIError(422, "", "Email address has been used: "+err.(models.ErrEmailAlreadyUsed).Email)
} else {
ctx.APIError(500, "AddEmailAddresses", err)
}
return
}
apiEmails := make([]*api.Email, len(emails))
for i := range emails {
apiEmails[i] = to.ApiEmail(emails[i])
}
ctx.JSON(201, &apiEmails)
}
func DeleteEmail(ctx *middleware.Context, form api.CreateEmailOption) {
if len(form.Emails) == 0 {
ctx.Status(204)
return
}
emails := make([]*models.EmailAddress, len(form.Emails))
for i := range form.Emails {
emails[i] = &models.EmailAddress{
Email: form.Emails[i],
}
}
if err := models.DeleteEmailAddresses(emails); err != nil {
ctx.APIError(500, "DeleteEmailAddresses", err)
return
}
ctx.Status(204)
}

View file

@ -26,6 +26,14 @@ func ApiUser(u *models.User) *api.User {
} }
} }
func ApiEmail(email *models.EmailAddress) *api.Email {
return &api.Email{
Email: email.Email,
Verified: email.IsActivated,
Primary: email.IsPrimary,
}
}
// ApiRepository converts repository to API format. // ApiRepository converts repository to API format.
func ApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository { func ApiRepository(owner *models.User, repo *models.Repository, permission api.Permission) *api.Repository {
cl := repo.CloneLink() cl := repo.CloneLink()

View file

@ -226,7 +226,7 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) {
e := &models.EmailAddress{ e := &models.EmailAddress{
UID: ctx.User.Id, UID: ctx.User.Id,
Email: strings.TrimSpace(form.Email), Email: form.Email,
IsActivated: !setting.Service.RegisterEmailConfirm, IsActivated: !setting.Service.RegisterEmailConfirm,
} }
if err := models.AddEmailAddress(e); err != nil { if err := models.AddEmailAddress(e); err != nil {

View file

@ -1 +1 @@
0.8.6.1215 0.8.7.1215