2014-08-26 14:11:15 +04:00
// 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 v1
import (
2014-08-29 07:24:37 +04:00
"fmt"
2014-08-26 14:11:15 +04:00
"path"
2014-08-29 07:24:37 +04:00
"strings"
2014-08-26 14:11:15 +04:00
"github.com/Unknwon/com"
2014-11-15 01:11:30 +03:00
api "github.com/gogits/go-gogs-client"
2014-08-26 14:11:15 +04:00
"github.com/gogits/gogs/models"
2014-08-29 07:24:37 +04:00
"github.com/gogits/gogs/modules/auth"
2014-11-17 05:32:26 +03:00
"github.com/gogits/gogs/modules/base"
2014-08-29 07:24:37 +04:00
"github.com/gogits/gogs/modules/log"
2014-08-26 14:11:15 +04:00
"github.com/gogits/gogs/modules/middleware"
2014-11-13 10:32:18 +03:00
"github.com/gogits/gogs/modules/setting"
2014-08-26 14:11:15 +04:00
)
2014-12-13 04:30:32 +03:00
// ToApiRepository converts repository to API format.
func ToApiRepository ( owner * models . User , repo * models . Repository , permission api . Permission ) * api . Repository {
2014-12-14 00:46:00 +03:00
cl , err := repo . CloneLink ( )
if err != nil {
log . Error ( 4 , "CloneLink: %v" , err )
2014-12-13 04:30:32 +03:00
}
return & api . Repository {
Id : repo . Id ,
Owner : * ToApiUser ( owner ) ,
FullName : owner . Name + "/" + repo . Name ,
Private : repo . IsPrivate ,
Fork : repo . IsFork ,
2014-12-14 00:46:00 +03:00
HtmlUrl : setting . AppUrl + owner . Name + "/" + repo . Name ,
CloneUrl : cl . HTTPS ,
SshUrl : cl . SSH ,
2014-12-13 04:30:32 +03:00
Permissions : permission ,
}
}
2014-08-26 14:11:15 +04:00
func SearchRepos ( ctx * middleware . Context ) {
opt := models . SearchOption {
Keyword : path . Base ( ctx . Query ( "q" ) ) ,
Uid : com . StrTo ( ctx . Query ( "uid" ) ) . MustInt64 ( ) ,
Limit : com . StrTo ( ctx . Query ( "limit" ) ) . MustInt ( ) ,
}
if opt . Limit == 0 {
opt . Limit = 10
}
2014-10-25 15:50:19 +04:00
// Check visibility.
if ctx . IsSigned && opt . Uid > 0 {
if ctx . User . Id == opt . Uid {
opt . Private = true
} else {
u , err := models . GetUserById ( opt . Uid )
if err != nil {
ctx . JSON ( 500 , map [ string ] interface { } {
"ok" : false ,
"error" : err . Error ( ) ,
} )
return
}
2014-12-13 04:30:32 +03:00
if u . IsOrganization ( ) && u . IsOwnedBy ( ctx . User . Id ) {
2014-10-25 15:50:19 +04:00
opt . Private = true
}
// FIXME: how about collaborators?
}
}
2014-08-26 14:11:15 +04:00
repos , err := models . SearchRepositoryByName ( opt )
if err != nil {
ctx . JSON ( 500 , map [ string ] interface { } {
"ok" : false ,
"error" : err . Error ( ) ,
} )
return
}
2014-11-15 01:11:30 +03:00
results := make ( [ ] * api . Repository , len ( repos ) )
2014-08-26 14:11:15 +04:00
for i := range repos {
if err = repos [ i ] . GetOwner ( ) ; err != nil {
ctx . JSON ( 500 , map [ string ] interface { } {
"ok" : false ,
"error" : err . Error ( ) ,
} )
return
}
2014-11-15 01:11:30 +03:00
results [ i ] = & api . Repository {
2014-11-13 10:32:18 +03:00
Id : repos [ i ] . Id ,
FullName : path . Join ( repos [ i ] . Owner . Name , repos [ i ] . Name ) ,
2014-08-26 14:11:15 +04:00
}
}
2014-12-13 04:30:32 +03:00
ctx . JSON ( 200 , map [ string ] interface { } {
2014-08-26 14:11:15 +04:00
"ok" : true ,
"data" : results ,
} )
}
2014-08-29 07:24:37 +04:00
2014-12-13 04:30:32 +03:00
func createRepo ( ctx * middleware . Context , owner * models . User , opt api . CreateRepoOption ) {
repo , err := models . CreateRepository ( owner , opt . Name , opt . Description ,
opt . Gitignore , opt . License , opt . Private , false , opt . AutoInit )
if err != nil {
if err == models . ErrRepoAlreadyExist ||
err == models . ErrRepoNameIllegal {
ctx . JSON ( 422 , & base . ApiJsonErr { err . Error ( ) , base . DOC_URL } )
} else {
log . Error ( 4 , "CreateRepository: %v" , err )
if repo != nil {
if err = models . DeleteRepository ( ctx . User . Id , repo . Id , ctx . User . Name ) ; err != nil {
log . Error ( 4 , "DeleteRepository: %v" , err )
}
}
ctx . Error ( 500 )
}
return
}
ctx . JSON ( 200 , ToApiRepository ( owner , repo , api . Permission { true , true , true } ) )
}
// POST /user/repos
// https://developer.github.com/v3/repos/#create
func CreateRepo ( ctx * middleware . Context , opt api . CreateRepoOption ) {
// Shouldn't reach this condition, but just in case.
if ctx . User . IsOrganization ( ) {
ctx . JSON ( 422 , "not allowed creating repository for organization" )
return
}
createRepo ( ctx , ctx . User , opt )
}
// POST /orgs/:org/repos
// https://developer.github.com/v3/repos/#create
func CreateOrgRepo ( ctx * middleware . Context , opt api . CreateRepoOption ) {
org , err := models . GetOrgByName ( ctx . Params ( ":org" ) )
if err != nil {
if err == models . ErrUserNotExist {
ctx . Error ( 404 )
} else {
ctx . Error ( 500 )
}
return
}
if ! org . IsOwnedBy ( ctx . User . Id ) {
ctx . Error ( 403 )
return
}
createRepo ( ctx , org , opt )
}
func MigrateRepo ( ctx * middleware . Context , form auth . MigrateRepoForm ) {
2014-08-29 13:31:53 +04:00
u , err := models . GetUserByName ( ctx . Query ( "username" ) )
if err != nil {
ctx . JSON ( 500 , map [ string ] interface { } {
"ok" : false ,
"error" : err . Error ( ) ,
} )
return
}
if ! u . ValidtePassword ( ctx . Query ( "password" ) ) {
ctx . JSON ( 500 , map [ string ] interface { } {
"ok" : false ,
"error" : "username or password is not correct" ,
} )
return
}
ctxUser := u
2014-08-29 07:24:37 +04:00
// Not equal means current user is an organization.
2014-08-29 13:31:53 +04:00
if form . Uid != u . Id {
2014-08-29 07:24:37 +04:00
org , err := models . GetUserById ( form . Uid )
2014-08-29 13:31:53 +04:00
if err != nil {
2014-12-13 04:30:32 +03:00
log . Error ( 4 , "GetUserById: %v" , err )
ctx . Error ( 500 )
2014-08-29 07:24:37 +04:00
return
}
ctxUser = org
}
if ctx . HasError ( ) {
2014-12-13 04:30:32 +03:00
ctx . JSON ( 422 , map [ string ] interface { } {
2014-08-29 13:31:53 +04:00
"ok" : false ,
"error" : ctx . GetErrMsg ( ) ,
2014-08-29 07:24:37 +04:00
} )
return
}
if ctxUser . IsOrganization ( ) {
// Check ownership of organization.
2014-12-13 04:30:32 +03:00
if ! ctxUser . IsOwnedBy ( u . Id ) {
2014-08-29 07:24:37 +04:00
ctx . JSON ( 403 , map [ string ] interface { } {
2014-08-29 13:31:53 +04:00
"ok" : false ,
"error" : "given user is not owner of organization" ,
2014-08-29 07:24:37 +04:00
} )
return
}
}
authStr := strings . Replace ( fmt . Sprintf ( "://%s:%s" ,
form . AuthUserName , form . AuthPasswd ) , "@" , "%40" , - 1 )
url := strings . Replace ( form . HttpsUrl , "://" , authStr + "@" , 1 )
repo , err := models . MigrateRepository ( ctxUser , form . RepoName , form . Description , form . Private ,
form . Mirror , url )
if err == nil {
log . Trace ( "Repository migrated: %s/%s" , ctxUser . Name , form . RepoName )
2014-08-29 13:31:53 +04:00
ctx . JSON ( 200 , map [ string ] interface { } {
"ok" : true ,
"data" : "/" + ctxUser . Name + "/" + form . RepoName ,
2014-08-29 07:24:37 +04:00
} )
return
}
if repo != nil {
if errDelete := models . DeleteRepository ( ctxUser . Id , repo . Id , ctxUser . Name ) ; errDelete != nil {
log . Error ( 4 , "DeleteRepository: %v" , errDelete )
}
}
ctx . JSON ( 500 , map [ string ] interface { } {
2014-08-29 13:31:53 +04:00
"ok" : false ,
"error" : err . Error ( ) ,
2014-08-29 07:24:37 +04:00
} )
}
2014-11-13 10:32:18 +03:00
2014-11-13 20:57:00 +03:00
// GET /user/repos
// https://developer.github.com/v3/repos/#list-your-repositories
2014-11-13 10:32:18 +03:00
func ListMyRepos ( ctx * middleware . Context ) {
ownRepos , err := models . GetRepositories ( ctx . User . Id , true )
if err != nil {
2014-11-17 05:32:26 +03:00
ctx . JSON ( 500 , & base . ApiJsonErr { "GetRepositories: " + err . Error ( ) , base . DOC_URL } )
2014-11-13 10:32:18 +03:00
return
}
numOwnRepos := len ( ownRepos )
collaRepos , err := models . GetCollaborativeRepos ( ctx . User . Name )
if err != nil {
2014-11-17 05:32:26 +03:00
ctx . JSON ( 500 , & base . ApiJsonErr { "GetCollaborativeRepos: " + err . Error ( ) , base . DOC_URL } )
2014-11-13 10:32:18 +03:00
return
}
2014-11-15 01:11:30 +03:00
repos := make ( [ ] * api . Repository , numOwnRepos + len ( collaRepos ) )
2014-11-13 10:32:18 +03:00
for i := range ownRepos {
2014-12-13 04:30:32 +03:00
repos [ i ] = ToApiRepository ( ctx . User , ownRepos [ i ] , api . Permission { true , true , true } )
2014-11-13 10:32:18 +03:00
}
for i := range collaRepos {
if err = collaRepos [ i ] . GetOwner ( ) ; err != nil {
2014-11-17 05:32:26 +03:00
ctx . JSON ( 500 , & base . ApiJsonErr { "GetOwner: " + err . Error ( ) , base . DOC_URL } )
2014-11-13 10:32:18 +03:00
return
}
j := i + numOwnRepos
2014-12-13 04:30:32 +03:00
repos [ j ] = ToApiRepository ( collaRepos [ i ] . Owner , collaRepos [ i ] . Repository , api . Permission { false , collaRepos [ i ] . CanPush , true } )
2014-11-13 10:32:18 +03:00
// FIXME: cache result to reduce DB query?
2014-12-13 04:30:32 +03:00
if collaRepos [ i ] . Owner . IsOrganization ( ) && collaRepos [ i ] . Owner . IsOwnedBy ( ctx . User . Id ) {
2014-11-13 10:32:18 +03:00
repos [ j ] . Permissions . Admin = true
}
}
ctx . JSON ( 200 , & repos )
}