Merge branch 'master' of github.com:gogits/gogs

This commit is contained in:
Lunny Xiao 2014-03-16 22:32:50 +08:00
commit f824d6a4b1
27 changed files with 732 additions and 191 deletions

View File

@ -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.

View File

@ -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 =

18
conf/gitignore/Ruby Normal file
View File

@ -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/

21
conf/license/MIT License Normal file
View File

@ -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
View File

@ -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)
}

View File

@ -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,

View File

@ -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

View File

@ -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
}

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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 {

View File

@ -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"
}

View File

@ -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
}

View File

@ -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"/>

View File

@ -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>

View File

@ -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>

View File

@ -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&nbsp;&nbsp;
<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" .}}

View File

@ -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">&times;</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" .}}

View File

@ -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>

View File

@ -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
View File

@ -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"))