Merge branch 'master' of github.com:gogits/gogs
commit
f824d6a4b1
|
@ -17,6 +17,7 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, devel
|
|||
|
||||
## Features
|
||||
|
||||
- Activity timeline
|
||||
- SSH protocal support.
|
||||
- Register/delete account.
|
||||
- Create/delete public repository.
|
||||
|
|
|
@ -3,8 +3,8 @@ RUN_USER = lunny
|
|||
|
||||
[repository]
|
||||
ROOT = /Users/%(RUN_USER)s/git/gogs-repositories
|
||||
LANG_IGNS=Google Go|C|Python
|
||||
LICENSES=Apache v2 License|GPL v2|BSD (3-Clause) License
|
||||
LANG_IGNS=Google Go|C|Python|Ruby
|
||||
LICENSES=Apache v2 License|GPL v2|MIT License|BSD (3-Clause) License
|
||||
|
||||
[server]
|
||||
HTTP_ADDR =
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
*.gem
|
||||
*.rbc
|
||||
.bundle
|
||||
.config
|
||||
coverage
|
||||
InstalledFiles
|
||||
lib/bundler/man
|
||||
pkg
|
||||
rdoc
|
||||
spec/reports
|
||||
test/tmp
|
||||
test/version_tmp
|
||||
tmp
|
||||
|
||||
# YARD artifacts
|
||||
.yardoc
|
||||
_yardoc
|
||||
doc/
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
24
gogs.go
24
gogs.go
|
@ -7,7 +7,7 @@ package main
|
|||
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
// "os/user"
|
||||
"runtime"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
|
@ -20,21 +20,21 @@ import (
|
|||
// Test that go1.1 tag above is included in builds. main.go refers to this definition.
|
||||
const go11tag = true
|
||||
|
||||
const APP_VER = "0.0.8.0315"
|
||||
const APP_VER = "0.0.8.0316.1"
|
||||
|
||||
func init() {
|
||||
base.AppVer = APP_VER
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
||||
|
||||
func checkRunUser() bool {
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
// TODO: log
|
||||
return false
|
||||
}
|
||||
return u.Username == base.Cfg.MustValue("", "RUN_USER")
|
||||
}
|
||||
// func checkRunUser() bool {
|
||||
// u, err := user.Current()
|
||||
// if err != nil {
|
||||
// // TODO: log
|
||||
// return false
|
||||
// }
|
||||
// return u.Username == base.Cfg.MustValue("", "RUN_USER")
|
||||
// }
|
||||
|
||||
func main() {
|
||||
/*if !checkRunUser() {
|
||||
|
@ -51,8 +51,6 @@ func main() {
|
|||
CmdServ,
|
||||
CmdUpdate,
|
||||
}
|
||||
app.Flags = append(app.Flags, []cli.Flag{
|
||||
cli.BoolFlag{"noterm", "disable color output"},
|
||||
}...)
|
||||
app.Flags = append(app.Flags, []cli.Flag{}...)
|
||||
app.Run(os.Args)
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ func (a Action) GetRepoName() string {
|
|||
return a.RepoName
|
||||
}
|
||||
|
||||
// CommitRepoAction records action for commit repository.
|
||||
func CommitRepoAction(userId int64, userName string,
|
||||
repoId int64, repoName string, msg string) error {
|
||||
_, err := orm.InsertOne(&Action{
|
||||
|
@ -57,8 +58,7 @@ func CommitRepoAction(userId int64, userName string,
|
|||
return err
|
||||
}
|
||||
|
||||
// NewRepoAction inserts action for create repository.
|
||||
|
||||
// NewRepoAction records action for create repository.
|
||||
func NewRepoAction(user *User, repo *Repository) error {
|
||||
_, err := orm.InsertOne(&Action{
|
||||
UserId: user.Id,
|
||||
|
|
|
@ -1,21 +1,32 @@
|
|||
// 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 models
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
var (
|
||||
sshOpLocker = sync.Mutex{}
|
||||
//publicKeyRootPath string
|
||||
sshPath string
|
||||
appPath string
|
||||
tmplPublicKey = "### autogenerated by gitgos, DO NOT EDIT\n" +
|
||||
"command=\"%s serv key-%d\",no-port-forwarding," +
|
||||
sshPath string
|
||||
appPath string
|
||||
// "### autogenerated by gitgos, DO NOT EDIT\n"
|
||||
tmplPublicKey = "command=\"%s serv key-%d\",no-port-forwarding," +
|
||||
"no-X11-forwarding,no-agent-forwarding,no-pty %s\n"
|
||||
)
|
||||
|
||||
|
@ -47,29 +58,60 @@ func init() {
|
|||
}
|
||||
|
||||
type PublicKey struct {
|
||||
Id int64
|
||||
OwnerId int64 `xorm:"index"`
|
||||
Name string `xorm:"unique not null"`
|
||||
Content string `xorm:"text not null"`
|
||||
Created time.Time `xorm:"created"`
|
||||
Updated time.Time `xorm:"updated"`
|
||||
Id int64
|
||||
OwnerId int64 `xorm:"index"`
|
||||
Name string `xorm:"unique not null"`
|
||||
Fingerprint string
|
||||
Content string `xorm:"text not null"`
|
||||
Created time.Time `xorm:"created"`
|
||||
Updated time.Time `xorm:"updated"`
|
||||
}
|
||||
|
||||
var (
|
||||
ErrKeyAlreadyExist = errors.New("Public key already exist")
|
||||
)
|
||||
|
||||
func GenAuthorizedKey(keyId int64, key string) string {
|
||||
return fmt.Sprintf(tmplPublicKey, appPath, keyId, key)
|
||||
}
|
||||
|
||||
func AddPublicKey(key *PublicKey) error {
|
||||
_, err := orm.Insert(key)
|
||||
func AddPublicKey(key *PublicKey) (err error) {
|
||||
// Check if public key name has been used.
|
||||
has, err := orm.Get(key)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
return ErrKeyAlreadyExist
|
||||
}
|
||||
|
||||
// Calculate fingerprint.
|
||||
tmpPath := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond()),
|
||||
"id_rsa.pub")
|
||||
os.MkdirAll(path.Dir(tmpPath), os.ModePerm)
|
||||
f, err := os.Create(tmpPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if _, err = f.WriteString(key.Content); err != nil {
|
||||
return err
|
||||
}
|
||||
f.Close()
|
||||
stdout, _, err := com.ExecCmd("ssh-keygen", "-l", "-f", tmpPath)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(stdout) < 2 {
|
||||
return errors.New("Not enough output for calculating fingerprint")
|
||||
}
|
||||
key.Fingerprint = strings.Split(stdout, " ")[1]
|
||||
|
||||
// Save SSH key.
|
||||
if _, err = orm.Insert(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SaveAuthorizedKeyFile(key)
|
||||
if err != nil {
|
||||
_, err2 := orm.Delete(key)
|
||||
if err2 != nil {
|
||||
// TODO: log the error
|
||||
if err = SaveAuthorizedKeyFile(key); err != nil {
|
||||
if _, err2 := orm.Delete(key); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -77,9 +119,71 @@ func AddPublicKey(key *PublicKey) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func DeletePublicKey(key *PublicKey) error {
|
||||
_, err := orm.Delete(key)
|
||||
return err
|
||||
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
|
||||
func DeletePublicKey(key *PublicKey) (err error) {
|
||||
has, err := orm.Id(key.Id).Get(key)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return errors.New("Public key does not exist")
|
||||
}
|
||||
if _, err = orm.Delete(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
|
||||
p := filepath.Join(sshPath, "authorized_keys")
|
||||
tmpP := filepath.Join(sshPath, "authorized_keys.tmp")
|
||||
fr, err := os.Open(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
fw, err := os.Create(tmpP)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
buf := bufio.NewReader(fr)
|
||||
for {
|
||||
line, errRead := buf.ReadString('\n')
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if errRead != nil {
|
||||
if errRead != io.EOF {
|
||||
return errRead
|
||||
}
|
||||
|
||||
// Reached end of file, if nothing to read then break,
|
||||
// otherwise handle the last line.
|
||||
if len(line) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Found the line and copy rest of file.
|
||||
if strings.Contains(line, fmt.Sprintf("key-%d", key.Id)) && strings.Contains(line, key.Content) {
|
||||
continue
|
||||
}
|
||||
// Still finding the line, copy the line that currently read.
|
||||
if _, err = fw.WriteString(line + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if errRead == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.Remove(p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Rename(tmpP, p)
|
||||
}
|
||||
|
||||
func ListPublicKey(userId int64) ([]PublicKey, error) {
|
||||
|
@ -89,11 +193,16 @@ func ListPublicKey(userId int64) ([]PublicKey, error) {
|
|||
}
|
||||
|
||||
func SaveAuthorizedKeyFile(key *PublicKey) error {
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
|
||||
p := filepath.Join(sshPath, "authorized_keys")
|
||||
f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
//os.Chmod(p, 0600)
|
||||
_, err = f.WriteString(GenAuthorizedKey(key.Id, key.Content))
|
||||
return err
|
||||
|
|
|
@ -264,7 +264,7 @@ func GetRepositoryById(id int64) (repo *Repository, err error) {
|
|||
// GetRepositories returns the list of repositories of given user.
|
||||
func GetRepositories(user *User) ([]Repository, error) {
|
||||
repos := make([]Repository, 0, 10)
|
||||
err := orm.Find(&repos, &Repository{OwnerId: user.Id})
|
||||
err := orm.Desc("updated").Find(&repos, &Repository{OwnerId: user.Id})
|
||||
return repos, err
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ func UpdateUser(user *User) (err error) {
|
|||
|
||||
// DeleteUser completely deletes everything of the user.
|
||||
func DeleteUser(user *User) error {
|
||||
// Check ownership of repository.
|
||||
count, err := GetRepositoryCount(user)
|
||||
if err != nil {
|
||||
return errors.New("modesl.GetRepositories: " + err.Error())
|
||||
|
@ -151,6 +152,22 @@ func DeleteUser(user *User) error {
|
|||
|
||||
// TODO: check issues, other repos' commits
|
||||
|
||||
// Delete all feeds.
|
||||
if _, err = orm.Delete(&Action{UserId: user.Id}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete all SSH keys.
|
||||
keys := make([]PublicKey, 0, 10)
|
||||
if err = orm.Find(&keys, &PublicKey{OwnerId: user.Id}); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, key := range keys {
|
||||
if err = DeletePublicKey(&key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = orm.Delete(user)
|
||||
// TODO: delete and update follower information.
|
||||
return err
|
||||
|
@ -158,8 +175,8 @@ func DeleteUser(user *User) error {
|
|||
|
||||
// EncodePasswd encodes password to safe format.
|
||||
func (user *User) EncodePasswd() error {
|
||||
newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(UserPasswdSalt), 16384, 8, 1, 64)
|
||||
user.Passwd = fmt.Sprintf("%x", newPasswd)
|
||||
var err error
|
||||
user.Passwd, err = EncodePasswd(user.Passwd)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -167,6 +184,14 @@ func UserPath(userName string) string {
|
|||
return filepath.Join(RepoRootPath, userName)
|
||||
}
|
||||
|
||||
func EncodePasswd(rawPasswd string) (string, error) {
|
||||
newPasswd, err := scrypt.Key([]byte(rawPasswd), []byte(UserPasswdSalt), 16384, 8, 1, 64)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%x", newPasswd), nil
|
||||
}
|
||||
|
||||
func GetUserByKeyId(keyId int64) (*User, error) {
|
||||
user := new(User)
|
||||
has, err := orm.Sql("select a.* from user as a, public_key as b where a.id = b.owner_id and b.id=?", keyId).Get(user)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/codegangsta/martini"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
|
@ -31,9 +33,7 @@ func RepoAssignment(redirect bool) martini.Handler {
|
|||
ctx.Render.Redirect("/")
|
||||
return
|
||||
}
|
||||
//data["ErrorMsg"] = err
|
||||
//log.Error("repo.Single: %v", err)
|
||||
//r.HTML(200, "base/error", data)
|
||||
ctx.Handle(200, "RepoAssignment", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
@ -45,9 +45,7 @@ func RepoAssignment(redirect bool) martini.Handler {
|
|||
ctx.Render.Redirect("/")
|
||||
return
|
||||
}
|
||||
//data["ErrorMsg"] = "invliad user account for single repository"
|
||||
//log.Error("repo.Single: %v", err)
|
||||
//r.HTML(200, "base/error", data)
|
||||
ctx.Handle(200, "RepoAssignment", errors.New("invliad user account for single repository"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -60,9 +58,7 @@ func RepoAssignment(redirect bool) martini.Handler {
|
|||
ctx.Render.Redirect("/")
|
||||
return
|
||||
}
|
||||
//data["ErrorMsg"] = err
|
||||
//log.Error("repo.Single: %v", err)
|
||||
//r.HTML(200, "base/error", data)
|
||||
ctx.Handle(200, "RepoAssignment", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -302,32 +302,23 @@ html, body {
|
|||
/* gogits user ssh keys */
|
||||
|
||||
#gogs-ssh-keys .list-group-item {
|
||||
line-height: 48px;
|
||||
padding: 15px 0;
|
||||
border-bottom: 1px solid #DDD;
|
||||
}
|
||||
|
||||
#gogs-ssh-keys .list-group-item .delete {
|
||||
margin: -5px 50px 0;
|
||||
}
|
||||
|
||||
#gogs-ssh-keys .list-group-item:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#gogs-ssh-keys .list-group-item:hover a.delete {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#gogs-ssh-keys .name {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#gogs-ssh-keys .list-group-item a.delete {
|
||||
float: right;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
margin-top: 10px;
|
||||
border-radius: 3px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#gogs-ssh-keys .print {
|
||||
padding-left: 1em;
|
||||
color: #888;
|
||||
|
@ -472,56 +463,6 @@ html, body {
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
/* #gogs-source */
|
||||
|
||||
#gogs-source-toolbar:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#gogs-source-toolbar .branch-switch {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#gogs-source-toolbar .breadcrumb {
|
||||
margin: 0 .5em;
|
||||
font-size: 16px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#gogs-source-table {
|
||||
margin-top: 1.5em;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#gogs-source-table .fa{
|
||||
font-size: 15px;
|
||||
width: 16px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#gogs-source-table .name{
|
||||
width: 160px;
|
||||
}
|
||||
|
||||
#gogs-source-table .size{
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
#gogs-source-table .date{
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
#gogs-source-table .is-dir .name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#gogs-source-table.table-hover > tbody > tr:hover > td {
|
||||
background-color: #FEFEFE;
|
||||
}
|
||||
|
||||
.activity-list {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
@ -583,6 +524,70 @@ html, body {
|
|||
color: #999;
|
||||
}
|
||||
|
||||
/* #gogs-source */
|
||||
#gogs-source .source-toolbar:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
#gogs-source .source-toolbar .branch-switch {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#gogs-source .source-toolbar .breadcrumb {
|
||||
margin: 0 .5em;
|
||||
padding: 6px 15px;
|
||||
font-size: 16px;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#gogs-source .source-toolbar,
|
||||
#gogs-source .info-box,
|
||||
#gogs-source .file-content {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.info-box .info-head,
|
||||
.info-box .info-content {
|
||||
padding: 9px 20px;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.file-list .icon {
|
||||
font-size: 17px;
|
||||
padding: 5px 0 4px 10px;
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
.file-list .wrap {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: top;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.file-list .name .wrap {
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
.file-list .text .wrap {
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.file-list .date .wrap {
|
||||
max-width: 100px;
|
||||
padding: 0 20px 0 0;
|
||||
}
|
||||
|
||||
.file-list .date {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
min-height: 100%;
|
||||
height: auto !important;
|
||||
|
|
|
@ -99,15 +99,16 @@ function initRegister() {
|
|||
}
|
||||
|
||||
function initUserSetting(){
|
||||
$('#gogs-ssh-keys').on("click",".delete",function(){
|
||||
var $this = $(this);
|
||||
Gogits.ajaxDelete("",{"id":$this.data("del")},function(json){
|
||||
if(json.ok){
|
||||
window.location.reload();
|
||||
}else{
|
||||
alert(json.err);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
$('#gogs-ssh-keys .delete').confirmation({
|
||||
singleton: true,
|
||||
onConfirm: function(e, $this){
|
||||
Gogits.ajaxDelete("",{"id":$this.data("del")},function(json){
|
||||
if(json.ok){
|
||||
window.location.reload();
|
||||
}else{
|
||||
alert(json.err);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -17,3 +17,7 @@ func Home(ctx *middleware.Context) {
|
|||
ctx.Data["PageIsHome"] = true
|
||||
ctx.Render.HTML(200, "home", ctx.Data)
|
||||
}
|
||||
|
||||
func Help(ctx *middleware.Context) string {
|
||||
return "This is help page"
|
||||
}
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
// 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 repo
|
||||
|
||||
import (
|
||||
|
@ -60,3 +64,15 @@ func Setting(ctx *middleware.Context) {
|
|||
ctx.Data["IsRepoToolbarSetting"] = true
|
||||
ctx.Render.HTML(200, "repo/setting", ctx.Data)
|
||||
}
|
||||
|
||||
func Commits(ctx *middleware.Context) string {
|
||||
return "This is commits page"
|
||||
}
|
||||
|
||||
func Issues(ctx *middleware.Context) string {
|
||||
return "This is issues page"
|
||||
}
|
||||
|
||||
func Pulls(ctx *middleware.Context) string {
|
||||
return "This is pulls page"
|
||||
}
|
||||
|
|
|
@ -128,6 +128,10 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
|
|||
}
|
||||
|
||||
if err := models.AddPublicKey(k); err != nil {
|
||||
if err.Error() == models.ErrKeyAlreadyExist.Error() {
|
||||
ctx.RenderWithErr("Public key name has been used", "user/publickey", &form)
|
||||
return
|
||||
}
|
||||
ctx.Handle(200, "ssh.AddPublicKey", err)
|
||||
return
|
||||
} else {
|
||||
|
|
|
@ -157,13 +157,23 @@ func Delete(ctx *middleware.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := models.DeleteUser(ctx.User); err != nil {
|
||||
rawPasswd := ctx.Query("password")
|
||||
encodedPwd, _ := models.EncodePasswd(rawPasswd)
|
||||
if len(encodedPwd) == 0 || encodedPwd != ctx.User.Passwd {
|
||||
ctx.Data["HasError"] = true
|
||||
switch err.Error() {
|
||||
case models.ErrUserOwnRepos.Error():
|
||||
ctx.Data["ErrorMsg"] = "Your account still have ownership of repository, you have to delete or transfer them first."
|
||||
default:
|
||||
ctx.Handle(200, "user.Delete", err)
|
||||
ctx.Data["ErrorMsg"] = "Your password error. Make sure you are owner of this account."
|
||||
} else {
|
||||
if err := models.DeleteUser(ctx.User); err != nil {
|
||||
ctx.Data["HasError"] = true
|
||||
switch err {
|
||||
case models.ErrUserOwnRepos:
|
||||
ctx.Data["ErrorMsg"] = "Your account still have ownership of repository, you have to delete or transfer them first."
|
||||
default:
|
||||
ctx.Handle(200, "user.Delete", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
ctx.Render.Redirect("/")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -189,3 +199,15 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
|
|||
}
|
||||
ctx.Render.JSON(200, &feeds)
|
||||
}
|
||||
|
||||
func Issues(ctx *middleware.Context) string {
|
||||
return "This is issues page"
|
||||
}
|
||||
|
||||
func Pulls(ctx *middleware.Context) string {
|
||||
return "This is pulls page"
|
||||
}
|
||||
|
||||
func Stars(ctx *middleware.Context) string {
|
||||
return "This is stars page"
|
||||
}
|
||||
|
|
2
serve.go
2
serve.go
|
@ -58,7 +58,7 @@ func runServ(*cli.Context) {
|
|||
|
||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||
if cmd == "" {
|
||||
println("Hi ", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
|
||||
println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
<nav class="gogs-nav">
|
||||
<a id="gogs-nav-logo" class="gogs-nav-item{{if .PageIsHome}} active{{end}}" href="/"><img src="/img/favicon.png" alt="Gogs Logo" id="gogs-logo"></a>
|
||||
<a class="gogs-nav-item{{if .PageIsUserDashboard}} active{{end}}" href="/">Dashboard</a>
|
||||
<a class="gogs-nav-item" href="#">Explore</a>
|
||||
<a class="gogs-nav-item" href="#">Help</a>{{if .IsSigned}}
|
||||
<a class="gogs-nav-item" href="/help">Help</a>{{if .IsSigned}}
|
||||
<a id="gogs-nav-out" class="gogs-nav-item navbar-right navbar-btn btn btn-danger" href="/user/logout/"><i class="fa fa-power-off fa-lg"></i></a>
|
||||
<a id="gogs-nav-avatar" class="gogs-nav-item navbar-right" href="{{.SignedUser.HomeLink}}" data-toggle="tooltip" data-placement="bottom" title="{{.SignedUserName}}">
|
||||
<img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username"/>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="initReadme">
|
||||
<input type="checkbox" name="initReadme" {{if .initReadme}}checked{{end}}>
|
||||
<strong>Initialize this repository with a README</strong>
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</div>
|
||||
<div id="gogs-repo-setting-container" class="col-md-9 tab-content">
|
||||
<div id="options" class="tab-pane">
|
||||
repo-options
|
||||
<h4>Repository Options</h4>
|
||||
</div>
|
||||
<div id="delete" class="tab-pane">
|
||||
<h4>Delete Repository</h4>
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
{{template "repo/toolbar" .}}
|
||||
<div id="gogs-body" class="container">
|
||||
<div id="gogs-source">
|
||||
<div id="gogs-source-toolbar">
|
||||
<div class="source-toolbar">
|
||||
<button class="btn btn-default pull-right"><i class="fa fa-plus-square"></i>Add File</button>
|
||||
<div class="dropdown branch-switch">
|
||||
<a href="#" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><i class="fa fa-chain"></i>master
|
||||
<b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="current" href="/{{.RepositoryLink}}/branch/master">master</a></li>
|
||||
<li><a href="//{{.RepositoryLink}}/branch/develop">develop</a></li>
|
||||
<li><a class="current" href="/{{.RepositoryLink}}/tree/master">master</a></li>
|
||||
<li><a href="/{{.RepositoryLink}}/tree/develop">develop</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{{$paths := .Paths}}
|
||||
|
@ -32,29 +32,60 @@
|
|||
{{end}}
|
||||
</ol>
|
||||
</div>
|
||||
<table id="gogs-source-table" class="table table-hover">
|
||||
<thead class="hidden">
|
||||
<tr>
|
||||
<th class="name">Filename</th>
|
||||
<th class="date">Date modified</th>
|
||||
<th class="text">Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Files}}
|
||||
<tr {{if .IsDir}}class="is-dir"{{end}}>
|
||||
<td class="name"><i class="fa {{if .IsDir}}fa-folder{{else}}fa-file{{end}}"></i>
|
||||
{{if .IsDir}}
|
||||
<a href="/{{$username}}/{{$reponame}}/tree/{{$branchname}}/{{.Path}}">{{.Name}}</a>
|
||||
{{else}}
|
||||
<a href="#">{{.Name}} - {{FileSize .Size}}</a>
|
||||
{{end}}</td>
|
||||
<td class="date"><time datetime="{{.Created}}" data-title="true" title="{{.Created}}">{{TimeSince .Created}}</time></td>
|
||||
<td class="text">{{.Message}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="panel panel-default info-box">
|
||||
<div class="panel-heading info-head">
|
||||
Merge branch 'release/1.1.1'
|
||||
</div>
|
||||
<div class="panel-body info-content">
|
||||
slene authored 4 days ago
|
||||
</div>
|
||||
<table class="panel-footer table file-list">
|
||||
<thead class="hidden">
|
||||
<tr>
|
||||
<th class="icon"></th>
|
||||
<th class="name">Filename</th>
|
||||
<th class="text">Message</th>
|
||||
<th class="date">Date modified</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Files}}
|
||||
<tr {{if .IsDir}}class="is-dir"{{end}}>
|
||||
<td class="icon">
|
||||
<i class="fa {{if .IsDir}}fa-folder{{else}}fa-file-text-o{{end}}"></i>
|
||||
</td>
|
||||
<td class="name">
|
||||
<span class="wrap">
|
||||
{{if .IsDir}}
|
||||
<a href="/{{$username}}/{{$reponame}}/tree/{{$branchname}}/{{.Path}}">{{.Name}}</a>
|
||||
{{else}}
|
||||
<a href="/{{$username}}/{{$reponame}}/blob/{{$branchname}}/{{.Name}}">{{.Name}}</a>
|
||||
{{end}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="text">
|
||||
<span class="wrap">
|
||||
{{.Message}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="date">
|
||||
<span class="wrap">
|
||||
{{TimeSince .Created}}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="panel panel-default file-content">
|
||||
<div class="panel-heading">
|
||||
README.md
|
||||
</div>
|
||||
<div class="panel-body markdown">
|
||||
httplib
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
|
@ -13,22 +13,33 @@
|
|||
</ul>
|
||||
</div>
|
||||
<div id="gogs-user-setting-container" class="col-md-9">
|
||||
<form action="/user/delete" method="post" class="form-horizontal" id="gogs-user-delete">
|
||||
<h4>Delete Account</h4>
|
||||
<p class="alert alert-danger">{{if not .HasError}}The operation will delete your account permanently. Sorry to see you go, but we know you'll back soon.{{else}}{{.ErrorMsg}}{{end}}</p>
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
<button type="submit" class="btn btn-danger btn-lg">Delete Account</button>
|
||||
<h4>Delete Account</h4>
|
||||
<p class="alert alert-danger">{{if not .HasError}}The operation will delete your account permanently. Sorry to see you go, but we know you'll back soon.{{else}}{{.ErrorMsg}}{{end}}</p>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-danger btn-lg" href="#delete-account-modal" id="gogs-delete-account" data-toggle="modal">Delete Account</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="delete-account-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<form action="/user/delete" method="post" class="modal-content" id="gogs-user-delete">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title" id="myModalLabel">Delete Account</h4>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Make sure your are owner of this account. Please enter your password.<strong class="text-danger">*</strong></label>
|
||||
<input name="password" class="form-control" type="password" placeholder="Type your account password" required="required">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(function(){
|
||||
$('#gogs-user-delete').on('submit',function(){
|
||||
return confirm("Are you sure ?");
|
||||
})
|
||||
});
|
||||
</script>
|
||||
{{template "base/footer" .}}
|
|
@ -5,7 +5,7 @@
|
|||
<h4>Account Setting</h4>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item"><a href="/user/setting">Account Profile</a></li>
|
||||
<li class="list-group-item"><a href="/user/setting/Password">Password</a></li>
|
||||
<li class="list-group-item"><a href="/user/setting/password">Password</a></li>
|
||||
<li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li>
|
||||
<li class="list-group-item list-group-item-success"><a href="/user/setting/ssh/">SSH Keys</a></li>
|
||||
<li class="list-group-item"><a href="/user/setting/security">Security</a></li>
|
||||
|
@ -18,12 +18,14 @@
|
|||
<h4>SSH Keys</h4>{{if .AddSSHKeySuccess}}
|
||||
<p class="alert alert-success">New SSH Key has been added !</p>{{else if .HasError}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}}
|
||||
<ul id="gogs-ssh-keys-list" class="list-group">
|
||||
<li class="list-group-item"><span class="name">SSH Key's name</span></li>{{range .Keys}}
|
||||
<li class="list-group-item"><span class="name">SSH Key's name</span></li>
|
||||
{{range .Keys}}
|
||||
<li class="list-group-item">
|
||||
<span class="name">{{.Name}}</span>
|
||||
<span class="print">(print code)</span>
|
||||
<a href="#" class="btn btn-link btn-danger right delete" rel="{{.Id}}" data-del="{{.Id}}">Delete</a>
|
||||
</li>{{end}}
|
||||
<span class="print">({{.Fingerprint}})</span>
|
||||
<button href="#" class="btn btn-danger delete pull-right" rel="{{.Id}}" data-del="{{.Id}}">Delete</button>
|
||||
</li>
|
||||
{{end}}
|
||||
<li class="list-group-item">
|
||||
<a class="btn btn-link btn-primary" href="#ssh-add-modal" id="gogs-ssh-add" data-toggle="modal">Add SSH Key</a>
|
||||
</li>
|
||||
|
|
27
update.go
27
update.go
|
@ -1,13 +1,19 @@
|
|||
// 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 main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
|
||||
git "github.com/gogits/git"
|
||||
|
||||
"github.com/gogits/gogs/models"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
)
|
||||
|
||||
var CmdUpdate = cli.Command{
|
||||
|
@ -41,11 +47,18 @@ func runUpdate(*cli.Context) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
sUserId, _ := strconv.Atoi(userId)
|
||||
sRepoId, _ := strconv.Atoi(repoId)
|
||||
err = models.CommitRepoAction(int64(sUserId), userName,
|
||||
int64(sRepoId), repoName, lastCommit.Message())
|
||||
sUserId, err := strconv.Atoi(userId)
|
||||
if err != nil {
|
||||
//TODO: log
|
||||
log.Error("runUpdate.Parse userId: %v", err)
|
||||
return
|
||||
}
|
||||
sRepoId, err := strconv.Atoi(repoId)
|
||||
if err != nil {
|
||||
log.Error("runUpdate.Parse repoId: %v", err)
|
||||
return
|
||||
}
|
||||
if err = models.CommitRepoAction(int64(sUserId), userName,
|
||||
int64(sRepoId), repoName, lastCommit.Message()); err != nil {
|
||||
log.Error("runUpdate.models.CommitRepoAction: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
10
web.go
10
web.go
|
@ -50,6 +50,9 @@ func runWeb(*cli.Context) {
|
|||
|
||||
// Routers.
|
||||
m.Get("/", middleware.SignInRequire(false), routers.Home)
|
||||
m.Get("/issues", middleware.SignInRequire(true), user.Issues)
|
||||
m.Get("/pulls", middleware.SignInRequire(true), user.Pulls)
|
||||
m.Get("/stars", middleware.SignInRequire(true), user.Stars)
|
||||
m.Any("/user/login", middleware.SignOutRequire(), binding.BindIgnErr(auth.LogInForm{}), user.SignIn)
|
||||
m.Any("/user/logout", middleware.SignInRequire(true), user.SignOut)
|
||||
m.Any("/user/sign_up", middleware.SignOutRequire(), binding.BindIgnErr(auth.RegisterForm{}), user.SignUp)
|
||||
|
@ -67,15 +70,18 @@ func runWeb(*cli.Context) {
|
|||
m.Any("/repo/create", middleware.SignInRequire(true), binding.BindIgnErr(auth.CreateRepoForm{}), repo.Create)
|
||||
m.Any("/repo/delete", middleware.SignInRequire(true), binding.Bind(auth.DeleteRepoForm{}), repo.Delete)
|
||||
|
||||
m.Get("/help", routers.Help)
|
||||
|
||||
m.Get("/:username/:reponame/settings", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Setting)
|
||||
m.Get("/:username/:reponame/commits", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Commits)
|
||||
m.Get("/:username/:reponame/issues", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Issues)
|
||||
m.Get("/:username/:reponame/pulls", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Pulls)
|
||||
m.Get("/:username/:reponame/tree/:branchname/**",
|
||||
middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single)
|
||||
m.Get("/:username/:reponame/tree/:branchname",
|
||||
middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single)
|
||||
m.Get("/:username/:reponame", middleware.SignInRequire(false), middleware.RepoAssignment(true), repo.Single)
|
||||
|
||||
//m.Get("/:username/:reponame", repo.Repo)
|
||||
|
||||
listenAddr := fmt.Sprintf("%s:%s",
|
||||
base.Cfg.MustValue("server", "HTTP_ADDR"),
|
||||
base.Cfg.MustValue("server", "HTTP_PORT", "3000"))
|
||||
|
|
Loading…
Reference in New Issue