mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	merged
This commit is contained in:
		
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -5,4 +5,6 @@ gogs
 | 
				
			|||||||
*.db
 | 
					*.db
 | 
				
			||||||
*.log
 | 
					*.log
 | 
				
			||||||
custom/
 | 
					custom/
 | 
				
			||||||
.vendor/
 | 
					.vendor/
 | 
				
			||||||
 | 
					.idea/
 | 
				
			||||||
 | 
					*.iml
 | 
				
			||||||
@@ -9,13 +9,12 @@ github.com/Unknwon/com=
 | 
				
			|||||||
github.com/Unknwon/cae=
 | 
					github.com/Unknwon/cae=
 | 
				
			||||||
github.com/Unknwon/goconfig=
 | 
					github.com/Unknwon/goconfig=
 | 
				
			||||||
github.com/dchest/scrypt=
 | 
					github.com/dchest/scrypt=
 | 
				
			||||||
github.com/go-sql-driver/mysql=
 | 
					 | 
				
			||||||
github.com/lib/pq=
 | 
					 | 
				
			||||||
github.com/lunny/xorm=
 | 
					github.com/lunny/xorm=
 | 
				
			||||||
github.com/gogits/logs=
 | 
					github.com/gogits/logs=
 | 
				
			||||||
github.com/gogits/binding=
 | 
					github.com/gogits/binding=
 | 
				
			||||||
github.com/gogits/git=
 | 
					github.com/gogits/git=
 | 
				
			||||||
github.com/gogits/gfm=
 | 
					github.com/gogits/gfm=
 | 
				
			||||||
 | 
					github.com/gogits/cache=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[res]
 | 
					[res]
 | 
				
			||||||
include=templates|public|conf
 | 
					include=templates|public|conf
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					# Contributing to Gogs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Want to hack on Gogs? Awesome! Here are instructions to get you
 | 
				
			||||||
 | 
					started. They are probably not perfect, please let us know if anything
 | 
				
			||||||
 | 
					feels wrong or incomplete.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Contribution guidelines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Pull requests are always welcome
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We are always thrilled to receive pull requests, and do our best to
 | 
				
			||||||
 | 
					process them as fast as possible. Not sure if that typo is worth a pull
 | 
				
			||||||
 | 
					request? Do it! We will appreciate it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If your pull request is not accepted on the first try, don't be
 | 
				
			||||||
 | 
					discouraged! If there's a problem with the implementation, hopefully you
 | 
				
			||||||
 | 
					received feedback on what to improve.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We're trying very hard to keep Gogs lean and focused. We don't want it
 | 
				
			||||||
 | 
					to do everything for everybody. This means that we might decide against
 | 
				
			||||||
 | 
					incorporating a new feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Discuss your design on the mailing list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We recommend discussing your plans [on the mailing
 | 
				
			||||||
 | 
					list](https://groups.google.com/forum/#!forum/gogits)
 | 
				
			||||||
 | 
					before starting to code - especially for more ambitious contributions.
 | 
				
			||||||
 | 
					This gives other contributors a chance to point you in the right
 | 
				
			||||||
 | 
					direction, give feedback on your design, and maybe point out if someone
 | 
				
			||||||
 | 
					else is working on the same thing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We may close your pull request if not first discussed on the mailing
 | 
				
			||||||
 | 
					list. We aren't doing this to be jerks. We are doing this to prevent
 | 
				
			||||||
 | 
					people from spending large amounts of time on changes that may need
 | 
				
			||||||
 | 
					to be designed or architected in a specific way, or may not align with
 | 
				
			||||||
 | 
					the vision of the project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Create issues...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Any significant improvement should be documented as [a GitHub
 | 
				
			||||||
 | 
					issue](https://github.com/gogits/gogs/issues) before anybody
 | 
				
			||||||
 | 
					starts working on it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### ...but check for existing issues first!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please take a moment to check that an issue doesn't already exist
 | 
				
			||||||
 | 
					documenting your bug report or improvement proposal. If it does, it
 | 
				
			||||||
 | 
					never hurts to add a quick "+1" or "I have this problem too". This will
 | 
				
			||||||
 | 
					help prioritize the most common problems and requests.
 | 
				
			||||||
@@ -5,7 +5,7 @@ Gogs(Go Git Service) is a GitHub-like clone in the Go Programming Language.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms**  that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency.
 | 
					Since we choose to use pure Go implementation of Git manipulation, Gogs certainly supports **ALL platforms**  that Go supports, including Linux, Max OS X, and Windows with **ZERO** dependency.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Current version: 0.1.1 Alpha
 | 
					##### Current version: 0.1.5 Alpha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Purpose
 | 
					## Purpose
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,7 +15,7 @@ There are some very good products in this category such as [gitlab](http://gitla
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, develop specification, change log and road map.
 | 
					- Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, develop specification, change log and road map.
 | 
				
			||||||
- See [Trello Broad](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team.
 | 
					- See [Trello Broad](https://trello.com/b/uxAoeLUl/gogs-go-git-service) to follow the develop team.
 | 
				
			||||||
- Try it before anything? Go down to **Installation -> Install from binary** section!.
 | 
					- Try it before anything? Do it [online](http://try.gogits.org/Unknown/gogs) or go down to **Installation -> Install from binary** section!
 | 
				
			||||||
- Having troubles? Get help from [Troubleshooting](https://github.com/gogits/gogs/wiki/Troubleshooting).
 | 
					- Having troubles? Get help from [Troubleshooting](https://github.com/gogits/gogs/wiki/Troubleshooting).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Features
 | 
					## Features
 | 
				
			||||||
@@ -28,7 +28,8 @@ There are some very good products in this category such as [gitlab](http://gitla
 | 
				
			|||||||
- Repository viewer.
 | 
					- Repository viewer.
 | 
				
			||||||
- Gravatar support.
 | 
					- Gravatar support.
 | 
				
			||||||
- Mail service(register).
 | 
					- Mail service(register).
 | 
				
			||||||
- Supports MySQL and PostgreSQL.
 | 
					- Administration panel.
 | 
				
			||||||
 | 
					- Supports MySQL, PostgreSQL and SQLite3(binary release only).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installation
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								conf/app.ini
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								conf/app.ini
									
									
									
									
									
								
							@@ -8,8 +8,8 @@ RUN_MODE = dev
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[repository]
 | 
					[repository]
 | 
				
			||||||
ROOT = /Users/%(RUN_USER)s/git/gogs-repositories
 | 
					ROOT = /Users/%(RUN_USER)s/git/gogs-repositories
 | 
				
			||||||
LANG_IGNS = Google Go|C|Python|Ruby|C Sharp
 | 
					LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp
 | 
				
			||||||
LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|BSD (3-Clause) License
 | 
					LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[server]
 | 
					[server]
 | 
				
			||||||
DOMAIN = localhost
 | 
					DOMAIN = localhost
 | 
				
			||||||
@@ -18,7 +18,7 @@ HTTP_ADDR =
 | 
				
			|||||||
HTTP_PORT = 3000
 | 
					HTTP_PORT = 3000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[database]
 | 
					[database]
 | 
				
			||||||
; Either "mysql" or "postgres", it's your choice
 | 
					; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice
 | 
				
			||||||
DB_TYPE = mysql
 | 
					DB_TYPE = mysql
 | 
				
			||||||
HOST = 
 | 
					HOST = 
 | 
				
			||||||
NAME = gogs
 | 
					NAME = gogs
 | 
				
			||||||
@@ -26,6 +26,10 @@ USER = root
 | 
				
			|||||||
PASSWD =
 | 
					PASSWD =
 | 
				
			||||||
; For "postgres" only, either "disable", "require" or "verify-full"
 | 
					; For "postgres" only, either "disable", "require" or "verify-full"
 | 
				
			||||||
SSL_MODE = disable
 | 
					SSL_MODE = disable
 | 
				
			||||||
 | 
					; For "sqlite3" only
 | 
				
			||||||
 | 
					PATH = data/gogs.db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[admin]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
 | 
					; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
 | 
				
			||||||
@@ -36,6 +40,10 @@ ACTIVE_CODE_LIVE_MINUTES = 180
 | 
				
			|||||||
RESET_PASSWD_CODE_LIVE_MINUTES = 180
 | 
					RESET_PASSWD_CODE_LIVE_MINUTES = 180
 | 
				
			||||||
; User need to confirm e-mail for registration
 | 
					; User need to confirm e-mail for registration
 | 
				
			||||||
REGISTER_EMAIL_CONFIRM = false
 | 
					REGISTER_EMAIL_CONFIRM = false
 | 
				
			||||||
 | 
					; Does not allow register and admin create account only
 | 
				
			||||||
 | 
					DISENABLE_REGISTERATION = false
 | 
				
			||||||
 | 
					; User must sign in to view anything.
 | 
				
			||||||
 | 
					REQUIRE_SIGNIN_VIEW = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[mailer]
 | 
					[mailer]
 | 
				
			||||||
ENABLED = false
 | 
					ENABLED = false
 | 
				
			||||||
@@ -52,6 +60,16 @@ FROM =
 | 
				
			|||||||
USER = 
 | 
					USER = 
 | 
				
			||||||
PASSWD = 
 | 
					PASSWD = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[cache]
 | 
				
			||||||
 | 
					; Either "memory", "redis", or "memcache", default is "memory"
 | 
				
			||||||
 | 
					ADAPTER = memory
 | 
				
			||||||
 | 
					; For "memory" only, GC interval in seconds, default is 60
 | 
				
			||||||
 | 
					INTERVAL = 60
 | 
				
			||||||
 | 
					; For "redis" and "memcache", connection host address
 | 
				
			||||||
 | 
					; redis: ":6039"
 | 
				
			||||||
 | 
					; memcache: "127.0.0.1:11211"
 | 
				
			||||||
 | 
					HOST =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log]
 | 
					[log]
 | 
				
			||||||
; Either "console", "file", "conn" or "smtp", default is "console"
 | 
					; Either "console", "file", "conn" or "smtp", default is "console"
 | 
				
			||||||
MODE = console
 | 
					MODE = console
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								conf/gitignore/C++
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								conf/gitignore/C++
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# Compiled Object files
 | 
				
			||||||
 | 
					*.slo
 | 
				
			||||||
 | 
					*.lo
 | 
				
			||||||
 | 
					*.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Compiled Dynamic libraries
 | 
				
			||||||
 | 
					*.so
 | 
				
			||||||
 | 
					*.dylib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Compiled Static libraries
 | 
				
			||||||
 | 
					*.lai
 | 
				
			||||||
 | 
					*.la
 | 
				
			||||||
 | 
					*.a
 | 
				
			||||||
							
								
								
									
										201
									
								
								conf/license/Artistic License 2.0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								conf/license/Artistic License 2.0
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,201 @@
 | 
				
			|||||||
 | 
					The Artistic License 2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					           Copyright (c) 2014
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     Everyone is permitted to copy and distribute verbatim copies
 | 
				
			||||||
 | 
					      of this license document, but changing it is not allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Preamble
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This license establishes the terms under which a given free software
 | 
				
			||||||
 | 
					Package may be copied, modified, distributed, and/or redistributed.
 | 
				
			||||||
 | 
					The intent is that the Copyright Holder maintains some artistic
 | 
				
			||||||
 | 
					control over the development of that Package while still keeping the
 | 
				
			||||||
 | 
					Package available as open source and free software.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You are always permitted to make arrangements wholly outside of this
 | 
				
			||||||
 | 
					license directly with the Copyright Holder of a given Package.  If the
 | 
				
			||||||
 | 
					terms of this license do not permit the full use that you propose to
 | 
				
			||||||
 | 
					make of the Package, you should contact the Copyright Holder and seek
 | 
				
			||||||
 | 
					a different licensing arrangement.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Copyright Holder" means the individual(s) or organization(s)
 | 
				
			||||||
 | 
					    named in the copyright notice for the entire Package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Contributor" means any party that has contributed code or other
 | 
				
			||||||
 | 
					    material to the Package, in accordance with the Copyright Holder's
 | 
				
			||||||
 | 
					    procedures.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "You" and "your" means any person who would like to copy,
 | 
				
			||||||
 | 
					    distribute, or modify the Package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Package" means the collection of files distributed by the
 | 
				
			||||||
 | 
					    Copyright Holder, and derivatives of that collection and/or of
 | 
				
			||||||
 | 
					    those files. A given Package may consist of either the Standard
 | 
				
			||||||
 | 
					    Version, or a Modified Version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Distribute" means providing a copy of the Package or making it
 | 
				
			||||||
 | 
					    accessible to anyone else, or in the case of a company or
 | 
				
			||||||
 | 
					    organization, to others outside of your company or organization.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Distributor Fee" means any fee that you charge for Distributing
 | 
				
			||||||
 | 
					    this Package or providing support for this Package to another
 | 
				
			||||||
 | 
					    party.  It does not mean licensing fees.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Standard Version" refers to the Package if it has not been
 | 
				
			||||||
 | 
					    modified, or has been modified only in ways explicitly requested
 | 
				
			||||||
 | 
					    by the Copyright Holder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Modified Version" means the Package, if it has been changed, and
 | 
				
			||||||
 | 
					    such changes were not explicitly requested by the Copyright
 | 
				
			||||||
 | 
					    Holder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Original License" means this Artistic License as Distributed with
 | 
				
			||||||
 | 
					    the Standard Version of the Package, in its current version or as
 | 
				
			||||||
 | 
					    it may be modified by The Perl Foundation in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Source" form means the source code, documentation source, and
 | 
				
			||||||
 | 
					    configuration files for the Package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "Compiled" form means the compiled bytecode, object code, binary,
 | 
				
			||||||
 | 
					    or any other form resulting from mechanical transformation or
 | 
				
			||||||
 | 
					    translation of the Source form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission for Use and Modification Without Distribution
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(1)  You are permitted to use the Standard Version and create and use
 | 
				
			||||||
 | 
					Modified Versions for any purpose without restriction, provided that
 | 
				
			||||||
 | 
					you do not Distribute the Modified Version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permissions for Redistribution of the Standard Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(2)  You may Distribute verbatim copies of the Source form of the
 | 
				
			||||||
 | 
					Standard Version of this Package in any medium without restriction,
 | 
				
			||||||
 | 
					either gratis or for a Distributor Fee, provided that you duplicate
 | 
				
			||||||
 | 
					all of the original copyright notices and associated disclaimers.  At
 | 
				
			||||||
 | 
					your discretion, such verbatim copies may or may not include a
 | 
				
			||||||
 | 
					Compiled form of the Package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(3)  You may apply any bug fixes, portability changes, and other
 | 
				
			||||||
 | 
					modifications made available from the Copyright Holder.  The resulting
 | 
				
			||||||
 | 
					Package will still be considered the Standard Version, and as such
 | 
				
			||||||
 | 
					will be subject to the Original License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Distribution of Modified Versions of the Package as Source
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(4)  You may Distribute your Modified Version as Source (either gratis
 | 
				
			||||||
 | 
					or for a Distributor Fee, and with or without a Compiled form of the
 | 
				
			||||||
 | 
					Modified Version) provided that you clearly document how it differs
 | 
				
			||||||
 | 
					from the Standard Version, including, but not limited to, documenting
 | 
				
			||||||
 | 
					any non-standard features, executables, or modules, and provided that
 | 
				
			||||||
 | 
					you do at least ONE of the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (a)  make the Modified Version available to the Copyright Holder
 | 
				
			||||||
 | 
					    of the Standard Version, under the Original License, so that the
 | 
				
			||||||
 | 
					    Copyright Holder may include your modifications in the Standard
 | 
				
			||||||
 | 
					    Version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (b)  ensure that installation of your Modified Version does not
 | 
				
			||||||
 | 
					    prevent the user installing or running the Standard Version. In
 | 
				
			||||||
 | 
					    addition, the Modified Version must bear a name that is different
 | 
				
			||||||
 | 
					    from the name of the Standard Version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (c)  allow anyone who receives a copy of the Modified Version to
 | 
				
			||||||
 | 
					    make the Source form of the Modified Version available to others
 | 
				
			||||||
 | 
					    under
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (i)  the Original License or
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (ii)  a license that permits the licensee to freely copy,
 | 
				
			||||||
 | 
					    modify and redistribute the Modified Version using the same
 | 
				
			||||||
 | 
					    licensing terms that apply to the copy that the licensee
 | 
				
			||||||
 | 
					    received, and requires that the Source form of the Modified
 | 
				
			||||||
 | 
					    Version, and of any works derived from it, be made freely
 | 
				
			||||||
 | 
					    available in that license fees are prohibited but Distributor
 | 
				
			||||||
 | 
					    Fees are allowed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Distribution of Compiled Forms of the Standard Version
 | 
				
			||||||
 | 
					or Modified Versions without the Source
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(5)  You may Distribute Compiled forms of the Standard Version without
 | 
				
			||||||
 | 
					the Source, provided that you include complete instructions on how to
 | 
				
			||||||
 | 
					get the Source of the Standard Version.  Such instructions must be
 | 
				
			||||||
 | 
					valid at the time of your distribution.  If these instructions, at any
 | 
				
			||||||
 | 
					time while you are carrying out such distribution, become invalid, you
 | 
				
			||||||
 | 
					must provide new instructions on demand or cease further distribution.
 | 
				
			||||||
 | 
					If you provide valid instructions or cease distribution within thirty
 | 
				
			||||||
 | 
					days after you become aware that the instructions are invalid, then
 | 
				
			||||||
 | 
					you do not forfeit any of your rights under this license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(6)  You may Distribute a Modified Version in Compiled form without
 | 
				
			||||||
 | 
					the Source, provided that you comply with Section 4 with respect to
 | 
				
			||||||
 | 
					the Source of the Modified Version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Aggregating or Linking the Package
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(7)  You may aggregate the Package (either the Standard Version or
 | 
				
			||||||
 | 
					Modified Version) with other packages and Distribute the resulting
 | 
				
			||||||
 | 
					aggregation provided that you do not charge a licensing fee for the
 | 
				
			||||||
 | 
					Package.  Distributor Fees are permitted, and licensing fees for other
 | 
				
			||||||
 | 
					components in the aggregation are permitted. The terms of this license
 | 
				
			||||||
 | 
					apply to the use and Distribution of the Standard or Modified Versions
 | 
				
			||||||
 | 
					as included in the aggregation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(8) You are permitted to link Modified and Standard Versions with
 | 
				
			||||||
 | 
					other works, to embed the Package in a larger work of your own, or to
 | 
				
			||||||
 | 
					build stand-alone binary or bytecode versions of applications that
 | 
				
			||||||
 | 
					include the Package, and Distribute the result without restriction,
 | 
				
			||||||
 | 
					provided the result does not expose a direct interface to the Package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Items That are Not Considered Part of a Modified Version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(9) Works (including, but not limited to, modules and scripts) that
 | 
				
			||||||
 | 
					merely extend or make use of the Package, do not, by themselves, cause
 | 
				
			||||||
 | 
					the Package to be a Modified Version.  In addition, such works are not
 | 
				
			||||||
 | 
					considered parts of the Package itself, and are not subject to the
 | 
				
			||||||
 | 
					terms of this license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					General Provisions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(10)  Any use, modification, and distribution of the Standard or
 | 
				
			||||||
 | 
					Modified Versions is governed by this Artistic License. By using,
 | 
				
			||||||
 | 
					modifying or distributing the Package, you accept this license. Do not
 | 
				
			||||||
 | 
					use, modify, or distribute the Package, if you do not accept this
 | 
				
			||||||
 | 
					license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(11)  If your Modified Version has been derived from a Modified
 | 
				
			||||||
 | 
					Version made by someone other than you, you are nevertheless required
 | 
				
			||||||
 | 
					to ensure that your Modified Version complies with the requirements of
 | 
				
			||||||
 | 
					this license.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(12)  This license does not grant you the right to use any trademark,
 | 
				
			||||||
 | 
					service mark, tradename, or logo of the Copyright Holder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(13)  This license includes the non-exclusive, worldwide,
 | 
				
			||||||
 | 
					free-of-charge patent license to make, have made, use, offer to sell,
 | 
				
			||||||
 | 
					sell, import and otherwise transfer the Package with respect to any
 | 
				
			||||||
 | 
					patent claims licensable by the Copyright Holder that are necessarily
 | 
				
			||||||
 | 
					infringed by the Package. If you institute patent litigation
 | 
				
			||||||
 | 
					(including a cross-claim or counterclaim) against any party alleging
 | 
				
			||||||
 | 
					that the Package constitutes direct or contributory patent
 | 
				
			||||||
 | 
					infringement, then this Artistic License to you shall terminate on the
 | 
				
			||||||
 | 
					date that such litigation is filed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(14)  Disclaimer of Warranty:
 | 
				
			||||||
 | 
					THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
 | 
				
			||||||
 | 
					IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
 | 
				
			||||||
 | 
					WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 | 
				
			||||||
 | 
					NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
 | 
				
			||||||
 | 
					LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
 | 
				
			||||||
 | 
					BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
 | 
				
			||||||
 | 
					ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
							
								
								
									
										8
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								gogs.go
									
									
									
									
									
								
							@@ -15,12 +15,12 @@ import (
 | 
				
			|||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// +build go1.1
 | 
					// +build go1.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Test that go1.1 tag above is included in builds. main.go refers to this definition.
 | 
					// Test that go1.2 tag above is included in builds. main.go refers to this definition.
 | 
				
			||||||
const go11tag = true
 | 
					const go12tag = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const APP_VER = "0.1.1.0320.1"
 | 
					const APP_VER = "0.1.5.0321"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	base.AppVer = APP_VER
 | 
						base.AppVer = APP_VER
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -64,6 +64,10 @@ func CommitRepoAction(userId int64, userName string,
 | 
				
			|||||||
	watches = append(watches, Watch{UserId: userId})
 | 
						watches = append(watches, Watch{UserId: userId})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := range watches {
 | 
						for i := range watches {
 | 
				
			||||||
 | 
							if userId == watches[i].UserId && i > 0 {
 | 
				
			||||||
 | 
								continue // Do not add twice in case author watches his/her repository.
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		_, err = orm.InsertOne(&Action{
 | 
							_, err = orm.InsertOne(&Action{
 | 
				
			||||||
			UserId:      watches[i].UserId,
 | 
								UserId:      watches[i].UserId,
 | 
				
			||||||
			ActUserId:   userId,
 | 
								ActUserId:   userId,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								models/issue.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								models/issue.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +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 models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Issue struct {
 | 
				
			||||||
 | 
						Id       int64
 | 
				
			||||||
 | 
						RepoId   int64 `xorm:"index"`
 | 
				
			||||||
 | 
						PosterId int64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PullRequest struct {
 | 
				
			||||||
 | 
						Id int64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Comment struct {
 | 
				
			||||||
 | 
						Id int64
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,6 +7,7 @@ package models
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_ "github.com/go-sql-driver/mysql"
 | 
						_ "github.com/go-sql-driver/mysql"
 | 
				
			||||||
	_ "github.com/lib/pq"
 | 
						_ "github.com/lib/pq"
 | 
				
			||||||
@@ -16,48 +17,37 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	orm          *xorm.Engine
 | 
						orm *xorm.Engine
 | 
				
			||||||
	RepoRootPath string
 | 
					
 | 
				
			||||||
 | 
						DbCfg struct {
 | 
				
			||||||
 | 
							Type, Host, Name, User, Pwd, Path, SslMode string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Members struct {
 | 
					func LoadModelsConfig() {
 | 
				
			||||||
	Id     int64
 | 
						DbCfg.Type = base.Cfg.MustValue("database", "DB_TYPE")
 | 
				
			||||||
	OrgId  int64 `xorm:"unique(s) index"`
 | 
						DbCfg.Host = base.Cfg.MustValue("database", "HOST")
 | 
				
			||||||
	UserId int64 `xorm:"unique(s)"`
 | 
						DbCfg.Name = base.Cfg.MustValue("database", "NAME")
 | 
				
			||||||
}
 | 
						DbCfg.User = base.Cfg.MustValue("database", "USER")
 | 
				
			||||||
 | 
						DbCfg.Pwd = base.Cfg.MustValue("database", "PASSWD")
 | 
				
			||||||
type Issue struct {
 | 
						DbCfg.SslMode = base.Cfg.MustValue("database", "SSL_MODE")
 | 
				
			||||||
	Id       int64
 | 
						DbCfg.Path = base.Cfg.MustValue("database", "PATH", "data/gogs.db")
 | 
				
			||||||
	RepoId   int64 `xorm:"index"`
 | 
					 | 
				
			||||||
	PosterId int64
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type PullRequest struct {
 | 
					 | 
				
			||||||
	Id int64
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type Comment struct {
 | 
					 | 
				
			||||||
	Id int64
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setEngine() {
 | 
					func setEngine() {
 | 
				
			||||||
	dbType := base.Cfg.MustValue("database", "DB_TYPE")
 | 
					 | 
				
			||||||
	dbHost := base.Cfg.MustValue("database", "HOST")
 | 
					 | 
				
			||||||
	dbName := base.Cfg.MustValue("database", "NAME")
 | 
					 | 
				
			||||||
	dbUser := base.Cfg.MustValue("database", "USER")
 | 
					 | 
				
			||||||
	dbPwd := base.Cfg.MustValue("database", "PASSWD")
 | 
					 | 
				
			||||||
	sslMode := base.Cfg.MustValue("database", "SSL_MODE")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	switch dbType {
 | 
						switch DbCfg.Type {
 | 
				
			||||||
	case "mysql":
 | 
						case "mysql":
 | 
				
			||||||
		orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8",
 | 
							orm, err = xorm.NewEngine("mysql", fmt.Sprintf("%s:%s@%s/%s?charset=utf8",
 | 
				
			||||||
			dbUser, dbPwd, dbHost, dbName))
 | 
								DbCfg.User, DbCfg.Pwd, DbCfg.Host, DbCfg.Name))
 | 
				
			||||||
	case "postgres":
 | 
						case "postgres":
 | 
				
			||||||
		orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s",
 | 
							orm, err = xorm.NewEngine("postgres", fmt.Sprintf("user=%s password=%s dbname=%s sslmode=%s",
 | 
				
			||||||
			dbUser, dbPwd, dbName, sslMode))
 | 
								DbCfg.User, DbCfg.Pwd, DbCfg.Name, DbCfg.SslMode))
 | 
				
			||||||
 | 
						case "sqlite3":
 | 
				
			||||||
 | 
							os.MkdirAll(path.Dir(DbCfg.Path), os.ModePerm)
 | 
				
			||||||
 | 
							orm, err = xorm.NewEngine("sqlite3", DbCfg.Path)
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		fmt.Printf("Unknown database type: %s\n", dbType)
 | 
							fmt.Printf("Unknown database type: %s\n", DbCfg.Type)
 | 
				
			||||||
		os.Exit(2)
 | 
							os.Exit(2)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -65,8 +55,8 @@ func setEngine() {
 | 
				
			|||||||
		os.Exit(2)
 | 
							os.Exit(2)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: for serv command, MUST remove the output to os.stdout, so
 | 
						// WARNNING: for serv command, MUST remove the output to os.stdout,
 | 
				
			||||||
	// use log file to instead print to stdout
 | 
						// so use log file to instead print to stdout.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//x.ShowDebug = true
 | 
						//x.ShowDebug = true
 | 
				
			||||||
	//orm.ShowErr = true
 | 
						//orm.ShowErr = true
 | 
				
			||||||
@@ -77,20 +67,29 @@ func setEngine() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	orm.Logger = f
 | 
						orm.Logger = f
 | 
				
			||||||
	orm.ShowSQL = true
 | 
						orm.ShowSQL = true
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Determine and create root git reposiroty path.
 | 
					 | 
				
			||||||
	RepoRootPath = base.Cfg.MustValue("repository", "ROOT")
 | 
					 | 
				
			||||||
	if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil {
 | 
					 | 
				
			||||||
		fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err)
 | 
					 | 
				
			||||||
		os.Exit(2)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func NewEngine() {
 | 
				
			||||||
	setEngine()
 | 
						setEngine()
 | 
				
			||||||
	if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Access),
 | 
						if err := orm.Sync(new(User), new(PublicKey), new(Repository), new(Watch),
 | 
				
			||||||
		new(Action), new(Watch)); err != nil {
 | 
							new(Action), new(Access)); err != nil {
 | 
				
			||||||
		fmt.Printf("sync database struct error: %v\n", err)
 | 
							fmt.Printf("sync database struct error: %v\n", err)
 | 
				
			||||||
		os.Exit(2)
 | 
							os.Exit(2)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Statistic struct {
 | 
				
			||||||
 | 
						Counter struct {
 | 
				
			||||||
 | 
							User, PublicKey, Repo, Watch, Action, Access int64
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetStatistic() (stats Statistic) {
 | 
				
			||||||
 | 
						stats.Counter.User, _ = orm.Count(new(User))
 | 
				
			||||||
 | 
						stats.Counter.PublicKey, _ = orm.Count(new(PublicKey))
 | 
				
			||||||
 | 
						stats.Counter.Repo, _ = orm.Count(new(Repository))
 | 
				
			||||||
 | 
						stats.Counter.Watch, _ = orm.Count(new(Watch))
 | 
				
			||||||
 | 
						stats.Counter.Action, _ = orm.Count(new(Action))
 | 
				
			||||||
 | 
						stats.Counter.Access, _ = orm.Count(new(Access))
 | 
				
			||||||
 | 
						return stats
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,9 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
 | 
						LoadModelsConfig()
 | 
				
			||||||
 | 
						NewEngine()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	orm, err = xorm.NewEngine("sqlite3", "./test.db")
 | 
						orm, err = xorm.NewEngine("sqlite3", "./test.db")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,8 +27,12 @@ const (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	sshOpLocker = sync.Mutex{}
 | 
						ErrKeyAlreadyExist = errors.New("Public key already exist")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var sshOpLocker = sync.Mutex{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
	sshPath string
 | 
						sshPath string
 | 
				
			||||||
	appPath string
 | 
						appPath string
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -79,10 +83,6 @@ type PublicKey struct {
 | 
				
			|||||||
	Updated     time.Time `xorm:"updated"`
 | 
						Updated     time.Time `xorm:"updated"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrKeyAlreadyExist = errors.New("Public key already exist")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GenAuthorizedKey returns formatted public key string.
 | 
					// GenAuthorizedKey returns formatted public key string.
 | 
				
			||||||
func GenAuthorizedKey(keyId int64, key string) string {
 | 
					func GenAuthorizedKey(keyId int64, key string) string {
 | 
				
			||||||
	return fmt.Sprintf(TPL_PUBLICK_KEY+"\n", appPath, keyId, key)
 | 
						return fmt.Sprintf(TPL_PUBLICK_KEY+"\n", appPath, keyId, key)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										276
									
								
								models/repo.go
									
									
									
									
									
								
							
							
						
						
									
										276
									
								
								models/repo.go
									
									
									
									
									
								
							@@ -12,6 +12,7 @@ import (
 | 
				
			|||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
@@ -26,68 +27,26 @@ import (
 | 
				
			|||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Repository represents a git repository.
 | 
					var (
 | 
				
			||||||
type Repository struct {
 | 
						ErrRepoAlreadyExist  = errors.New("Repository already exist")
 | 
				
			||||||
	Id          int64
 | 
						ErrRepoNotExist      = errors.New("Repository does not exist")
 | 
				
			||||||
	OwnerId     int64 `xorm:"unique(s)"`
 | 
						ErrRepoFileNotExist  = errors.New("Target Repo file does not exist")
 | 
				
			||||||
	ForkId      int64
 | 
						ErrRepoNameIllegal   = errors.New("Repository name contains illegal characters")
 | 
				
			||||||
	LowerName   string `xorm:"unique(s) index not null"`
 | 
						ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded")
 | 
				
			||||||
	Name        string `xorm:"index not null"`
 | 
					)
 | 
				
			||||||
	Description string
 | 
					 | 
				
			||||||
	Website     string
 | 
					 | 
				
			||||||
	Private     bool
 | 
					 | 
				
			||||||
	NumWatchs   int
 | 
					 | 
				
			||||||
	NumStars    int
 | 
					 | 
				
			||||||
	NumForks    int
 | 
					 | 
				
			||||||
	Created     time.Time `xorm:"created"`
 | 
					 | 
				
			||||||
	Updated     time.Time `xorm:"updated"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Watch is connection request for receiving repository notifycation.
 | 
					var gitInitLocker = sync.Mutex{}
 | 
				
			||||||
type Watch struct {
 | 
					 | 
				
			||||||
	Id     int64
 | 
					 | 
				
			||||||
	RepoId int64 `xorm:"UNIQUE(watch)"`
 | 
					 | 
				
			||||||
	UserId int64 `xorm:"UNIQUE(watch)"`
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Watch or unwatch repository.
 | 
					 | 
				
			||||||
func WatchRepo(userId, repoId int64, watch bool) (err error) {
 | 
					 | 
				
			||||||
	if watch {
 | 
					 | 
				
			||||||
		_, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId})
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		_, err = orm.Delete(&Watch{0, repoId, userId})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetWatches returns all watches of given repository.
 | 
					 | 
				
			||||||
func GetWatches(repoId int64) ([]Watch, error) {
 | 
					 | 
				
			||||||
	watches := make([]Watch, 0, 10)
 | 
					 | 
				
			||||||
	err := orm.Find(&watches, &Watch{RepoId: repoId})
 | 
					 | 
				
			||||||
	return watches, err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// IsWatching checks if user has watched given repository.
 | 
					 | 
				
			||||||
func IsWatching(userId, repoId int64) bool {
 | 
					 | 
				
			||||||
	has, _ := orm.Get(&Watch{0, repoId, userId})
 | 
					 | 
				
			||||||
	return has
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	gitInitLocker          = sync.Mutex{}
 | 
					 | 
				
			||||||
	LanguageIgns, Licenses []string
 | 
						LanguageIgns, Licenses []string
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					func LoadRepoConfig() {
 | 
				
			||||||
	ErrRepoAlreadyExist = errors.New("Repository already exist")
 | 
					 | 
				
			||||||
	ErrRepoNotExist     = errors.New("Repository does not exist")
 | 
					 | 
				
			||||||
	ErrRepoFileNotExist = errors.New("Target Repo file does not exist")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	LanguageIgns = strings.Split(base.Cfg.MustValue("repository", "LANG_IGNS"), "|")
 | 
						LanguageIgns = strings.Split(base.Cfg.MustValue("repository", "LANG_IGNS"), "|")
 | 
				
			||||||
	Licenses = strings.Split(base.Cfg.MustValue("repository", "LICENSES"), "|")
 | 
						Licenses = strings.Split(base.Cfg.MustValue("repository", "LICENSES"), "|")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewRepoContext() {
 | 
				
			||||||
	zip.Verbose = false
 | 
						zip.Verbose = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check if server has basic git setting.
 | 
						// Check if server has basic git setting.
 | 
				
			||||||
@@ -104,6 +63,32 @@ func init() {
 | 
				
			|||||||
			os.Exit(2)
 | 
								os.Exit(2)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Initialize illegal patterns.
 | 
				
			||||||
 | 
						for i := range illegalPatterns[1:] {
 | 
				
			||||||
 | 
							pattern := ""
 | 
				
			||||||
 | 
							for j := range illegalPatterns[i+1] {
 | 
				
			||||||
 | 
								pattern += "[" + string(illegalPatterns[i+1][j]-32) + string(illegalPatterns[i+1][j]) + "]"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							illegalPatterns[i+1] = pattern
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Repository represents a git repository.
 | 
				
			||||||
 | 
					type Repository struct {
 | 
				
			||||||
 | 
						Id          int64
 | 
				
			||||||
 | 
						OwnerId     int64 `xorm:"unique(s)"`
 | 
				
			||||||
 | 
						ForkId      int64
 | 
				
			||||||
 | 
						LowerName   string `xorm:"unique(s) index not null"`
 | 
				
			||||||
 | 
						Name        string `xorm:"index not null"`
 | 
				
			||||||
 | 
						Description string
 | 
				
			||||||
 | 
						Website     string
 | 
				
			||||||
 | 
						Private     bool
 | 
				
			||||||
 | 
						NumWatches  int
 | 
				
			||||||
 | 
						NumStars    int
 | 
				
			||||||
 | 
						NumForks    int
 | 
				
			||||||
 | 
						Created     time.Time `xorm:"created"`
 | 
				
			||||||
 | 
						Updated     time.Time `xorm:"updated"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsRepositoryExist returns true if the repository with given name under user has already existed.
 | 
					// IsRepositoryExist returns true if the repository with given name under user has already existed.
 | 
				
			||||||
@@ -120,8 +105,28 @@ func IsRepositoryExist(user *User, repoName string) (bool, error) {
 | 
				
			|||||||
	return s.IsDir(), nil
 | 
						return s.IsDir(), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						// Define as all lower case!!
 | 
				
			||||||
 | 
						illegalPatterns = []string{"[.][Gg][Ii][Tt]", "user", "help", "stars", "issues", "pulls", "commits", "admin", "repo", "template", "admin"}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsLegalName returns false if name contains illegal characters.
 | 
				
			||||||
 | 
					func IsLegalName(repoName string) bool {
 | 
				
			||||||
 | 
						for _, pattern := range illegalPatterns {
 | 
				
			||||||
 | 
							has, _ := regexp.MatchString(pattern, repoName)
 | 
				
			||||||
 | 
							if has {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CreateRepository creates a repository for given user or orgnaziation.
 | 
					// CreateRepository creates a repository for given user or orgnaziation.
 | 
				
			||||||
func CreateRepository(user *User, repoName, desc, repoLang, license string, private bool, initReadme bool) (*Repository, error) {
 | 
					func CreateRepository(user *User, repoName, desc, repoLang, license string, private bool, initReadme bool) (*Repository, error) {
 | 
				
			||||||
 | 
						if !IsLegalName(repoName) {
 | 
				
			||||||
 | 
							return nil, ErrRepoNameIllegal
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isExist, err := IsRepositoryExist(user, repoName)
 | 
						isExist, err := IsRepositoryExist(user, repoName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -331,6 +336,82 @@ func initRepository(f string, user *User, repo *Repository, initReadme bool, rep
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// UserRepo reporesents a repository with user name.
 | 
				
			||||||
 | 
					type UserRepo struct {
 | 
				
			||||||
 | 
						*Repository
 | 
				
			||||||
 | 
						UserName string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetRepos returns given number of repository objects with offset.
 | 
				
			||||||
 | 
					func GetRepos(num, offset int) ([]UserRepo, error) {
 | 
				
			||||||
 | 
						repos := make([]Repository, 0, num)
 | 
				
			||||||
 | 
						if err := orm.Limit(num, offset).Asc("id").Find(&repos); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						urepos := make([]UserRepo, len(repos))
 | 
				
			||||||
 | 
						for i := range repos {
 | 
				
			||||||
 | 
							urepos[i].Repository = &repos[i]
 | 
				
			||||||
 | 
							u := new(User)
 | 
				
			||||||
 | 
							has, err := orm.Id(urepos[i].Repository.OwnerId).Get(u)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							} else if !has {
 | 
				
			||||||
 | 
								return nil, ErrUserNotExist
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							urepos[i].UserName = u.Name
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return urepos, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RepoPath(userName, repoName string) string {
 | 
				
			||||||
 | 
						return filepath.Join(UserPath(userName), repoName+".git")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeleteRepository deletes a repository for a user or orgnaztion.
 | 
				
			||||||
 | 
					func DeleteRepository(userId, repoId int64, userName string) (err error) {
 | 
				
			||||||
 | 
						repo := &Repository{Id: repoId, OwnerId: userId}
 | 
				
			||||||
 | 
						has, err := orm.Get(repo)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						} else if !has {
 | 
				
			||||||
 | 
							return ErrRepoNotExist
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session := orm.NewSession()
 | 
				
			||||||
 | 
						if err = session.Begin(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, err = session.Delete(&Repository{Id: repoId}); err != nil {
 | 
				
			||||||
 | 
							session.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil {
 | 
				
			||||||
 | 
							session.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						rawSql := "UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?"
 | 
				
			||||||
 | 
						if _, err = session.Exec(rawSql, userId); err != nil {
 | 
				
			||||||
 | 
							session.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, err = session.Delete(&Watch{RepoId: repoId}); err != nil {
 | 
				
			||||||
 | 
							session.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = session.Commit(); err != nil {
 | 
				
			||||||
 | 
							session.Rollback()
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil {
 | 
				
			||||||
 | 
							// TODO: log and delete manully
 | 
				
			||||||
 | 
							log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err)
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRepositoryByName returns the repository by given name under user if exists.
 | 
					// GetRepositoryByName returns the repository by given name under user if exists.
 | 
				
			||||||
func GetRepositoryByName(user *User, repoName string) (*Repository, error) {
 | 
					func GetRepositoryByName(user *User, repoName string) (*Repository, error) {
 | 
				
			||||||
	repo := &Repository{
 | 
						repo := &Repository{
 | 
				
			||||||
@@ -368,6 +449,45 @@ func GetRepositoryCount(user *User) (int64, error) {
 | 
				
			|||||||
	return orm.Count(&Repository{OwnerId: user.Id})
 | 
						return orm.Count(&Repository{OwnerId: user.Id})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Watch is connection request for receiving repository notifycation.
 | 
				
			||||||
 | 
					type Watch struct {
 | 
				
			||||||
 | 
						Id     int64
 | 
				
			||||||
 | 
						RepoId int64 `xorm:"UNIQUE(watch)"`
 | 
				
			||||||
 | 
						UserId int64 `xorm:"UNIQUE(watch)"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Watch or unwatch repository.
 | 
				
			||||||
 | 
					func WatchRepo(userId, repoId int64, watch bool) (err error) {
 | 
				
			||||||
 | 
						if watch {
 | 
				
			||||||
 | 
							if _, err = orm.Insert(&Watch{RepoId: repoId, UserId: userId}); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rawSql := "UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?"
 | 
				
			||||||
 | 
							_, err = orm.Exec(rawSql, repoId)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if _, err = orm.Delete(&Watch{0, repoId, userId}); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							rawSql := "UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?"
 | 
				
			||||||
 | 
							_, err = orm.Exec(rawSql, repoId)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetWatches returns all watches of given repository.
 | 
				
			||||||
 | 
					func GetWatches(repoId int64) ([]Watch, error) {
 | 
				
			||||||
 | 
						watches := make([]Watch, 0, 10)
 | 
				
			||||||
 | 
						err := orm.Find(&watches, &Watch{RepoId: repoId})
 | 
				
			||||||
 | 
						return watches, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsWatching checks if user has watched given repository.
 | 
				
			||||||
 | 
					func IsWatching(userId, repoId int64) bool {
 | 
				
			||||||
 | 
						has, _ := orm.Get(&Watch{0, repoId, userId})
 | 
				
			||||||
 | 
						return has
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func StarReposiory(user *User, repoName string) error {
 | 
					func StarReposiory(user *User, repoName string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -388,56 +508,6 @@ func ForkRepository(reposName string, userId int64) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func RepoPath(userName, repoName string) string {
 | 
					 | 
				
			||||||
	return filepath.Join(UserPath(userName), repoName+".git")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// DeleteRepository deletes a repository for a user or orgnaztion.
 | 
					 | 
				
			||||||
func DeleteRepository(userId, repoId int64, userName string) (err error) {
 | 
					 | 
				
			||||||
	repo := &Repository{Id: repoId, OwnerId: userId}
 | 
					 | 
				
			||||||
	has, err := orm.Get(repo)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	} else if !has {
 | 
					 | 
				
			||||||
		return ErrRepoNotExist
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	session := orm.NewSession()
 | 
					 | 
				
			||||||
	if err = session.Begin(); err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err = session.Delete(&Repository{Id: repoId}); err != nil {
 | 
					 | 
				
			||||||
		session.Rollback()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil {
 | 
					 | 
				
			||||||
		session.Rollback()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rawSql := "UPDATE user SET num_repos = num_repos - 1 WHERE id = ?"
 | 
					 | 
				
			||||||
	if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" {
 | 
					 | 
				
			||||||
		rawSql = "UPDATE \"user\" SET num_repos = num_repos - 1 WHERE id = ?"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err = session.Exec(rawSql, userId); err != nil {
 | 
					 | 
				
			||||||
		session.Rollback()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err = session.Commit(); err != nil {
 | 
					 | 
				
			||||||
		session.Rollback()
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil {
 | 
					 | 
				
			||||||
		// TODO: log and delete manully
 | 
					 | 
				
			||||||
		log.Error("delete repo %s/%s failed: %v", userName, repo.Name, err)
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RepoFile represents a file object in git repository.
 | 
					// RepoFile represents a file object in git repository.
 | 
				
			||||||
type RepoFile struct {
 | 
					type RepoFile struct {
 | 
				
			||||||
	*git.TreeEntry
 | 
						*git.TreeEntry
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								models/user.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								models/user.go
									
									
									
									
									
								
							@@ -33,6 +33,14 @@ const (
 | 
				
			|||||||
	LT_LDAP
 | 
						LT_LDAP
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ErrUserOwnRepos     = errors.New("User still have ownership of repositories")
 | 
				
			||||||
 | 
						ErrUserAlreadyExist = errors.New("User already exist")
 | 
				
			||||||
 | 
						ErrUserNotExist     = errors.New("User does not exist")
 | 
				
			||||||
 | 
						ErrEmailAlreadyUsed = errors.New("E-mail already used")
 | 
				
			||||||
 | 
						ErrUserNameIllegal  = errors.New("User name contains illegal characters")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// User represents the object of individual and member of organization.
 | 
					// User represents the object of individual and member of organization.
 | 
				
			||||||
type User struct {
 | 
					type User struct {
 | 
				
			||||||
	Id            int64
 | 
						Id            int64
 | 
				
			||||||
@@ -51,6 +59,7 @@ type User struct {
 | 
				
			|||||||
	Location      string
 | 
						Location      string
 | 
				
			||||||
	Website       string
 | 
						Website       string
 | 
				
			||||||
	IsActive      bool
 | 
						IsActive      bool
 | 
				
			||||||
 | 
						IsAdmin       bool
 | 
				
			||||||
	Rands         string    `xorm:"VARCHAR(10)"`
 | 
						Rands         string    `xorm:"VARCHAR(10)"`
 | 
				
			||||||
	Created       time.Time `xorm:"created"`
 | 
						Created       time.Time `xorm:"created"`
 | 
				
			||||||
	Updated       time.Time `xorm:"updated"`
 | 
						Updated       time.Time `xorm:"updated"`
 | 
				
			||||||
@@ -66,19 +75,28 @@ func (user *User) AvatarLink() string {
 | 
				
			|||||||
	return "http://1.gravatar.com/avatar/" + user.Avatar
 | 
						return "http://1.gravatar.com/avatar/" + user.Avatar
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Follow struct {
 | 
					// NewGitSig generates and returns the signature of given user.
 | 
				
			||||||
	Id       int64
 | 
					func (user *User) NewGitSig() *git.Signature {
 | 
				
			||||||
	UserId   int64     `xorm:"unique(s)"`
 | 
						return &git.Signature{
 | 
				
			||||||
	FollowId int64     `xorm:"unique(s)"`
 | 
							Name:  user.Name,
 | 
				
			||||||
	Created  time.Time `xorm:"created"`
 | 
							Email: user.Email,
 | 
				
			||||||
 | 
							When:  time.Now(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					// EncodePasswd encodes password to safe format.
 | 
				
			||||||
	ErrUserOwnRepos     = errors.New("User still have ownership of repositories")
 | 
					func (user *User) EncodePasswd() error {
 | 
				
			||||||
	ErrUserAlreadyExist = errors.New("User already exist")
 | 
						newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64)
 | 
				
			||||||
	ErrUserNotExist     = errors.New("User does not exist")
 | 
						user.Passwd = fmt.Sprintf("%x", newPasswd)
 | 
				
			||||||
	ErrEmailAlreadyUsed = errors.New("E-mail already used")
 | 
						return err
 | 
				
			||||||
)
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Member represents user is member of organization.
 | 
				
			||||||
 | 
					type Member struct {
 | 
				
			||||||
 | 
						Id     int64
 | 
				
			||||||
 | 
						OrgId  int64 `xorm:"unique(member) index"`
 | 
				
			||||||
 | 
						UserId int64 `xorm:"unique(member)"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsUserExist checks if given user name exist,
 | 
					// IsUserExist checks if given user name exist,
 | 
				
			||||||
// the user name should be noncased unique.
 | 
					// the user name should be noncased unique.
 | 
				
			||||||
@@ -91,15 +109,6 @@ func IsEmailUsed(email string) (bool, error) {
 | 
				
			|||||||
	return orm.Get(&User{Email: email})
 | 
						return orm.Get(&User{Email: email})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewGitSig generates and returns the signature of given user.
 | 
					 | 
				
			||||||
func (user *User) NewGitSig() *git.Signature {
 | 
					 | 
				
			||||||
	return &git.Signature{
 | 
					 | 
				
			||||||
		Name:  user.Name,
 | 
					 | 
				
			||||||
		Email: user.Email,
 | 
					 | 
				
			||||||
		When:  time.Now(),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// return a user salt token
 | 
					// return a user salt token
 | 
				
			||||||
func GetUserSalt() string {
 | 
					func GetUserSalt() string {
 | 
				
			||||||
	return base.GetRandomString(10)
 | 
						return base.GetRandomString(10)
 | 
				
			||||||
@@ -107,6 +116,10 @@ func GetUserSalt() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// RegisterUser creates record of a new user.
 | 
					// RegisterUser creates record of a new user.
 | 
				
			||||||
func RegisterUser(user *User) (*User, error) {
 | 
					func RegisterUser(user *User) (*User, error) {
 | 
				
			||||||
 | 
						if !IsLegalName(user.Name) {
 | 
				
			||||||
 | 
							return nil, ErrUserNameIllegal
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	isExist, err := IsUserExist(user.Name)
 | 
						isExist, err := IsUserExist(user.Name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -136,7 +149,20 @@ func RegisterUser(user *User) (*User, error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return user, nil
 | 
					
 | 
				
			||||||
 | 
						if user.Id == 1 {
 | 
				
			||||||
 | 
							user.IsAdmin = true
 | 
				
			||||||
 | 
							user.IsActive = true
 | 
				
			||||||
 | 
							_, err = orm.Id(user.Id).UseBool().Update(user)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return user, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetUsers returns given number of user objects with offset.
 | 
				
			||||||
 | 
					func GetUsers(num, offset int) ([]User, error) {
 | 
				
			||||||
 | 
						users := make([]User, 0, num)
 | 
				
			||||||
 | 
						err := orm.Limit(num, offset).Asc("id").Find(&users)
 | 
				
			||||||
 | 
						return users, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// get user by erify code
 | 
					// get user by erify code
 | 
				
			||||||
@@ -217,22 +243,14 @@ func DeleteUser(user *User) error {
 | 
				
			|||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EncodePasswd encodes password to safe format.
 | 
					 | 
				
			||||||
func (user *User) EncodePasswd() error {
 | 
					 | 
				
			||||||
	newPasswd, err := scrypt.Key([]byte(user.Passwd), []byte(base.SecretKey), 16384, 8, 1, 64)
 | 
					 | 
				
			||||||
	user.Passwd = fmt.Sprintf("%x", newPasswd)
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// UserPath returns the path absolute path of user repositories.
 | 
					// UserPath returns the path absolute path of user repositories.
 | 
				
			||||||
func UserPath(userName string) string {
 | 
					func UserPath(userName string) string {
 | 
				
			||||||
	return filepath.Join(RepoRootPath, strings.ToLower(userName))
 | 
						return filepath.Join(base.RepoRootPath, strings.ToLower(userName))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetUserByKeyId(keyId int64) (*User, error) {
 | 
					func GetUserByKeyId(keyId int64) (*User, error) {
 | 
				
			||||||
	user := new(User)
 | 
						user := new(User)
 | 
				
			||||||
	rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?"
 | 
						rawSql := "SELECT a.* FROM `user` AS a, public_key AS b WHERE a.id = b.owner_id AND b.id=?"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	has, err := orm.Sql(rawSql, keyId).Get(user)
 | 
						has, err := orm.Sql(rawSql, keyId).Get(user)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -289,6 +307,13 @@ func LoginUserPlain(name, passwd string) (*User, error) {
 | 
				
			|||||||
	return &user, err
 | 
						return &user, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Follow is connection request for receiving user notifycation.
 | 
				
			||||||
 | 
					type Follow struct {
 | 
				
			||||||
 | 
						Id       int64
 | 
				
			||||||
 | 
						UserId   int64 `xorm:"unique(follow)"`
 | 
				
			||||||
 | 
						FollowId int64 `xorm:"unique(follow)"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FollowUser marks someone be another's follower.
 | 
					// FollowUser marks someone be another's follower.
 | 
				
			||||||
func FollowUser(userId int64, followId int64) (err error) {
 | 
					func FollowUser(userId int64, followId int64) (err error) {
 | 
				
			||||||
	session := orm.NewSession()
 | 
						session := orm.NewSession()
 | 
				
			||||||
@@ -300,19 +325,13 @@ func FollowUser(userId int64, followId int64) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rawSql := "UPDATE user SET num_followers = num_followers + 1 WHERE id = ?"
 | 
						rawSql := "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?"
 | 
				
			||||||
	if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" {
 | 
					 | 
				
			||||||
		rawSql = "UPDATE \"user\" SET num_followers = num_followers + 1 WHERE id = ?"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err = session.Exec(rawSql, followId); err != nil {
 | 
						if _, err = session.Exec(rawSql, followId); err != nil {
 | 
				
			||||||
		session.Rollback()
 | 
							session.Rollback()
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rawSql = "UPDATE user SET num_followings = num_followings + 1 WHERE id = ?"
 | 
						rawSql = "UPDATE `user` SET num_followings = num_followings + 1 WHERE id = ?"
 | 
				
			||||||
	if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" {
 | 
					 | 
				
			||||||
		rawSql = "UPDATE \"user\" SET num_followings = num_followings + 1 WHERE id = ?"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err = session.Exec(rawSql, userId); err != nil {
 | 
						if _, err = session.Exec(rawSql, userId); err != nil {
 | 
				
			||||||
		session.Rollback()
 | 
							session.Rollback()
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -331,19 +350,13 @@ func UnFollowUser(userId int64, unFollowId int64) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rawSql := "UPDATE user SET num_followers = num_followers - 1 WHERE id = ?"
 | 
						rawSql := "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?"
 | 
				
			||||||
	if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" {
 | 
					 | 
				
			||||||
		rawSql = "UPDATE \"user\" SET num_followers = num_followers - 1 WHERE id = ?"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err = session.Exec(rawSql, unFollowId); err != nil {
 | 
						if _, err = session.Exec(rawSql, unFollowId); err != nil {
 | 
				
			||||||
		session.Rollback()
 | 
							session.Rollback()
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rawSql = "UPDATE user SET num_followings = num_followings - 1 WHERE id = ?"
 | 
						rawSql = "UPDATE `user` SET num_followings = num_followings - 1 WHERE id = ?"
 | 
				
			||||||
	if base.Cfg.MustValue("database", "DB_TYPE") == "postgres" {
 | 
					 | 
				
			||||||
		rawSql = "UPDATE \"user\" SET num_followings = num_followings - 1 WHERE id = ?"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if _, err = session.Exec(rawSql, userId); err != nil {
 | 
						if _, err = session.Exec(rawSql, userId); err != nil {
 | 
				
			||||||
		session.Rollback()
 | 
							session.Rollback()
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										55
									
								
								modules/auth/admin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								modules/auth/admin.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					// 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/codegangsta/martini"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/binding"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AdminEditUserForm struct {
 | 
				
			||||||
 | 
						Email    string `form:"email" binding:"Required;Email;MaxSize(50)"`
 | 
				
			||||||
 | 
						Website  string `form:"website" binding:"MaxSize(50)"`
 | 
				
			||||||
 | 
						Location string `form:"location" binding:"MaxSize(50)"`
 | 
				
			||||||
 | 
						Avatar   string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
 | 
				
			||||||
 | 
						Active   string `form:"active"`
 | 
				
			||||||
 | 
						Admin    string `form:"admin"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *AdminEditUserForm) Name(field string) string {
 | 
				
			||||||
 | 
						names := map[string]string{
 | 
				
			||||||
 | 
							"Email":    "E-mail address",
 | 
				
			||||||
 | 
							"Website":  "Website",
 | 
				
			||||||
 | 
							"Location": "Location",
 | 
				
			||||||
 | 
							"Avatar":   "Gravatar Email",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return names[field]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f *AdminEditUserForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) {
 | 
				
			||||||
 | 
						if req.Method == "GET" || errors.Count() == 0 {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData)
 | 
				
			||||||
 | 
						data["HasError"] = true
 | 
				
			||||||
 | 
						AssignForm(f, data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(errors.Overall) > 0 {
 | 
				
			||||||
 | 
							for _, err := range errors.Overall {
 | 
				
			||||||
 | 
								log.Error("AdminEditUserForm.Validate: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						validate(errors, data, f)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -79,7 +79,7 @@ type UpdateProfileForm struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (f *UpdateProfileForm) Name(field string) string {
 | 
					func (f *UpdateProfileForm) Name(field string) string {
 | 
				
			||||||
	names := map[string]string{
 | 
						names := map[string]string{
 | 
				
			||||||
		"Email":    "Email address",
 | 
							"Email":    "E-mail address",
 | 
				
			||||||
		"Website":  "Website",
 | 
							"Website":  "Website",
 | 
				
			||||||
		"Location": "Location",
 | 
							"Location": "Location",
 | 
				
			||||||
		"Avatar":   "Gravatar Email",
 | 
							"Avatar":   "Gravatar Email",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,6 +15,8 @@ import (
 | 
				
			|||||||
	"github.com/Unknwon/com"
 | 
						"github.com/Unknwon/com"
 | 
				
			||||||
	"github.com/Unknwon/goconfig"
 | 
						"github.com/Unknwon/goconfig"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/cache"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -26,20 +28,32 @@ type Mailer struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	AppVer      string
 | 
						AppVer       string
 | 
				
			||||||
	AppName     string
 | 
						AppName      string
 | 
				
			||||||
	AppLogo     string
 | 
						AppLogo      string
 | 
				
			||||||
	AppUrl      string
 | 
						AppUrl       string
 | 
				
			||||||
	Domain      string
 | 
						Domain       string
 | 
				
			||||||
	SecretKey   string
 | 
						SecretKey    string
 | 
				
			||||||
 | 
						RunUser      string
 | 
				
			||||||
 | 
						RepoRootPath string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Cfg         *goconfig.ConfigFile
 | 
						Cfg         *goconfig.ConfigFile
 | 
				
			||||||
	MailService *Mailer
 | 
						MailService *Mailer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Cache        cache.Cache
 | 
				
			||||||
 | 
						CacheAdapter string
 | 
				
			||||||
 | 
						CacheConfig  string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LogMode   string
 | 
				
			||||||
 | 
						LogConfig string
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Service struct {
 | 
					var Service struct {
 | 
				
			||||||
	RegisterEmailConfirm bool
 | 
						RegisterEmailConfirm   bool
 | 
				
			||||||
	ActiveCodeLives      int
 | 
						DisenableRegisteration bool
 | 
				
			||||||
	ResetPwdCodeLives    int
 | 
						RequireSignInView      bool
 | 
				
			||||||
 | 
						ActiveCodeLives        int
 | 
				
			||||||
 | 
						ResetPwdCodeLives      int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func exeDir() (string, error) {
 | 
					func exeDir() (string, error) {
 | 
				
			||||||
@@ -66,19 +80,21 @@ var logLevels = map[string]string{
 | 
				
			|||||||
func newService() {
 | 
					func newService() {
 | 
				
			||||||
	Service.ActiveCodeLives = Cfg.MustInt("service", "ACTIVE_CODE_LIVE_MINUTES", 180)
 | 
						Service.ActiveCodeLives = Cfg.MustInt("service", "ACTIVE_CODE_LIVE_MINUTES", 180)
 | 
				
			||||||
	Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180)
 | 
						Service.ResetPwdCodeLives = Cfg.MustInt("service", "RESET_PASSWD_CODE_LIVE_MINUTES", 180)
 | 
				
			||||||
 | 
						Service.DisenableRegisteration = Cfg.MustBool("service", "DISENABLE_REGISTERATION", false)
 | 
				
			||||||
 | 
						Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW", false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newLogService() {
 | 
					func newLogService() {
 | 
				
			||||||
	// Get and check log mode.
 | 
						// Get and check log mode.
 | 
				
			||||||
	mode := Cfg.MustValue("log", "MODE", "console")
 | 
						LogMode = Cfg.MustValue("log", "MODE", "console")
 | 
				
			||||||
	modeSec := "log." + mode
 | 
						modeSec := "log." + LogMode
 | 
				
			||||||
	if _, err := Cfg.GetSection(modeSec); err != nil {
 | 
						if _, err := Cfg.GetSection(modeSec); err != nil {
 | 
				
			||||||
		fmt.Printf("Unknown log mode: %s\n", mode)
 | 
							fmt.Printf("Unknown log mode: %s\n", LogMode)
 | 
				
			||||||
		os.Exit(2)
 | 
							os.Exit(2)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Log level.
 | 
						// Log level.
 | 
				
			||||||
	levelName := Cfg.MustValue("log."+mode, "LEVEL", "Trace")
 | 
						levelName := Cfg.MustValue("log."+LogMode, "LEVEL", "Trace")
 | 
				
			||||||
	level, ok := logLevels[levelName]
 | 
						level, ok := logLevels[levelName]
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		fmt.Printf("Unknown log level: %s\n", levelName)
 | 
							fmt.Printf("Unknown log level: %s\n", levelName)
 | 
				
			||||||
@@ -86,14 +102,13 @@ func newLogService() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Generate log configuration.
 | 
						// Generate log configuration.
 | 
				
			||||||
	var config string
 | 
						switch LogMode {
 | 
				
			||||||
	switch mode {
 | 
					 | 
				
			||||||
	case "console":
 | 
						case "console":
 | 
				
			||||||
		config = fmt.Sprintf(`{"level":%s}`, level)
 | 
							LogConfig = fmt.Sprintf(`{"level":%s}`, level)
 | 
				
			||||||
	case "file":
 | 
						case "file":
 | 
				
			||||||
		logPath := Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log")
 | 
							logPath := Cfg.MustValue(modeSec, "FILE_NAME", "log/gogs.log")
 | 
				
			||||||
		os.MkdirAll(path.Dir(logPath), os.ModePerm)
 | 
							os.MkdirAll(path.Dir(logPath), os.ModePerm)
 | 
				
			||||||
		config = fmt.Sprintf(
 | 
							LogConfig = fmt.Sprintf(
 | 
				
			||||||
			`{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level,
 | 
								`{"level":%s,"filename":%s,"rotate":%v,"maxlines":%d,"maxsize",%d,"daily":%v,"maxdays":%d}`, level,
 | 
				
			||||||
			logPath,
 | 
								logPath,
 | 
				
			||||||
			Cfg.MustBool(modeSec, "LOG_ROTATE", true),
 | 
								Cfg.MustBool(modeSec, "LOG_ROTATE", true),
 | 
				
			||||||
@@ -102,13 +117,13 @@ func newLogService() {
 | 
				
			|||||||
			Cfg.MustBool(modeSec, "DAILY_ROTATE", true),
 | 
								Cfg.MustBool(modeSec, "DAILY_ROTATE", true),
 | 
				
			||||||
			Cfg.MustInt(modeSec, "MAX_DAYS", 7))
 | 
								Cfg.MustInt(modeSec, "MAX_DAYS", 7))
 | 
				
			||||||
	case "conn":
 | 
						case "conn":
 | 
				
			||||||
		config = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level,
 | 
							LogConfig = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":%s,"addr":%s}`, level,
 | 
				
			||||||
			Cfg.MustBool(modeSec, "RECONNECT_ON_MSG", false),
 | 
								Cfg.MustBool(modeSec, "RECONNECT_ON_MSG", false),
 | 
				
			||||||
			Cfg.MustBool(modeSec, "RECONNECT", false),
 | 
								Cfg.MustBool(modeSec, "RECONNECT", false),
 | 
				
			||||||
			Cfg.MustValue(modeSec, "PROTOCOL", "tcp"),
 | 
								Cfg.MustValue(modeSec, "PROTOCOL", "tcp"),
 | 
				
			||||||
			Cfg.MustValue(modeSec, "ADDR", ":7020"))
 | 
								Cfg.MustValue(modeSec, "ADDR", ":7020"))
 | 
				
			||||||
	case "smtp":
 | 
						case "smtp":
 | 
				
			||||||
		config = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level,
 | 
							LogConfig = fmt.Sprintf(`{"level":%s,"username":%s,"password":%s,"host":%s,"sendTos":%s,"subject":%s}`, level,
 | 
				
			||||||
			Cfg.MustValue(modeSec, "USER", "example@example.com"),
 | 
								Cfg.MustValue(modeSec, "USER", "example@example.com"),
 | 
				
			||||||
			Cfg.MustValue(modeSec, "PASSWD", "******"),
 | 
								Cfg.MustValue(modeSec, "PASSWD", "******"),
 | 
				
			||||||
			Cfg.MustValue(modeSec, "HOST", "127.0.0.1:25"),
 | 
								Cfg.MustValue(modeSec, "HOST", "127.0.0.1:25"),
 | 
				
			||||||
@@ -116,8 +131,32 @@ func newLogService() {
 | 
				
			|||||||
			Cfg.MustValue(modeSec, "SUBJECT", "Diagnostic message from serve"))
 | 
								Cfg.MustValue(modeSec, "SUBJECT", "Diagnostic message from serve"))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), mode, config)
 | 
						log.NewLogger(Cfg.MustInt64("log", "BUFFER_LEN", 10000), LogMode, LogConfig)
 | 
				
			||||||
	log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName)
 | 
						log.Info("Log Mode: %s(%s)", strings.Title(LogMode), levelName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newCacheService() {
 | 
				
			||||||
 | 
						CacheAdapter = Cfg.MustValue("cache", "ADAPTER", "memory")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch CacheAdapter {
 | 
				
			||||||
 | 
						case "memory":
 | 
				
			||||||
 | 
							CacheConfig = fmt.Sprintf(`{"interval":%d}`, Cfg.MustInt("cache", "INTERVAL", 60))
 | 
				
			||||||
 | 
						case "redis", "memcache":
 | 
				
			||||||
 | 
							CacheConfig = fmt.Sprintf(`{"conn":"%s"}`, Cfg.MustValue("cache", "HOST"))
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							fmt.Printf("Unknown cache adapter: %s\n", CacheAdapter)
 | 
				
			||||||
 | 
							os.Exit(2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						Cache, err = cache.NewCache(CacheAdapter, CacheConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Printf("Init cache system failed, adapter: %s, config: %s, %v\n",
 | 
				
			||||||
 | 
								CacheAdapter, CacheConfig, err)
 | 
				
			||||||
 | 
							os.Exit(2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Info("Cache Service Enabled")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newMailService() {
 | 
					func newMailService() {
 | 
				
			||||||
@@ -144,7 +183,7 @@ func newRegisterMailService() {
 | 
				
			|||||||
	log.Info("Register Mail Service Enabled")
 | 
						log.Info("Register Mail Service Enabled")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func NewConfigContext() {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	workDir, err := exeDir()
 | 
						workDir, err := exeDir()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -173,11 +212,20 @@ func init() {
 | 
				
			|||||||
	AppUrl = Cfg.MustValue("server", "ROOT_URL")
 | 
						AppUrl = Cfg.MustValue("server", "ROOT_URL")
 | 
				
			||||||
	Domain = Cfg.MustValue("server", "DOMAIN")
 | 
						Domain = Cfg.MustValue("server", "DOMAIN")
 | 
				
			||||||
	SecretKey = Cfg.MustValue("security", "SECRET_KEY")
 | 
						SecretKey = Cfg.MustValue("security", "SECRET_KEY")
 | 
				
			||||||
 | 
						RunUser = Cfg.MustValue("", "RUN_USER")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Determine and create root git reposiroty path.
 | 
				
			||||||
 | 
						RepoRootPath = Cfg.MustValue("repository", "ROOT")
 | 
				
			||||||
 | 
						if err = os.MkdirAll(RepoRootPath, os.ModePerm); err != nil {
 | 
				
			||||||
 | 
							fmt.Printf("models.init(fail to create RepoRootPath(%s)): %v\n", RepoRootPath, err)
 | 
				
			||||||
 | 
							os.Exit(2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewServices() {
 | 
					func NewServices() {
 | 
				
			||||||
	newService()
 | 
						newService()
 | 
				
			||||||
	newLogService()
 | 
						newLogService()
 | 
				
			||||||
 | 
						newCacheService()
 | 
				
			||||||
	newMailService()
 | 
						newMailService()
 | 
				
			||||||
	newRegisterMailService()
 | 
						newRegisterMailService()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,7 @@ func isLink(link []byte) bool {
 | 
				
			|||||||
func IsMarkdownFile(name string) bool {
 | 
					func IsMarkdownFile(name string) bool {
 | 
				
			||||||
	name = strings.ToLower(name)
 | 
						name = strings.ToLower(name)
 | 
				
			||||||
	switch filepath.Ext(name) {
 | 
						switch filepath.Ext(name) {
 | 
				
			||||||
	case "md", "markdown":
 | 
						case ".md", ".markdown", ".mdown":
 | 
				
			||||||
		return true
 | 
							return true
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
@@ -61,7 +61,7 @@ type CustomRender struct {
 | 
				
			|||||||
func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
 | 
					func (options *CustomRender) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) {
 | 
				
			||||||
	if len(link) > 0 && !isLink(link) {
 | 
						if len(link) > 0 && !isLink(link) {
 | 
				
			||||||
		if link[0] == '#' {
 | 
							if link[0] == '#' {
 | 
				
			||||||
			link = append([]byte(options.urlPrefix), link...)
 | 
								// link = append([]byte(options.urlPrefix), link...)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			link = []byte(path.Join(options.urlPrefix, string(link)))
 | 
								link = []byte(path.Join(options.urlPrefix, string(link)))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,6 +33,10 @@ func List(l *list.List) chan interface{} {
 | 
				
			|||||||
	return c
 | 
						return c
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var mailDomains = map[string]string{
 | 
				
			||||||
 | 
						"gmail.com": "gmail.com",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var TemplateFuncs template.FuncMap = map[string]interface{}{
 | 
					var TemplateFuncs template.FuncMap = map[string]interface{}{
 | 
				
			||||||
	"AppName": func() string {
 | 
						"AppName": func() string {
 | 
				
			||||||
		return AppName
 | 
							return AppName
 | 
				
			||||||
@@ -56,7 +60,12 @@ var TemplateFuncs template.FuncMap = map[string]interface{}{
 | 
				
			|||||||
	"DateFormat": DateFormat,
 | 
						"DateFormat": DateFormat,
 | 
				
			||||||
	"List":       List,
 | 
						"List":       List,
 | 
				
			||||||
	"Mail2Domain": func(mail string) string {
 | 
						"Mail2Domain": func(mail string) string {
 | 
				
			||||||
		return "mail." + strings.Split(mail, "@")[1]
 | 
							suffix := strings.SplitN(mail, "@", 2)[1]
 | 
				
			||||||
 | 
							domain, ok := mailDomains[suffix]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return "mail." + suffix
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return domain
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"SubStr": func(str string, start, length int) string {
 | 
						"SubStr": func(str string, start, length int) string {
 | 
				
			||||||
		return str[start : start+length]
 | 
							return str[start : start+length]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ func (m Message) Content() string {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
var mailQueue chan *Message
 | 
					var mailQueue chan *Message
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func NewMailerContext() {
 | 
				
			||||||
	mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10))
 | 
						mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10))
 | 
				
			||||||
	go processMailQueue()
 | 
						go processMailQueue()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,12 +15,12 @@ func SignInRequire(redirect bool) martini.Handler {
 | 
				
			|||||||
	return func(ctx *Context) {
 | 
						return func(ctx *Context) {
 | 
				
			||||||
		if !ctx.IsSigned {
 | 
							if !ctx.IsSigned {
 | 
				
			||||||
			if redirect {
 | 
								if redirect {
 | 
				
			||||||
				ctx.Redirect("/")
 | 
									ctx.Redirect("/user/login")
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		} else if !ctx.User.IsActive && base.Service.RegisterEmailConfirm {
 | 
							} else if !ctx.User.IsActive && base.Service.RegisterEmailConfirm {
 | 
				
			||||||
			ctx.Data["Title"] = "Activate Your Account"
 | 
								ctx.Data["Title"] = "Activate Your Account"
 | 
				
			||||||
			ctx.Render.HTML(200, "user/active", ctx.Data)
 | 
								ctx.HTML(200, "user/active")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -31,6 +31,18 @@ func SignOutRequire() martini.Handler {
 | 
				
			|||||||
	return func(ctx *Context) {
 | 
						return func(ctx *Context) {
 | 
				
			||||||
		if ctx.IsSigned {
 | 
							if ctx.IsSigned {
 | 
				
			||||||
			ctx.Redirect("/")
 | 
								ctx.Redirect("/")
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AdminRequire requires user signed in as administor.
 | 
				
			||||||
 | 
					func AdminRequire() martini.Handler {
 | 
				
			||||||
 | 
						return func(ctx *Context) {
 | 
				
			||||||
 | 
							if !ctx.User.IsAdmin {
 | 
				
			||||||
 | 
								ctx.Error(403)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx.Data["PageIsAdmin"] = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,8 +12,11 @@ import (
 | 
				
			|||||||
	"github.com/codegangsta/martini"
 | 
						"github.com/codegangsta/martini"
 | 
				
			||||||
	"github.com/martini-contrib/sessions"
 | 
						"github.com/martini-contrib/sessions"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/cache"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -25,6 +28,7 @@ type Context struct {
 | 
				
			|||||||
	Req      *http.Request
 | 
						Req      *http.Request
 | 
				
			||||||
	Res      http.ResponseWriter
 | 
						Res      http.ResponseWriter
 | 
				
			||||||
	Session  sessions.Session
 | 
						Session  sessions.Session
 | 
				
			||||||
 | 
						Cache    cache.Cache
 | 
				
			||||||
	User     *models.User
 | 
						User     *models.User
 | 
				
			||||||
	IsSigned bool
 | 
						IsSigned bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -61,24 +65,29 @@ func (ctx *Context) HasError() bool {
 | 
				
			|||||||
	return hasErr.(bool)
 | 
						return hasErr.(bool)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// HTML calls render.HTML underlying but reduce one argument.
 | 
				
			||||||
 | 
					func (ctx *Context) HTML(status int, name string, htmlOpt ...HTMLOptions) {
 | 
				
			||||||
 | 
						ctx.Render.HTML(status, name, ctx.Data, htmlOpt...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RenderWithErr used for page has form validation but need to prompt error to users.
 | 
					// RenderWithErr used for page has form validation but need to prompt error to users.
 | 
				
			||||||
func (ctx *Context) RenderWithErr(msg, tpl string, form auth.Form) {
 | 
					func (ctx *Context) RenderWithErr(msg, tpl string, form auth.Form) {
 | 
				
			||||||
	ctx.Data["HasError"] = true
 | 
						ctx.Data["HasError"] = true
 | 
				
			||||||
	ctx.Data["ErrorMsg"] = msg
 | 
						ctx.Data["ErrorMsg"] = msg
 | 
				
			||||||
	auth.AssignForm(form, ctx.Data)
 | 
						auth.AssignForm(form, ctx.Data)
 | 
				
			||||||
	ctx.HTML(200, tpl, ctx.Data)
 | 
						ctx.HTML(200, tpl)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Handle handles and logs error by given status.
 | 
					// Handle handles and logs error by given status.
 | 
				
			||||||
func (ctx *Context) Handle(status int, title string, err error) {
 | 
					func (ctx *Context) Handle(status int, title string, err error) {
 | 
				
			||||||
	log.Error("%s: %v", title, err)
 | 
						log.Error("%s: %v", title, err)
 | 
				
			||||||
	if martini.Dev == martini.Prod {
 | 
						if martini.Dev == martini.Prod {
 | 
				
			||||||
		ctx.HTML(500, "status/500", ctx.Data)
 | 
							ctx.HTML(500, "status/500")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["ErrorMsg"] = err
 | 
						ctx.Data["ErrorMsg"] = err
 | 
				
			||||||
	ctx.HTML(status, fmt.Sprintf("status/%d", status), ctx.Data)
 | 
						ctx.HTML(status, fmt.Sprintf("status/%d", status))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// InitContext initializes a classic context for a request.
 | 
					// InitContext initializes a classic context for a request.
 | 
				
			||||||
@@ -92,6 +101,7 @@ func InitContext() martini.Handler {
 | 
				
			|||||||
			Req:     r,
 | 
								Req:     r,
 | 
				
			||||||
			Res:     res,
 | 
								Res:     res,
 | 
				
			||||||
			Session: session,
 | 
								Session: session,
 | 
				
			||||||
 | 
								Cache:   base.Cache,
 | 
				
			||||||
			Render:  rd,
 | 
								Render:  rd,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -106,6 +116,7 @@ func InitContext() martini.Handler {
 | 
				
			|||||||
			ctx.Data["SignedUser"] = user
 | 
								ctx.Data["SignedUser"] = user
 | 
				
			||||||
			ctx.Data["SignedUserId"] = user.Id
 | 
								ctx.Data["SignedUserId"] = user.Id
 | 
				
			||||||
			ctx.Data["SignedUserName"] = user.LowerName
 | 
								ctx.Data["SignedUserName"] = user.LowerName
 | 
				
			||||||
 | 
								ctx.Data["IsAdmin"] = ctx.User.IsAdmin
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Data["PageStartTime"] = time.Now()
 | 
							ctx.Data["PageStartTime"] = time.Now()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,7 @@ func RepoAssignment(redirect bool) martini.Handler {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Repo.Repository = repo
 | 
							ctx.Repo.Repository = repo
 | 
				
			||||||
		ctx.Repo.CloneLink.SSH = fmt.Sprintf("git@%s:%s/%s.git", base.Domain, user.LowerName, repo.LowerName)
 | 
							ctx.Repo.CloneLink.SSH = fmt.Sprintf("git@%s:%s/%s.git", base.Domain, user.LowerName, repo.LowerName)
 | 
				
			||||||
 | 
							ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("https://%s/%s/%s.git", base.Domain, user.LowerName, repo.LowerName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Data["IsRepositoryValid"] = true
 | 
							ctx.Data["IsRepositoryValid"] = true
 | 
				
			||||||
		ctx.Data["Repository"] = repo
 | 
							ctx.Data["Repository"] = repo
 | 
				
			||||||
@@ -78,5 +79,6 @@ func RepoAssignment(redirect bool) martini.Handler {
 | 
				
			|||||||
		ctx.Data["CloneLink"] = ctx.Repo.CloneLink
 | 
							ctx.Data["CloneLink"] = ctx.Repo.CloneLink
 | 
				
			||||||
		ctx.Data["RepositoryLink"] = ctx.Data["Title"]
 | 
							ctx.Data["RepositoryLink"] = ctx.Data["Title"]
 | 
				
			||||||
		ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
 | 
							ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
 | 
				
			||||||
 | 
							ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,8 +145,9 @@ html, body {
 | 
				
			|||||||
    float: right;
 | 
					    float: right;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#gogs-nav-signin {
 | 
					#gogs-nav-signin, #gogs-nav-signup {
 | 
				
			||||||
    float: right;
 | 
					    float: right;
 | 
				
			||||||
 | 
					    margin-left: 1em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#gogs-nav-out .fa {
 | 
					#gogs-nav-out .fa {
 | 
				
			||||||
@@ -324,6 +325,27 @@ html, body {
 | 
				
			|||||||
    color: #444;
 | 
					    color: #444;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.gogs-admin-nav {
 | 
				
			||||||
 | 
					    background-color: #FFF;
 | 
				
			||||||
 | 
					    padding-top: 10px;
 | 
				
			||||||
 | 
					    padding-left: 0;
 | 
				
			||||||
 | 
					    padding-right: 0;
 | 
				
			||||||
 | 
					    border: 1px solid #D8D8D8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.gogs-admin-nav li {
 | 
				
			||||||
 | 
					    margin-bottom: 8px;
 | 
				
			||||||
 | 
					    border-left: 4px solid transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.gogs-admin-nav li:hover {
 | 
				
			||||||
 | 
					    border-left-color: #EEE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.gogs-admin-nav li.active:hover {
 | 
				
			||||||
 | 
					    border-left: 4px solid #DD4B39;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* gogits user ssh keys */
 | 
					/* gogits user ssh keys */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#gogs-ssh-keys .list-group-item {
 | 
					#gogs-ssh-keys .list-group-item {
 | 
				
			||||||
@@ -376,7 +398,7 @@ html, body {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#gogs-feed-right .repo-panel .list-group-item a {
 | 
					#gogs-feed-right .repo-panel .list-group-item a {
 | 
				
			||||||
    display: inline-block;
 | 
					    display: block;
 | 
				
			||||||
    margin-left: 0;
 | 
					    margin-left: 0;
 | 
				
			||||||
    background-color: transparent;
 | 
					    background-color: transparent;
 | 
				
			||||||
    padding-left: 0;
 | 
					    padding-left: 0;
 | 
				
			||||||
@@ -406,7 +428,6 @@ html, body {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#gogs-feed-right .repo-panel span.stars {
 | 
					#gogs-feed-right .repo-panel span.stars {
 | 
				
			||||||
    color: #666;
 | 
					    color: #666;
 | 
				
			||||||
    line-height: 44px;
 | 
					 | 
				
			||||||
    margin-right: 1em;
 | 
					    margin-right: 1em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -445,7 +466,7 @@ html, body {
 | 
				
			|||||||
    padding: 0;
 | 
					    padding: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#gogs-repo-watching .dropdown-menu .dropdown-item:hover .dropdown-header {
 | 
					#gogs-repo-watching .dropdown-menu .dropdown-item:hover .dropdown-header, #gogs-repo-watching .dropdown-item .dropdown-header.text-primary {
 | 
				
			||||||
    color: rgb(65, 131, 196);
 | 
					    color: rgb(65, 131, 196);
 | 
				
			||||||
    cursor: pointer;
 | 
					    cursor: pointer;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -501,8 +522,7 @@ html, body {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.activity-list .info {
 | 
					.activity-list .info {
 | 
				
			||||||
    float: left;
 | 
					    margin: 0 0 0 40px;
 | 
				
			||||||
    padding: 0 0 0 10px;
 | 
					 | 
				
			||||||
    line-height: 1.7em;
 | 
					    line-height: 1.7em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -555,6 +575,15 @@ html, body {
 | 
				
			|||||||
    min-width: 200px;
 | 
					    min-width: 200px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#gogs-repo-clone .dropdown-menu{
 | 
				
			||||||
 | 
					    width: 400px;
 | 
				
			||||||
 | 
					    padding: 20px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#gogs-repo-clone .input-group{
 | 
				
			||||||
 | 
					    margin-bottom: 15px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* #gogs-source */
 | 
					/* #gogs-source */
 | 
				
			||||||
#gogs-source {
 | 
					#gogs-source {
 | 
				
			||||||
    margin-top: -20px;
 | 
					    margin-top: -20px;
 | 
				
			||||||
@@ -645,6 +674,62 @@ html, body {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.file-content .file-body {
 | 
					.file-content .file-body {
 | 
				
			||||||
    padding: 30px 30px 50px;
 | 
					    padding: 30px 30px 50px;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					    background-color: #FFF;
 | 
				
			||||||
 | 
					    overflow: auto;
 | 
				
			||||||
 | 
					    overflow-x: auto;
 | 
				
			||||||
 | 
					    overflow-y: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code pre {
 | 
				
			||||||
 | 
					    background-color: #FFF;
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code {
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code .lines-code > pre {
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					    background: none;
 | 
				
			||||||
 | 
					    border-left: 1px solid #ddd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code .lines-code ol.linenums > .active {
 | 
				
			||||||
 | 
					    background: #ffffdd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code .lines-num {
 | 
				
			||||||
 | 
					    text-align: right;
 | 
				
			||||||
 | 
					    color: #999;
 | 
				
			||||||
 | 
					    background: #fafafa;
 | 
				
			||||||
 | 
					    width: 1%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code .lines-num span {
 | 
				
			||||||
 | 
					    font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
 | 
				
			||||||
 | 
					    line-height: 1.6;
 | 
				
			||||||
 | 
					    padding: 0 8px 0 10px;
 | 
				
			||||||
 | 
					    cursor: pointer;
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
 | 
					    margin-top: 2px;
 | 
				
			||||||
 | 
					    font-size: 90%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code .lines-num span:first-child {
 | 
				
			||||||
 | 
					    margin-top: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code > table {
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.file-content .file-body.file-code > table > tbody > tr,
 | 
				
			||||||
 | 
					.file-content .file-body.file-code > table > tbody > tr > td,
 | 
				
			||||||
 | 
					.file-content .file-body.file-code > table {
 | 
				
			||||||
 | 
					    border: none;
 | 
				
			||||||
 | 
					    background: none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.branch-list th, .commit-list th {
 | 
					.branch-list th, .commit-list th {
 | 
				
			||||||
@@ -724,6 +809,28 @@ html, body {
 | 
				
			|||||||
    background-color: #FFF;
 | 
					    background-color: #FFF;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.commit-list .date {
 | 
				
			||||||
 | 
					    width: 120px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.commit-list .author {
 | 
				
			||||||
 | 
					    min-width: 180px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.guide-box pre, .guide-box .input-group {
 | 
				
			||||||
 | 
					    margin-top: 20px;
 | 
				
			||||||
 | 
					    margin-bottom: 30px;
 | 
				
			||||||
 | 
					    line-height: 24px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.guide-box input[readonly] {
 | 
				
			||||||
 | 
					    background-color: #FFF;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.guide-box {
 | 
				
			||||||
 | 
					    margin-top: 20px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* wrapper and footer */
 | 
					/* wrapper and footer */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#wrapper {
 | 
					#wrapper {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,8 @@
 | 
				
			|||||||
  line-height: 1.7;
 | 
					  line-height: 1.7;
 | 
				
			||||||
  padding: 15px 0 0;
 | 
					  padding: 15px 0 0;
 | 
				
			||||||
  margin: 0 0 15px;
 | 
					  margin: 0 0 15px;
 | 
				
			||||||
  color: #666;
 | 
					  color: #444;
 | 
				
			||||||
 | 
					  font-weight: bold;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown h1,
 | 
					.markdown h1,
 | 
				
			||||||
@@ -86,6 +87,10 @@
 | 
				
			|||||||
  margin-top: 6px;
 | 
					  margin-top: 6px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown li:first-child {
 | 
				
			||||||
 | 
					  margin-top: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown dl dt {
 | 
					.markdown dl dt {
 | 
				
			||||||
  font-style: italic;
 | 
					  font-style: italic;
 | 
				
			||||||
  margin-top: 9px;
 | 
					  margin-top: 9px;
 | 
				
			||||||
@@ -106,8 +111,8 @@
 | 
				
			|||||||
  line-height: 1.6;
 | 
					  line-height: 1.6;
 | 
				
			||||||
  overflow: auto;
 | 
					  overflow: auto;
 | 
				
			||||||
  background: #f8f8f8;
 | 
					  background: #f8f8f8;
 | 
				
			||||||
  padding: 6px 10px;
 | 
					 | 
				
			||||||
  border: 1px solid #ddd;
 | 
					  border: 1px solid #ddd;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown > pre.linenums {
 | 
					.markdown > pre.linenums {
 | 
				
			||||||
@@ -115,6 +120,17 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown > pre > ol.linenums {
 | 
					.markdown > pre > ol.linenums {
 | 
				
			||||||
 | 
					  list-style: none;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown > pre > ol.linenums > li {
 | 
				
			||||||
 | 
					  margin-top: 2px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown > pre.nums-style > ol.linenums {
 | 
				
			||||||
 | 
					  list-style-type: decimal;
 | 
				
			||||||
 | 
					  padding: 0 0 0 40px;
 | 
				
			||||||
  -webkit-box-shadow: inset 40px 0 0 #f5f5f5, inset 41px 0 0 #ccc;
 | 
					  -webkit-box-shadow: inset 40px 0 0 #f5f5f5, inset 41px 0 0 #ccc;
 | 
				
			||||||
  box-shadow: inset 40px 0 0 #f5f5f5, inset 41px 0 0 #ccc;
 | 
					  box-shadow: inset 40px 0 0 #f5f5f5, inset 41px 0 0 #ccc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -130,14 +146,14 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown > pre > ol.linenums > li:first-child {
 | 
					.markdown > pre > ol.linenums > li:first-child {
 | 
				
			||||||
  padding-top: 6px;
 | 
					  padding-top: 12px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown > pre > ol.linenums > li:last-child {
 | 
					.markdown > pre > ol.linenums > li:last-child {
 | 
				
			||||||
  padding-bottom: 6px;
 | 
					  padding-bottom: 12px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.markdown > pre > ol.linenums > li {
 | 
					.markdown > pre.nums-style > ol.linenums > li {
 | 
				
			||||||
  border-left: 1px solid #ddd;
 | 
					  border-left: 1px solid #ddd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -163,6 +179,54 @@
 | 
				
			|||||||
  color: #fff;
 | 
					  color: #fff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown .anchor-wrap {
 | 
				
			||||||
 | 
					  /*margin-top: -50px;*/
 | 
				
			||||||
 | 
					  /*padding-top: 50px;*/
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown h1 a, .markdown h2 a, .markdown h3 a {
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown h1 a.anchor,
 | 
				
			||||||
 | 
					.markdown h2 a.anchor,
 | 
				
			||||||
 | 
					.markdown h3 a.anchor,
 | 
				
			||||||
 | 
					.markdown h4 a.anchor,
 | 
				
			||||||
 | 
					.markdown h5 a.anchor,
 | 
				
			||||||
 | 
					.markdown h6 a.anchor {
 | 
				
			||||||
 | 
					  text-decoration:none;
 | 
				
			||||||
 | 
					  line-height:1;
 | 
				
			||||||
 | 
					  padding-left:0;
 | 
				
			||||||
 | 
					  margin-left:5px;
 | 
				
			||||||
 | 
					  top:15%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.markdown a span.octicon {
 | 
				
			||||||
 | 
					  font-size: 16px;
 | 
				
			||||||
 | 
					  font-family: "FontAwesome";
 | 
				
			||||||
 | 
					  line-height: 1;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					  -webkit-font-smoothing: antialiased;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown a span.octicon-link {
 | 
				
			||||||
 | 
					  display: none;
 | 
				
			||||||
 | 
					  color: #000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown a span.octicon-link:before {
 | 
				
			||||||
 | 
					  content: "\f0c1";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.markdown h1:hover .octicon-link,
 | 
				
			||||||
 | 
					.markdown h2:hover .octicon-link,
 | 
				
			||||||
 | 
					.markdown h3:hover .octicon-link,
 | 
				
			||||||
 | 
					.markdown h4:hover .octicon-link,
 | 
				
			||||||
 | 
					.markdown h5:hover .octicon-link,
 | 
				
			||||||
 | 
					.markdown h6:hover .octicon-link {
 | 
				
			||||||
 | 
					  display:inline-block
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Author: jmblog */
 | 
					/* Author: jmblog */
 | 
				
			||||||
/* Project: https://github.com/jmblog/color-themes-for-google-code-prettify */
 | 
					/* Project: https://github.com/jmblog/color-themes-for-google-code-prettify */
 | 
				
			||||||
/* GitHub Theme */
 | 
					/* GitHub Theme */
 | 
				
			||||||
@@ -187,6 +251,7 @@
 | 
				
			|||||||
  /* a comment */
 | 
					  /* a comment */
 | 
				
			||||||
  .com {
 | 
					  .com {
 | 
				
			||||||
    color: #999988;
 | 
					    color: #999988;
 | 
				
			||||||
 | 
					    font-style: italic;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* a type name */
 | 
					  /* a type name */
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										116
									
								
								public/js/app.js
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								public/js/app.js
									
									
									
									
									
								
							@@ -41,15 +41,15 @@ var Gogits = {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    Gogits.initPopovers = function () {
 | 
					    Gogits.initPopovers = function () {
 | 
				
			||||||
        var hideAllPopovers = function() {
 | 
					        var hideAllPopovers = function () {
 | 
				
			||||||
           $('[data-toggle=popover]').each(function() {
 | 
					            $('[data-toggle=popover]').each(function () {
 | 
				
			||||||
                $(this).popover('hide');
 | 
					                $(this).popover('hide');
 | 
				
			||||||
            });  
 | 
					            });
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $(document).on('click', function(e) {
 | 
					        $(document).on('click', function (e) {
 | 
				
			||||||
            var $e = $(e.target);
 | 
					            var $e = $(e.target);
 | 
				
			||||||
            if($e.data('toggle') == 'popover'||$e.parents("[data-toggle=popover], .popover").length > 0){
 | 
					            if ($e.data('toggle') == 'popover' || $e.parents("[data-toggle=popover], .popover").length > 0) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            hideAllPopovers();
 | 
					            hideAllPopovers();
 | 
				
			||||||
@@ -63,12 +63,56 @@ var Gogits = {
 | 
				
			|||||||
        var $tabs = $('[data-init=tabs]');
 | 
					        var $tabs = $('[data-init=tabs]');
 | 
				
			||||||
        $tabs.find("li:eq(0) a").tab("show");
 | 
					        $tabs.find("li:eq(0) a").tab("show");
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    // fix dropdown inside click
 | 
				
			||||||
 | 
					    Gogits.initDropDown = function(){
 | 
				
			||||||
 | 
					        $('.dropdown-menu').on('click','a,button,input,select',function(e){
 | 
				
			||||||
 | 
					            e.stopPropagation();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // render markdown
 | 
					    // render markdown
 | 
				
			||||||
    Gogits.renderMarkdown = function () {
 | 
					    Gogits.renderMarkdown = function () {
 | 
				
			||||||
        var $pre = $('.markdown').find('pre > code').parent();
 | 
					        var $md = $('.markdown');
 | 
				
			||||||
        $pre.addClass("prettyprint");
 | 
					        var $pre = $md.find('pre > code').parent();
 | 
				
			||||||
 | 
					        $pre.addClass('prettyprint linenums');
 | 
				
			||||||
        prettyPrint();
 | 
					        prettyPrint();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var $lineNums = $pre.parent().siblings('.lines-num');
 | 
				
			||||||
 | 
					        if ($lineNums.length > 0) {
 | 
				
			||||||
 | 
					            var nums = $pre.find('ol.linenums > li').length;
 | 
				
			||||||
 | 
					            for (var i = 1; i <= nums; i++) {
 | 
				
			||||||
 | 
					                $lineNums.append('<span id="L' + i + '" rel=".L' + i + '">' + i + '</span>');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var last;
 | 
				
			||||||
 | 
					            $(document).on('click', '.lines-num span', function () {
 | 
				
			||||||
 | 
					                var $e = $(this);
 | 
				
			||||||
 | 
					                if (last) {
 | 
				
			||||||
 | 
					                    last.removeClass('active');
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                last = $e.parent().siblings('.lines-code').find('ol.linenums > ' + $e.attr('rel'));
 | 
				
			||||||
 | 
					                last.addClass('active');
 | 
				
			||||||
 | 
					                window.location.href = '#' + $e.attr('id');
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Set anchor.
 | 
				
			||||||
 | 
					        var headers = {};
 | 
				
			||||||
 | 
					        $md.find('h1, h2, h3, h4, h5, h6').each(function () {
 | 
				
			||||||
 | 
					            var node = $(this);
 | 
				
			||||||
 | 
					            var val = encodeURIComponent(node.text().toLowerCase().replace(/[^\w\- ]/g, '').replace(/[ ]/g, '-'));
 | 
				
			||||||
 | 
					            var name = val;
 | 
				
			||||||
 | 
					            if (headers[val] > 0) {
 | 
				
			||||||
 | 
					                name = val + '-' + headers[val];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (headers[val] == undefined) {
 | 
				
			||||||
 | 
					                headers[val] = 1;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                headers[val] += 1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            node = node.wrap('<div id="' + name + '" class="anchor-wrap" ></div>');
 | 
				
			||||||
 | 
					            node.append('<a class="anchor" href="#' + name + '"><span class="octicon octicon-link"></span></a>');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
})(jQuery);
 | 
					})(jQuery);
 | 
				
			||||||
@@ -98,6 +142,7 @@ function initCore() {
 | 
				
			|||||||
    Gogits.initPopovers();
 | 
					    Gogits.initPopovers();
 | 
				
			||||||
    Gogits.initTabs();
 | 
					    Gogits.initTabs();
 | 
				
			||||||
    Gogits.initModals();
 | 
					    Gogits.initModals();
 | 
				
			||||||
 | 
					    Gogits.initDropDown();
 | 
				
			||||||
    Gogits.renderMarkdown();
 | 
					    Gogits.renderMarkdown();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -142,6 +187,60 @@ function initUserSetting() {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function initRepository() {
 | 
				
			||||||
 | 
					    // clone group button script
 | 
				
			||||||
 | 
					    (function () {
 | 
				
			||||||
 | 
					        var $clone = $('.clone-group-btn');
 | 
				
			||||||
 | 
					        if ($clone.length) {
 | 
				
			||||||
 | 
					            var $url = $('.clone-group-url');
 | 
				
			||||||
 | 
					            $clone.find('button[data-link]').on("click",function (e) {
 | 
				
			||||||
 | 
					                var $this = $(this);
 | 
				
			||||||
 | 
					                if (!$this.hasClass('btn-primary')) {
 | 
				
			||||||
 | 
					                    $clone.find('.btn-primary').removeClass('btn-primary').addClass("btn-default");
 | 
				
			||||||
 | 
					                    $(this).addClass('btn-primary').removeClass('btn-default');
 | 
				
			||||||
 | 
					                    $url.val($this.data("link"));
 | 
				
			||||||
 | 
					                    $clone.find('span.clone-url').text($this.data('link'));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }).eq(0).trigger("click");
 | 
				
			||||||
 | 
					            // todo copy to clipboard
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    })();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // watching script
 | 
				
			||||||
 | 
					    (function () {
 | 
				
			||||||
 | 
					        var $watch = $('#gogs-repo-watching'),
 | 
				
			||||||
 | 
					            watchLink = $watch.data("watch"),
 | 
				
			||||||
 | 
					            unwatchLink = $watch.data("unwatch");
 | 
				
			||||||
 | 
					        $watch.on('click', '.to-watch',function () {
 | 
				
			||||||
 | 
					            if ($watch.hasClass("watching")) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $.get(watchLink, function (json) {
 | 
				
			||||||
 | 
					                if (json.ok) {
 | 
				
			||||||
 | 
					                    $watch.find('.text-primary').removeClass('text-primary');
 | 
				
			||||||
 | 
					                    $watch.find('.to-watch h4').addClass('text-primary');
 | 
				
			||||||
 | 
					                    $watch.find('.fa-eye-slash').removeClass('fa-eye-slash').addClass('fa-eye');
 | 
				
			||||||
 | 
					                    $watch.removeClass("no-watching").addClass("watching");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }).on('click', '.to-unwatch', function () {
 | 
				
			||||||
 | 
					            if ($watch.hasClass("no-watching")) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $.get(unwatchLink, function (json) {
 | 
				
			||||||
 | 
					                if (json.ok) {
 | 
				
			||||||
 | 
					                    $watch.find('.text-primary').removeClass('text-primary');
 | 
				
			||||||
 | 
					                    $watch.find('.to-unwatch h4').addClass('text-primary');
 | 
				
			||||||
 | 
					                    $watch.find('.fa-eye').removeClass('fa-eye').addClass('fa-eye-slash');
 | 
				
			||||||
 | 
					                    $watch.removeClass("watching").addClass("no-watching");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    })();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(function ($) {
 | 
					(function ($) {
 | 
				
			||||||
    $(function () {
 | 
					    $(function () {
 | 
				
			||||||
        initCore();
 | 
					        initCore();
 | 
				
			||||||
@@ -152,5 +251,8 @@ function initUserSetting() {
 | 
				
			|||||||
        if (body.data("page") == "user") {
 | 
					        if (body.data("page") == "user") {
 | 
				
			||||||
            initUserSetting();
 | 
					            initUserSetting();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        if ($('.gogs-repo-nav').length) {
 | 
				
			||||||
 | 
					            initRepository();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
})(jQuery);
 | 
					})(jQuery);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -340,7 +340,7 @@ q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?
 | 
				
			|||||||
s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
 | 
					s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
 | 
				
			||||||
q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
 | 
					q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
 | 
				
			||||||
c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
 | 
					c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
 | 
				
			||||||
r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;
 | 
					r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d+1),k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;
 | 
				
			||||||
a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
 | 
					a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
 | 
				
			||||||
t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
 | 
					t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
 | 
				
			||||||
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
 | 
					"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
 | 
				
			||||||
@@ -400,7 +400,7 @@ PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000
 | 
				
			|||||||
["kwd",/^-[_a-z]+/],["typ",/^[A-Z_]\w*/],["pun",/^[,.;]/]]),["erlang","erl"]);
 | 
					["kwd",/^-[_a-z]+/],["typ",/^[A-Z_]\w*/],["pun",/^[,.;]/]]),["erlang","erl"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// lang-go.js
 | 
					// lang-go.js
 | 
				
			||||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]);
 | 
					// PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// lang-hs.js
 | 
					// lang-hs.js
 | 
				
			||||||
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/,
 | 
					PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										77
									
								
								routers/admin/admin.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								routers/admin/admin.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					// 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 admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/codegangsta/martini"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Dashboard(ctx *middleware.Context) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = "Admin Dashboard"
 | 
				
			||||||
 | 
						ctx.Data["PageIsDashboard"] = true
 | 
				
			||||||
 | 
						ctx.Data["Stats"] = models.GetStatistic()
 | 
				
			||||||
 | 
						ctx.HTML(200, "admin/dashboard")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Users(ctx *middleware.Context) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = "User Management"
 | 
				
			||||||
 | 
						ctx.Data["PageIsUsers"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						ctx.Data["Users"], err = models.GetUsers(100, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Handle(200, "admin.Users", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.HTML(200, "admin/users")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Repositories(ctx *middleware.Context) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = "Repository Management"
 | 
				
			||||||
 | 
						ctx.Data["PageIsRepos"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						ctx.Data["Repos"], err = models.GetRepos(100, 0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Handle(200, "admin.Repositories", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ctx.HTML(200, "admin/repos")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Config(ctx *middleware.Context) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = "Server Configuration"
 | 
				
			||||||
 | 
						ctx.Data["PageIsConfig"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["AppUrl"] = base.AppUrl
 | 
				
			||||||
 | 
						ctx.Data["Domain"] = base.Domain
 | 
				
			||||||
 | 
						ctx.Data["RunUser"] = base.RunUser
 | 
				
			||||||
 | 
						ctx.Data["RunMode"] = strings.Title(martini.Env)
 | 
				
			||||||
 | 
						ctx.Data["RepoRootPath"] = base.RepoRootPath
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["Service"] = base.Service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["DbCfg"] = models.DbCfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["MailerEnabled"] = false
 | 
				
			||||||
 | 
						if base.MailService != nil {
 | 
				
			||||||
 | 
							ctx.Data["MailerEnabled"] = true
 | 
				
			||||||
 | 
							ctx.Data["Mailer"] = base.MailService
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["CacheAdapter"] = base.CacheAdapter
 | 
				
			||||||
 | 
						ctx.Data["CacheConfig"] = base.CacheConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["LogMode"] = base.LogMode
 | 
				
			||||||
 | 
						ctx.Data["LogConfig"] = base.LogConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.HTML(200, "admin/config")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										109
									
								
								routers/admin/user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								routers/admin/user.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,109 @@
 | 
				
			|||||||
 | 
					// 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 admin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/codegangsta/martini"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewUser(ctx *middleware.Context, form auth.RegisterForm) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = "New Account"
 | 
				
			||||||
 | 
						ctx.Data["PageIsUsers"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
 | 
							ctx.HTML(200, "admin/users/new")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if form.Password != form.RetypePasswd {
 | 
				
			||||||
 | 
							ctx.Data["HasError"] = true
 | 
				
			||||||
 | 
							ctx.Data["Err_Password"] = true
 | 
				
			||||||
 | 
							ctx.Data["Err_RetypePasswd"] = true
 | 
				
			||||||
 | 
							ctx.Data["ErrorMsg"] = "Password and re-type password are not same"
 | 
				
			||||||
 | 
							auth.AssignForm(form, ctx.Data)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ctx.HasError() {
 | 
				
			||||||
 | 
							ctx.HTML(200, "admin/users/new")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u := &models.User{
 | 
				
			||||||
 | 
							Name:     form.UserName,
 | 
				
			||||||
 | 
							Email:    form.Email,
 | 
				
			||||||
 | 
							Passwd:   form.Password,
 | 
				
			||||||
 | 
							IsActive: true,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
						if u, err = models.RegisterUser(u); err != nil {
 | 
				
			||||||
 | 
							switch err {
 | 
				
			||||||
 | 
							case models.ErrUserAlreadyExist:
 | 
				
			||||||
 | 
								ctx.RenderWithErr("Username has been already taken", "admin/users/new", &form)
 | 
				
			||||||
 | 
							case models.ErrEmailAlreadyUsed:
 | 
				
			||||||
 | 
								ctx.RenderWithErr("E-mail address has been already used", "admin/users/new", &form)
 | 
				
			||||||
 | 
							case models.ErrUserNameIllegal:
 | 
				
			||||||
 | 
								ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "admin/users/new", &form)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								ctx.Handle(200, "admin.user.NewUser", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Trace("%s User created by admin(%s): %s", ctx.Req.RequestURI,
 | 
				
			||||||
 | 
							ctx.User.LowerName, strings.ToLower(form.UserName))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Redirect("/admin/users")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func EditUser(ctx *middleware.Context, params martini.Params, form auth.AdminEditUserForm) {
 | 
				
			||||||
 | 
						ctx.Data["Title"] = "Edit Account"
 | 
				
			||||||
 | 
						ctx.Data["PageIsUsers"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uid, err := base.StrTo(params["userid"]).Int()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Handle(200, "admin.user.EditUser", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u, err := models.GetUserById(int64(uid))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.Handle(200, "admin.user.EditUser", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
 | 
							ctx.Data["User"] = u
 | 
				
			||||||
 | 
							ctx.HTML(200, "admin/users/edit")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u.Email = form.Email
 | 
				
			||||||
 | 
						u.Website = form.Website
 | 
				
			||||||
 | 
						u.Location = form.Location
 | 
				
			||||||
 | 
						u.Avatar = base.EncodeMd5(form.Avatar)
 | 
				
			||||||
 | 
						u.AvatarEmail = form.Avatar
 | 
				
			||||||
 | 
						u.IsActive = form.Active == "on"
 | 
				
			||||||
 | 
						u.IsAdmin = form.Admin == "on"
 | 
				
			||||||
 | 
						if err := models.UpdateUser(u); err != nil {
 | 
				
			||||||
 | 
							ctx.Handle(200, "admin.user.EditUser", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["IsSuccess"] = true
 | 
				
			||||||
 | 
						ctx.Data["User"] = u
 | 
				
			||||||
 | 
						ctx.HTML(200, "admin/users/edit")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Trace("%s User profile updated by admin(%s): %s", ctx.Req.RequestURI,
 | 
				
			||||||
 | 
							ctx.User.LowerName, ctx.User.LowerName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -15,10 +15,10 @@ func Home(ctx *middleware.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["PageIsHome"] = true
 | 
						ctx.Data["PageIsHome"] = true
 | 
				
			||||||
	ctx.HTML(200, "home", ctx.Data)
 | 
						ctx.HTML(200, "home")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Help(ctx *middleware.Context) {
 | 
					func Help(ctx *middleware.Context) {
 | 
				
			||||||
	ctx.Data["PageIsHelp"] = true
 | 
						ctx.Data["PageIsHelp"] = true
 | 
				
			||||||
	ctx.HTML(200, "help", ctx.Data)
 | 
						ctx.HTML(200, "help")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,5 +21,5 @@ func TemplatePreview(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
	ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374"
 | 
						ctx.Data["Code"] = "2014031910370000009fff6782aadb2162b4a997acb69d4400888e0b9274657374"
 | 
				
			||||||
	ctx.Data["ActiveCodeLives"] = base.Service.ActiveCodeLives / 60
 | 
						ctx.Data["ActiveCodeLives"] = base.Service.ActiveCodeLives / 60
 | 
				
			||||||
	ctx.Data["ResetPwdCodeLives"] = base.Service.ResetPwdCodeLives / 60
 | 
						ctx.Data["ResetPwdCodeLives"] = base.Service.ResetPwdCodeLives / 60
 | 
				
			||||||
	ctx.HTML(200, params["_1"], ctx.Data)
 | 
						ctx.HTML(200, params["_1"])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
 | 
				
			|||||||
	ctx.Data["Licenses"] = models.Licenses
 | 
						ctx.Data["Licenses"] = models.Licenses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "repo/create", ctx.Data)
 | 
							ctx.HTML(200, "repo/create")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,6 +31,9 @@ func Create(ctx *middleware.Context, form auth.CreateRepoForm) {
 | 
				
			|||||||
	} else if err == models.ErrRepoAlreadyExist {
 | 
						} else if err == models.ErrRepoAlreadyExist {
 | 
				
			||||||
		ctx.RenderWithErr("Repository name has already been used", "repo/create", &form)
 | 
							ctx.RenderWithErr("Repository name has already been used", "repo/create", &form)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 | 
						} else if err == models.ErrRepoNameIllegal {
 | 
				
			||||||
 | 
							ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "repo/create", &form)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Handle(200, "repo.Create", err)
 | 
						ctx.Handle(200, "repo.Create", err)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -45,7 +48,7 @@ func SettingPost(ctx *middleware.Context) {
 | 
				
			|||||||
	case "delete":
 | 
						case "delete":
 | 
				
			||||||
		if len(ctx.Repo.Repository.Name) == 0 || ctx.Repo.Repository.Name != ctx.Query("repository") {
 | 
							if len(ctx.Repo.Repository.Name) == 0 || ctx.Repo.Repository.Name != ctx.Query("repository") {
 | 
				
			||||||
			ctx.Data["ErrorMsg"] = "Please make sure you entered repository name is correct."
 | 
								ctx.Data["ErrorMsg"] = "Please make sure you entered repository name is correct."
 | 
				
			||||||
			ctx.HTML(200, "repo/setting", ctx.Data)
 | 
								ctx.HTML(200, "repo/setting")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,7 +40,7 @@ func Branches(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
	ctx.Data["Branches"] = brs
 | 
						ctx.Data["Branches"] = brs
 | 
				
			||||||
	ctx.Data["IsRepoToolbarBranches"] = true
 | 
						ctx.Data["IsRepoToolbarBranches"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.HTML(200, "repo/branches", ctx.Data)
 | 
						ctx.HTML(200, "repo/branches")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Single(ctx *middleware.Context, params martini.Params) {
 | 
					func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			||||||
@@ -61,6 +61,8 @@ func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["IsRepoToolbarSource"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Branches.
 | 
						// Branches.
 | 
				
			||||||
	brs, err := models.GetBranches(params["username"], params["reponame"])
 | 
						brs, err := models.GetBranches(params["username"], params["reponame"])
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -69,7 +71,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	} else if len(brs) == 0 {
 | 
						} else if len(brs) == 0 {
 | 
				
			||||||
		ctx.Data["IsBareRepo"] = true
 | 
							ctx.Data["IsBareRepo"] = true
 | 
				
			||||||
		ctx.HTML(200, "repo/single", ctx.Data)
 | 
							ctx.HTML(200, "repo/single")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,6 +88,11 @@ func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + params["branchname"]
 | 
						branchLink := "/" + ctx.Repo.Owner.LowerName + "/" + ctx.Repo.Repository.Name + "/src/" + params["branchname"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(treename) != 0 && repoFile == nil {
 | 
				
			||||||
 | 
							ctx.Error(404)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if repoFile != nil && repoFile.IsFile() {
 | 
						if repoFile != nil && repoFile.IsFile() {
 | 
				
			||||||
		if repoFile.Size > 1024*1024 || repoFile.Filemode != git.FileModeBlob {
 | 
							if repoFile.Size > 1024*1024 || repoFile.Filemode != git.FileModeBlob {
 | 
				
			||||||
			ctx.Data["FileIsLarge"] = true
 | 
								ctx.Data["FileIsLarge"] = true
 | 
				
			||||||
@@ -95,6 +102,11 @@ func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.Data["IsFile"] = true
 | 
								ctx.Data["IsFile"] = true
 | 
				
			||||||
			ctx.Data["FileName"] = repoFile.Name
 | 
								ctx.Data["FileName"] = repoFile.Name
 | 
				
			||||||
 | 
								ext := path.Ext(repoFile.Name)
 | 
				
			||||||
 | 
								if len(ext) > 0 {
 | 
				
			||||||
 | 
									ext = ext[1:]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ctx.Data["FileExt"] = ext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name)
 | 
								readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name)
 | 
				
			||||||
			ctx.Data["ReadmeExist"] = readmeExist
 | 
								ctx.Data["ReadmeExist"] = readmeExist
 | 
				
			||||||
@@ -139,10 +151,9 @@ func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				// current repo branch link
 | 
									// current repo branch link
 | 
				
			||||||
				urlPrefix := "http://" + base.Domain + branchLink
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				ctx.Data["FileName"] = readmeFile.Name
 | 
									ctx.Data["FileName"] = readmeFile.Name
 | 
				
			||||||
				ctx.Data["FileContent"] = string(base.RenderMarkdown(blob.Contents(), urlPrefix))
 | 
									ctx.Data["FileContent"] = string(base.RenderMarkdown(blob.Contents(), branchLink))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -178,9 +189,8 @@ func Single(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ctx.Data["Paths"] = Paths
 | 
						ctx.Data["Paths"] = Paths
 | 
				
			||||||
	ctx.Data["Treenames"] = treenames
 | 
						ctx.Data["Treenames"] = treenames
 | 
				
			||||||
	ctx.Data["IsRepoToolbarSource"] = true
 | 
					 | 
				
			||||||
	ctx.Data["BranchLink"] = branchLink
 | 
						ctx.Data["BranchLink"] = branchLink
 | 
				
			||||||
	ctx.HTML(200, "repo/single", ctx.Data)
 | 
						ctx.HTML(200, "repo/single")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Http(ctx *middleware.Context, params martini.Params) {
 | 
					func Http(ctx *middleware.Context, params martini.Params) {
 | 
				
			||||||
@@ -212,6 +222,8 @@ func Setting(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["IsRepoToolbarSetting"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Branches.
 | 
						// Branches.
 | 
				
			||||||
	brs, err := models.GetBranches(params["username"], params["reponame"])
 | 
						brs, err := models.GetBranches(params["username"], params["reponame"])
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -220,7 +232,7 @@ func Setting(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	} else if len(brs) == 0 {
 | 
						} else if len(brs) == 0 {
 | 
				
			||||||
		ctx.Data["IsBareRepo"] = true
 | 
							ctx.Data["IsBareRepo"] = true
 | 
				
			||||||
		ctx.HTML(200, "repo/setting", ctx.Data)
 | 
							ctx.HTML(200, "repo/setting")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -229,9 +241,13 @@ func Setting(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
		title = t
 | 
							title = t
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(params["branchname"]) == 0 {
 | 
				
			||||||
 | 
							params["branchname"] = "master"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Data["Branchname"] = params["branchname"]
 | 
				
			||||||
	ctx.Data["Title"] = title + " - settings"
 | 
						ctx.Data["Title"] = title + " - settings"
 | 
				
			||||||
	ctx.Data["IsRepoToolbarSetting"] = true
 | 
						ctx.HTML(200, "repo/setting")
 | 
				
			||||||
	ctx.HTML(200, "repo/setting", ctx.Data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Commits(ctx *middleware.Context, params martini.Params) {
 | 
					func Commits(ctx *middleware.Context, params martini.Params) {
 | 
				
			||||||
@@ -255,17 +271,17 @@ func Commits(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
	ctx.Data["Reponame"] = params["reponame"]
 | 
						ctx.Data["Reponame"] = params["reponame"]
 | 
				
			||||||
	ctx.Data["CommitCount"] = commits.Len()
 | 
						ctx.Data["CommitCount"] = commits.Len()
 | 
				
			||||||
	ctx.Data["Commits"] = commits
 | 
						ctx.Data["Commits"] = commits
 | 
				
			||||||
	ctx.HTML(200, "repo/commits", ctx.Data)
 | 
						ctx.HTML(200, "repo/commits")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Issues(ctx *middleware.Context) {
 | 
					func Issues(ctx *middleware.Context) {
 | 
				
			||||||
	ctx.Data["IsRepoToolbarIssues"] = true
 | 
						ctx.Data["IsRepoToolbarIssues"] = true
 | 
				
			||||||
	ctx.HTML(200, "repo/issues", ctx.Data)
 | 
						ctx.HTML(200, "repo/issues")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Pulls(ctx *middleware.Context) {
 | 
					func Pulls(ctx *middleware.Context) {
 | 
				
			||||||
	ctx.Data["IsRepoToolbarPulls"] = true
 | 
						ctx.Data["IsRepoToolbarPulls"] = true
 | 
				
			||||||
	ctx.HTML(200, "repo/pulls", ctx.Data)
 | 
						ctx.HTML(200, "repo/pulls")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Action(ctx *middleware.Context, params martini.Params) {
 | 
					func Action(ctx *middleware.Context, params martini.Params) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,13 +24,13 @@ func Setting(ctx *middleware.Context, form auth.UpdateProfileForm) {
 | 
				
			|||||||
	ctx.Data["Owner"] = user
 | 
						ctx.Data["Owner"] = user
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "user/setting", ctx.Data)
 | 
							ctx.HTML(200, "user/setting")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// below is for POST requests
 | 
						// below is for POST requests
 | 
				
			||||||
	if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
						if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
				
			||||||
		ctx.HTML(200, "user/setting", ctx.Data)
 | 
							ctx.HTML(200, "user/setting")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,7 +45,8 @@ func Setting(ctx *middleware.Context, form auth.UpdateProfileForm) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["IsSuccess"] = true
 | 
						ctx.Data["IsSuccess"] = true
 | 
				
			||||||
	ctx.HTML(200, "user/setting", ctx.Data)
 | 
						ctx.HTML(200, "user/setting")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Trace("%s User setting updated: %s", ctx.Req.RequestURI, ctx.User.LowerName)
 | 
						log.Trace("%s User setting updated: %s", ctx.Req.RequestURI, ctx.User.LowerName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,7 +56,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) {
 | 
				
			|||||||
	ctx.Data["IsUserPageSettingPasswd"] = true
 | 
						ctx.Data["IsUserPageSettingPasswd"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "user/password", ctx.Data)
 | 
							ctx.HTML(200, "user/password")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -82,7 +83,7 @@ func SettingPassword(ctx *middleware.Context, form auth.UpdatePasswdForm) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["Owner"] = user
 | 
						ctx.Data["Owner"] = user
 | 
				
			||||||
	ctx.HTML(200, "user/password", ctx.Data)
 | 
						ctx.HTML(200, "user/password")
 | 
				
			||||||
	log.Trace("%s User password updated: %s", ctx.Req.RequestURI, ctx.User.LowerName)
 | 
						log.Trace("%s User password updated: %s", ctx.Req.RequestURI, ctx.User.LowerName)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,7 +124,7 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
 | 
				
			|||||||
	// Add new SSH key.
 | 
						// Add new SSH key.
 | 
				
			||||||
	if ctx.Req.Method == "POST" {
 | 
						if ctx.Req.Method == "POST" {
 | 
				
			||||||
		if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
							if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
				
			||||||
			ctx.HTML(200, "user/publickey", ctx.Data)
 | 
								ctx.HTML(200, "user/publickey")
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -155,7 +156,7 @@ func SettingSSHKeys(ctx *middleware.Context, form auth.AddSSHKeyForm) {
 | 
				
			|||||||
	ctx.Data["PageIsUserSetting"] = true
 | 
						ctx.Data["PageIsUserSetting"] = true
 | 
				
			||||||
	ctx.Data["IsUserPageSettingSSH"] = true
 | 
						ctx.Data["IsUserPageSettingSSH"] = true
 | 
				
			||||||
	ctx.Data["Keys"] = keys
 | 
						ctx.Data["Keys"] = keys
 | 
				
			||||||
	ctx.HTML(200, "user/publickey", ctx.Data)
 | 
						ctx.HTML(200, "user/publickey")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SettingNotification(ctx *middleware.Context) {
 | 
					func SettingNotification(ctx *middleware.Context) {
 | 
				
			||||||
@@ -163,7 +164,7 @@ func SettingNotification(ctx *middleware.Context) {
 | 
				
			|||||||
	ctx.Data["Title"] = "Notification"
 | 
						ctx.Data["Title"] = "Notification"
 | 
				
			||||||
	ctx.Data["PageIsUserSetting"] = true
 | 
						ctx.Data["PageIsUserSetting"] = true
 | 
				
			||||||
	ctx.Data["IsUserPageSettingNotify"] = true
 | 
						ctx.Data["IsUserPageSettingNotify"] = true
 | 
				
			||||||
	ctx.HTML(200, "user/notification", ctx.Data)
 | 
						ctx.HTML(200, "user/notification")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SettingSecurity(ctx *middleware.Context) {
 | 
					func SettingSecurity(ctx *middleware.Context) {
 | 
				
			||||||
@@ -171,5 +172,5 @@ func SettingSecurity(ctx *middleware.Context) {
 | 
				
			|||||||
	ctx.Data["Title"] = "Security"
 | 
						ctx.Data["Title"] = "Security"
 | 
				
			||||||
	ctx.Data["PageIsUserSetting"] = true
 | 
						ctx.Data["PageIsUserSetting"] = true
 | 
				
			||||||
	ctx.Data["IsUserPageSettingSecurity"] = true
 | 
						ctx.Data["IsUserPageSettingSecurity"] = true
 | 
				
			||||||
	ctx.HTML(200, "user/security", ctx.Data)
 | 
						ctx.HTML(200, "user/security")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,7 +34,7 @@ func Dashboard(ctx *middleware.Context) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["Feeds"] = feeds
 | 
						ctx.Data["Feeds"] = feeds
 | 
				
			||||||
	ctx.HTML(200, "user/dashboard", ctx.Data)
 | 
						ctx.HTML(200, "user/dashboard")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Profile(ctx *middleware.Context, params martini.Params) {
 | 
					func Profile(ctx *middleware.Context, params martini.Params) {
 | 
				
			||||||
@@ -70,19 +70,19 @@ func Profile(ctx *middleware.Context, params martini.Params) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["PageIsUserProfile"] = true
 | 
						ctx.Data["PageIsUserProfile"] = true
 | 
				
			||||||
	ctx.HTML(200, "user/profile", ctx.Data)
 | 
						ctx.HTML(200, "user/profile")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
					func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
				
			||||||
	ctx.Data["Title"] = "Log In"
 | 
						ctx.Data["Title"] = "Log In"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "user/signin", ctx.Data)
 | 
							ctx.HTML(200, "user/signin")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
						if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
				
			||||||
		ctx.HTML(200, "user/signin", ctx.Data)
 | 
							ctx.HTML(200, "user/signin")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,8 +112,14 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) {
 | 
				
			|||||||
	ctx.Data["Title"] = "Sign Up"
 | 
						ctx.Data["Title"] = "Sign Up"
 | 
				
			||||||
	ctx.Data["PageIsSignUp"] = true
 | 
						ctx.Data["PageIsSignUp"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if base.Service.DisenableRegisteration {
 | 
				
			||||||
 | 
							ctx.Data["DisenableRegisteration"] = true
 | 
				
			||||||
 | 
							ctx.HTML(200, "user/signup")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "user/signup", ctx.Data)
 | 
							ctx.HTML(200, "user/signup")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,7 +132,7 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.HasError() {
 | 
						if ctx.HasError() {
 | 
				
			||||||
		ctx.HTML(200, "user/signup", ctx.Data)
 | 
							ctx.HTML(200, "user/signup")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -139,11 +145,13 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	if u, err = models.RegisterUser(u); err != nil {
 | 
						if u, err = models.RegisterUser(u); err != nil {
 | 
				
			||||||
		switch err.Error() {
 | 
							switch err {
 | 
				
			||||||
		case models.ErrUserAlreadyExist.Error():
 | 
							case models.ErrUserAlreadyExist:
 | 
				
			||||||
			ctx.RenderWithErr("Username has been already taken", "user/signup", &form)
 | 
								ctx.RenderWithErr("Username has been already taken", "user/signup", &form)
 | 
				
			||||||
		case models.ErrEmailAlreadyUsed.Error():
 | 
							case models.ErrEmailAlreadyUsed:
 | 
				
			||||||
			ctx.RenderWithErr("E-mail address has been already used", "user/signup", &form)
 | 
								ctx.RenderWithErr("E-mail address has been already used", "user/signup", &form)
 | 
				
			||||||
 | 
							case models.ErrUserNameIllegal:
 | 
				
			||||||
 | 
								ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), "user/signup", &form)
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			ctx.Handle(200, "user.SignUp", err)
 | 
								ctx.Handle(200, "user.SignUp", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -153,12 +161,16 @@ func SignUp(ctx *middleware.Context, form auth.RegisterForm) {
 | 
				
			|||||||
	log.Trace("%s User created: %s", ctx.Req.RequestURI, strings.ToLower(form.UserName))
 | 
						log.Trace("%s User created: %s", ctx.Req.RequestURI, strings.ToLower(form.UserName))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Send confirmation e-mail.
 | 
						// Send confirmation e-mail.
 | 
				
			||||||
	if base.Service.RegisterEmailConfirm {
 | 
						if base.Service.RegisterEmailConfirm && u.Id > 1 {
 | 
				
			||||||
		mailer.SendRegisterMail(ctx.Render, u)
 | 
							mailer.SendRegisterMail(ctx.Render, u)
 | 
				
			||||||
		ctx.Data["IsSendRegisterMail"] = true
 | 
							ctx.Data["IsSendRegisterMail"] = true
 | 
				
			||||||
		ctx.Data["Email"] = u.Email
 | 
							ctx.Data["Email"] = u.Email
 | 
				
			||||||
		ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
 | 
							ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
 | 
				
			||||||
		ctx.Render.HTML(200, "user/active", ctx.Data)
 | 
							ctx.HTML(200, "user/active")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err = ctx.Cache.Put("MailResendLimit_"+u.LowerName, u.LowerName, 180); err != nil {
 | 
				
			||||||
 | 
								log.Error("Set cache(MailResendLimit) fail: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Redirect("/user/login")
 | 
						ctx.Redirect("/user/login")
 | 
				
			||||||
@@ -170,7 +182,7 @@ func Delete(ctx *middleware.Context) {
 | 
				
			|||||||
	ctx.Data["IsUserPageSettingDelete"] = true
 | 
						ctx.Data["IsUserPageSettingDelete"] = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "user/delete", ctx.Data)
 | 
							ctx.HTML(200, "user/delete")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -195,7 +207,7 @@ func Delete(ctx *middleware.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.HTML(200, "user/delete", ctx.Data)
 | 
						ctx.HTML(200, "user/delete")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@@ -218,15 +230,15 @@ func Feeds(ctx *middleware.Context, form auth.FeedsForm) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Issues(ctx *middleware.Context) {
 | 
					func Issues(ctx *middleware.Context) {
 | 
				
			||||||
	ctx.HTML(200, "user/issues", ctx.Data)
 | 
						ctx.HTML(200, "user/issues")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Pulls(ctx *middleware.Context) {
 | 
					func Pulls(ctx *middleware.Context) {
 | 
				
			||||||
	ctx.HTML(200, "user/pulls", ctx.Data)
 | 
						ctx.HTML(200, "user/pulls")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Stars(ctx *middleware.Context) {
 | 
					func Stars(ctx *middleware.Context) {
 | 
				
			||||||
	ctx.HTML(200, "user/stars", ctx.Data)
 | 
						ctx.HTML(200, "user/stars")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Activate(ctx *middleware.Context) {
 | 
					func Activate(ctx *middleware.Context) {
 | 
				
			||||||
@@ -239,12 +251,16 @@ func Activate(ctx *middleware.Context) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		// Resend confirmation e-mail.
 | 
							// Resend confirmation e-mail.
 | 
				
			||||||
		if base.Service.RegisterEmailConfirm {
 | 
							if base.Service.RegisterEmailConfirm {
 | 
				
			||||||
			ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
 | 
								if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
 | 
				
			||||||
			mailer.SendActiveMail(ctx.Render, ctx.User)
 | 
									ctx.Data["ResendLimited"] = true
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									ctx.Data["Hours"] = base.Service.ActiveCodeLives / 60
 | 
				
			||||||
 | 
									mailer.SendActiveMail(ctx.Render, ctx.User)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.Data["ServiceNotEnabled"] = true
 | 
								ctx.Data["ServiceNotEnabled"] = true
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		ctx.Render.HTML(200, "user/active", ctx.Data)
 | 
							ctx.HTML(200, "user/active")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -263,5 +279,5 @@ func Activate(ctx *middleware.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Data["IsActivateFailed"] = true
 | 
						ctx.Data["IsActivateFailed"] = true
 | 
				
			||||||
	ctx.Render.HTML(200, "user/active", ctx.Data)
 | 
						ctx.HTML(200, "user/active")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								serve.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								serve.go
									
									
									
									
									
								
							@@ -12,7 +12,9 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/codegangsta/cli"
 | 
						"github.com/codegangsta/cli"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -43,6 +45,10 @@ func In(b string, sl map[string]int) bool {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func runServ(*cli.Context) {
 | 
					func runServ(*cli.Context) {
 | 
				
			||||||
 | 
						base.NewConfigContext()
 | 
				
			||||||
 | 
						models.LoadModelsConfig()
 | 
				
			||||||
 | 
						models.NewEngine()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys := strings.Split(os.Args[2], "-")
 | 
						keys := strings.Split(os.Args[2], "-")
 | 
				
			||||||
	if len(keys) != 2 {
 | 
						if len(keys) != 2 {
 | 
				
			||||||
		fmt.Println("auth file format error")
 | 
							fmt.Println("auth file format error")
 | 
				
			||||||
@@ -144,7 +150,7 @@ func runServ(*cli.Context) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gitcmd := exec.Command(verb, rRepo)
 | 
						gitcmd := exec.Command(verb, rRepo)
 | 
				
			||||||
	gitcmd.Dir = models.RepoRootPath
 | 
						gitcmd.Dir = base.RepoRootPath
 | 
				
			||||||
	gitcmd.Stdout = os.Stdout
 | 
						gitcmd.Stdout = os.Stdout
 | 
				
			||||||
	gitcmd.Stdin = os.Stdin
 | 
						gitcmd.Stdin = os.Stdin
 | 
				
			||||||
	gitcmd.Stderr = os.Stderr
 | 
						gitcmd.Stderr = os.Stderr
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										93
									
								
								templates/admin/config.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								templates/admin/config.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
 | 
					<div id="gogs-body" class="container" data-page="admin">
 | 
				
			||||||
 | 
					    {{template "admin/nav" .}}
 | 
				
			||||||
 | 
					    <div id="gogs-admin-container" class="col-md-9">
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Server Configuration
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <div><b>Application Name:</b> {{AppName}}</div>
 | 
				
			||||||
 | 
					                <div><b>Application Version:</b> {{AppVer}}</div>
 | 
				
			||||||
 | 
					                <div><b>Application URL:</b> {{.AppUrl}}</div>
 | 
				
			||||||
 | 
					                <div><b>Domain:</b> {{.Domain}}</div>
 | 
				
			||||||
 | 
					                <hr/>
 | 
				
			||||||
 | 
					                <div><b>Run User:</b> {{.RunUser}}</div>
 | 
				
			||||||
 | 
					                <div><b>Run Mode:</b> {{.RunMode}}</div>
 | 
				
			||||||
 | 
					                <hr/>
 | 
				
			||||||
 | 
					                <div><b>Repository Root Path:</b> {{.RepoRootPath}}</div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Database Configuration
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <div><b>Type:</b> {{.DbCfg.Type}}</div>
 | 
				
			||||||
 | 
					                <div><b>Host:</b> {{.DbCfg.Host}}</div>
 | 
				
			||||||
 | 
					                <div><b>Name:</b> {{.DbCfg.Name}}</div>
 | 
				
			||||||
 | 
					                <div><b>User:</b> {{.DbCfg.User}}</div>
 | 
				
			||||||
 | 
					                <div><b>SslMode:</b> {{.DbCfg.SslMode}} (for "postgres" only)</div>
 | 
				
			||||||
 | 
					                <div><b>Path:</b> {{.DbCfg.Path}} (for "sqlite3" only)</div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Service Configuration
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <div><b>Register Email Confirmation:</b> <i class="fa fa{{if .Service.RegisterEmailConfirm}}-check{{end}}-square-o"></i></div>
 | 
				
			||||||
 | 
					                <div><b>Disenable Registeration:</b> <i class="fa fa{{if .Service.DisenableRegisteration}}-check{{end}}-square-o"></i></div>
 | 
				
			||||||
 | 
					                <div><b>Require Sign In View:</b> <i class="fa fa{{if .Service.RequireSignInView}}-check{{end}}-square-o"></i></div>
 | 
				
			||||||
 | 
					                <hr/>
 | 
				
			||||||
 | 
					                <div><b>Active Code Lives:</b> {{.Service.ActiveCodeLives}} minutes</div>
 | 
				
			||||||
 | 
					                <div><b>Reset Password Code Lives:</b> {{.Service.ResetPwdCodeLives}} minutes</div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Mailer Configuration
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <div><b>Enabled:</b> <i class="fa fa{{if .MailerEnabled}}-check{{end}}-square-o"></i></div>
 | 
				
			||||||
 | 
					                <div><b>Name:</b> {{.Mailer.Name}}</div>
 | 
				
			||||||
 | 
					                <div><b>Host:</b> {{.Mailer.Host}}</div>
 | 
				
			||||||
 | 
					                <div><b>User:</b> {{.Mailer.User}}</div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Cache Configuration
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <div><b>Cache Adapter:</b> {{.CacheAdapter}}</div>
 | 
				
			||||||
 | 
					                <div><b>Cache Config:</b></div>
 | 
				
			||||||
 | 
					                <div style="padding-top: 5px;"><pre>{{.CacheConfig}}</pre></div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Log Configuration
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <div><b>Log Mode:</b> {{.LogMode}}</div>
 | 
				
			||||||
 | 
					                <div><b>Log Config:</b></div>
 | 
				
			||||||
 | 
					                <div style="padding-top: 5px;"><pre>{{.LogConfig}}</pre></div>
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										26
									
								
								templates/admin/dashboard.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								templates/admin/dashboard.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
 | 
					<div id="gogs-body" class="container" data-page="admin">
 | 
				
			||||||
 | 
					    {{template "admin/nav" .}}
 | 
				
			||||||
 | 
					    <div id="gogs-admin-container" class="col-md-9">
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Statistic
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                Gogs database has <b>{{.Stats.Counter.User}}</b> users, <b>{{.Stats.Counter.PublicKey}}</b> SSH keys, <b>{{.Stats.Counter.Repo}}</b> repositories, <b>{{.Stats.Counter.Watch}}</b> watches, <b>{{.Stats.Counter.Action}}</b> actions, and <b>{{.Stats.Counter.Access}}</b> accesses.
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                System Status
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										8
									
								
								templates/admin/nav.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								templates/admin/nav.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					<div id="gogs-user-setting-nav" class="col-md-3 gogs-admin-nav">
 | 
				
			||||||
 | 
					    <ul class="list-group" data-init="tabs">
 | 
				
			||||||
 | 
					        <li class="list-group-item{{if .PageIsDashboard}} active{{end}}"><a href="/admin"><i class="fa fa-tachometer fa-lg"></i> Dashboard</a></li>
 | 
				
			||||||
 | 
					        <li class="list-group-item{{if .PageIsUsers}} active{{end}}"><a href="/admin/users"><i class="fa fa-users fa-lg"></i> Users</a></li>
 | 
				
			||||||
 | 
					        <li class="list-group-item{{if .PageIsRepos}} active{{end}}"><a href="/admin/repos"><i class="fa fa-book fa-lg"></i> Repositories</a></li>
 | 
				
			||||||
 | 
					        <li class="list-group-item{{if .PageIsConfig}} active{{end}}"><a href="/admin/config"><i class="fa fa-cogs fa-lg"></i> Configuration</a></li>
 | 
				
			||||||
 | 
					    </ul>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
							
								
								
									
										42
									
								
								templates/admin/repos.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								templates/admin/repos.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
 | 
					<div id="gogs-body" class="container" data-page="admin">
 | 
				
			||||||
 | 
					    {{template "admin/nav" .}}
 | 
				
			||||||
 | 
					    <div id="gogs-admin-container" class="col-md-9">
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Repository Management
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <table class="table table-striped">
 | 
				
			||||||
 | 
					                    <thead>
 | 
				
			||||||
 | 
					                        <tr>
 | 
				
			||||||
 | 
					                            <th>Id</th>
 | 
				
			||||||
 | 
					                            <th>Owner</th>
 | 
				
			||||||
 | 
					                            <th>Name</th>
 | 
				
			||||||
 | 
					                            <th>Private</th>
 | 
				
			||||||
 | 
					                            <th>Watches</th>
 | 
				
			||||||
 | 
					                            <th>Forks</th>
 | 
				
			||||||
 | 
					                            <th>Created</th>
 | 
				
			||||||
 | 
					                        </tr>
 | 
				
			||||||
 | 
					                    </thead>
 | 
				
			||||||
 | 
					                    <tbody>
 | 
				
			||||||
 | 
					                        {{range .Repos}}
 | 
				
			||||||
 | 
					                        <tr>
 | 
				
			||||||
 | 
					                            <td>{{.Id}}</td>
 | 
				
			||||||
 | 
					                            <th>{{.UserName}}</th>
 | 
				
			||||||
 | 
					                            <td><a href="/{{.UserName}}/{{.Name}}">{{.Name}}</a></td>
 | 
				
			||||||
 | 
					                            <td><i class="fa fa{{if .Private}}-check{{end}}-square-o"></i></td>
 | 
				
			||||||
 | 
					                            <td>{{.NumWatches}}</td>
 | 
				
			||||||
 | 
					                            <td>{{.NumForks}}</td>
 | 
				
			||||||
 | 
					                            <td>{{DateFormat .Created "M d, Y"}}</td>
 | 
				
			||||||
 | 
					                        </tr>
 | 
				
			||||||
 | 
					                        {{end}}
 | 
				
			||||||
 | 
					                    </tbody>
 | 
				
			||||||
 | 
					                </table>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										45
									
								
								templates/admin/users.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								templates/admin/users.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
 | 
					<div id="gogs-body" class="container" data-page="admin">
 | 
				
			||||||
 | 
					    {{template "admin/nav" .}}
 | 
				
			||||||
 | 
					    <div id="gogs-admin-container" class="col-md-9">
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                User Management
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					                <a href="/admin/users/new" class="btn btn-primary">New Account</a>
 | 
				
			||||||
 | 
					                <table class="table table-striped">
 | 
				
			||||||
 | 
					                    <thead>
 | 
				
			||||||
 | 
					                        <tr>
 | 
				
			||||||
 | 
					                            <th>Id</th>
 | 
				
			||||||
 | 
					                            <th>Name</th>
 | 
				
			||||||
 | 
					                            <th>E-mail</th>
 | 
				
			||||||
 | 
					                            <th>Actived</th>
 | 
				
			||||||
 | 
					                            <th>Admin</th>
 | 
				
			||||||
 | 
					                            <th>Repos</th>
 | 
				
			||||||
 | 
					                            <th>Join</th>
 | 
				
			||||||
 | 
					                            <th>Edit</th>
 | 
				
			||||||
 | 
					                        </tr>
 | 
				
			||||||
 | 
					                    </thead>
 | 
				
			||||||
 | 
					                    <tbody>
 | 
				
			||||||
 | 
					                        {{range .Users}}
 | 
				
			||||||
 | 
					                        <tr>
 | 
				
			||||||
 | 
					                            <td>{{.Id}}</td>
 | 
				
			||||||
 | 
					                            <td><a href="/user/{{.Name}}">{{.Name}}</a></td>
 | 
				
			||||||
 | 
					                            <td>{{.Email}}</td>
 | 
				
			||||||
 | 
					                            <td><i class="fa fa{{if .IsActive}}-check{{end}}-square-o"></i></td>
 | 
				
			||||||
 | 
					                            <td><i class="fa fa{{if .IsAdmin}}-check{{end}}-square-o"></i></td>
 | 
				
			||||||
 | 
					                            <td>{{.NumRepos}}</td>
 | 
				
			||||||
 | 
					                            <td>{{DateFormat .Created "M d, Y"}}</td>
 | 
				
			||||||
 | 
					                            <td><a href="/admin/users/{{.Id}}"><i class="fa fa-pencil-square-o"></i></a></td>
 | 
				
			||||||
 | 
					                        </tr>
 | 
				
			||||||
 | 
					                        {{end}}
 | 
				
			||||||
 | 
					                    </tbody>
 | 
				
			||||||
 | 
					                </table>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										83
									
								
								templates/admin/users/edit.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								templates/admin/users/edit.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
 | 
					<div id="gogs-body" class="container" data-page="admin">
 | 
				
			||||||
 | 
					    {{template "admin/nav" .}}
 | 
				
			||||||
 | 
					    <div id="gogs-admin-container" class="col-md-9">
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                Edit Account
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					            	<br/>
 | 
				
			||||||
 | 
									<form action="/admin/users/{{.User.Id}}" method="post" class="form-horizontal">
 | 
				
			||||||
 | 
									    {{if .IsSuccess}}<p class="alert alert-success">Account profile has been successfully updated.</p>{{else if .HasError}}<p class="alert alert-danger form-error">{{.ErrorMsg}}</p>{{end}}
 | 
				
			||||||
 | 
					                	<input type="hidden" value="{{.User.Id}}" name="userId"/>
 | 
				
			||||||
 | 
										<div class="form-group">
 | 
				
			||||||
 | 
											<label class="col-md-3 control-label">Username: </label>
 | 
				
			||||||
 | 
											<label class="control-label">{{.User.Name}}</label>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}">
 | 
				
			||||||
 | 
											<label class="col-md-3 control-label">Email<strong class="text-danger">*</strong></label>
 | 
				
			||||||
 | 
											<div class="col-md-7">
 | 
				
			||||||
 | 
												<input name="email" class="form-control" placeholder="Type account's e-mail address" value="{{.User.Email}}" required="required">
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						                <div class="form-group">
 | 
				
			||||||
 | 
						                    <label class="col-md-3 control-label">Website</label>
 | 
				
			||||||
 | 
						                    <div class="col-md-7">
 | 
				
			||||||
 | 
						                        <input name="website" class="form-control" placeholder="Type account's website URL" value="{{.User.Website}}">
 | 
				
			||||||
 | 
						                    </div>
 | 
				
			||||||
 | 
						                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						                <div class="form-group">
 | 
				
			||||||
 | 
						                    <label class="col-md-3 control-label">Location</label>
 | 
				
			||||||
 | 
						                    <div class="col-md-7">
 | 
				
			||||||
 | 
						                        <input name="location" class="form-control" placeholder="Type account's current location" value="{{.User.Location}}">
 | 
				
			||||||
 | 
						                    </div>
 | 
				
			||||||
 | 
						                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						                <div class="form-group {{if .Err_Avatar}}has-error has-feedback{{end}}">
 | 
				
			||||||
 | 
						                    <label class="col-md-3 control-label">Gravatar Email<strong class="text-danger">*</strong></label>
 | 
				
			||||||
 | 
						                    <div class="col-md-7">
 | 
				
			||||||
 | 
						                        <input name="avatar" class="form-control" placeholder="Type account's Gravatar e-mail address" required="required" value="{{.User.AvatarEmail}}">
 | 
				
			||||||
 | 
						                    </div>
 | 
				
			||||||
 | 
						                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						                <div class="form-group">
 | 
				
			||||||
 | 
								            <div class="col-md-7 col-md-offset-3">
 | 
				
			||||||
 | 
								                <div class="checkbox">
 | 
				
			||||||
 | 
								                    <label>
 | 
				
			||||||
 | 
								                        <input type="checkbox" name="active" {{if .User.IsActive}}checked{{end}}>
 | 
				
			||||||
 | 
								                        <strong>This account has activated</strong>
 | 
				
			||||||
 | 
								                    </label>
 | 
				
			||||||
 | 
								                </div>
 | 
				
			||||||
 | 
								            </div>
 | 
				
			||||||
 | 
						                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						                <div class="form-group">
 | 
				
			||||||
 | 
								            <div class="col-md-7 col-md-offset-3">
 | 
				
			||||||
 | 
								                <div class="checkbox">
 | 
				
			||||||
 | 
								                    <label>
 | 
				
			||||||
 | 
								                        <input type="checkbox" name="admin" {{if .User.IsAdmin}}checked{{end}}>
 | 
				
			||||||
 | 
								                        <strong>This account has administor permisson</strong>
 | 
				
			||||||
 | 
								                    </label>
 | 
				
			||||||
 | 
								                </div>
 | 
				
			||||||
 | 
								            </div>
 | 
				
			||||||
 | 
						                </div>
 | 
				
			||||||
 | 
										<hr/>
 | 
				
			||||||
 | 
										<div class="form-group">
 | 
				
			||||||
 | 
										    <div class="col-md-offset-3 col-md-6">
 | 
				
			||||||
 | 
										    	<button type="submit" class="btn btn-lg btn-primary btn-block">Update account profile</button>
 | 
				
			||||||
 | 
										    	<!-- <a type="button" href="/admin/users/{{.User.Id}}/delete" class="btn btn-lg btn-danger btn-block">Delete this account</a> -->
 | 
				
			||||||
 | 
										    </div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</form>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										54
									
								
								templates/admin/users/new.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								templates/admin/users/new.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					{{template "base/head" .}}
 | 
				
			||||||
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
 | 
					<div id="gogs-body" class="container" data-page="admin">
 | 
				
			||||||
 | 
					    {{template "admin/nav" .}}
 | 
				
			||||||
 | 
					    <div id="gogs-admin-container" class="col-md-9">
 | 
				
			||||||
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
 | 
					            <div class="panel-heading">
 | 
				
			||||||
 | 
					                New Account
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="panel-body">
 | 
				
			||||||
 | 
					            	<br/>
 | 
				
			||||||
 | 
									<form action="/admin/users/new" method="post" class="form-horizontal">
 | 
				
			||||||
 | 
									    <div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div>
 | 
				
			||||||
 | 
										<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}">
 | 
				
			||||||
 | 
											<label class="col-md-3 control-label">Username: </label>
 | 
				
			||||||
 | 
											<div class="col-md-7">
 | 
				
			||||||
 | 
												<input name="username" class="form-control" placeholder="Type account's username" value="{{.username}}" required="required">
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}">
 | 
				
			||||||
 | 
											<label class="col-md-3 control-label">Email: </label>
 | 
				
			||||||
 | 
											<div class="col-md-7">
 | 
				
			||||||
 | 
												<input name="email" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid">
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="form-group {{if .Err_Password}}has-error has-feedback{{end}}">
 | 
				
			||||||
 | 
											<label class="col-md-3 control-label">Password: </label>
 | 
				
			||||||
 | 
											<div class="col-md-7">
 | 
				
			||||||
 | 
												<input name="passwd" type="password" class="form-control" placeholder="Type account's password" required="required" title="Password must contain at least 6 characters">
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										<div class="form-group {{if .Err_RetypePasswd}}has-error has-feedback{{end}}">
 | 
				
			||||||
 | 
											<label class="col-md-3 control-label">Re-type: </label>
 | 
				
			||||||
 | 
											<div class="col-md-7">
 | 
				
			||||||
 | 
												<input name="retypepasswd" type="password" class="form-control" placeholder="Re-type account's password" required="required" title="Re-type Password must be same to Password">
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
										<hr/>
 | 
				
			||||||
 | 
										<div class="form-group">
 | 
				
			||||||
 | 
										    <div class="col-md-offset-3 col-md-7">
 | 
				
			||||||
 | 
										    	<button type="submit" class="btn btn-lg btn-primary">Create new account</button>
 | 
				
			||||||
 | 
										    </div>
 | 
				
			||||||
 | 
										</div>
 | 
				
			||||||
 | 
									</form>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
@@ -2,12 +2,19 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
<footer id="footer">
 | 
					<footer id="footer">
 | 
				
			||||||
    <div class="container footer-wrap">
 | 
					    <div class="container footer-wrap">
 | 
				
			||||||
        <p>© 2014 Gogs · ver {{AppVer}} ·
 | 
					    	<div class="row">
 | 
				
			||||||
            All: {{LoadTimes .PageStartTime}} ·
 | 
						    	<div class="col-md-6">
 | 
				
			||||||
            Tmpl: {{call .TmplLoadTimes}} ·
 | 
							        <p>© 2014 GoGits · Version: {{AppVer}} ·
 | 
				
			||||||
            <i class="fa fa-github"></i><a target="_blank" href="https://github.com/gogits/gogs">GitHub</a> ·
 | 
							            Page: <b>{{LoadTimes .PageStartTime}}</b> ·
 | 
				
			||||||
        </p>
 | 
							            Template: <b>{{call .TmplLoadTimes}}</b>
 | 
				
			||||||
        <p class="desc"></p>
 | 
							        </p>
 | 
				
			||||||
 | 
						        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    	<div class="col-md-1" style="margin: -5px;">
 | 
				
			||||||
 | 
							        <a target="_blank" href="https://github.com/gogits/gogs"><i class="fa fa-github fa-2x"></i></a>
 | 
				
			||||||
 | 
						        </div>
 | 
				
			||||||
 | 
						        <p class="desc"></p>
 | 
				
			||||||
 | 
					    	</div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</footer>
 | 
					</footer>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,9 @@
 | 
				
			|||||||
            </a>
 | 
					            </a>
 | 
				
			||||||
            <a class="navbar-right gogs-nav-item{{if .PageIsNewRepo}} active{{end}}" href="/repo/create" data-toggle="tooltip" data-placement="bottom" title="New Repository"><i class="fa fa-plus fa-lg"></i></a>
 | 
					            <a class="navbar-right gogs-nav-item{{if .PageIsNewRepo}} active{{end}}" href="/repo/create" data-toggle="tooltip" data-placement="bottom" title="New Repository"><i class="fa fa-plus fa-lg"></i></a>
 | 
				
			||||||
            <a class="navbar-right gogs-nav-item{{if .PageIsUserSetting}} active{{end}}" href="/user/setting"  data-toggle="tooltip" data-placement="bottom" title="Setting"><i class="fa fa-cogs fa-lg"></i></a>
 | 
					            <a class="navbar-right gogs-nav-item{{if .PageIsUserSetting}} active{{end}}" href="/user/setting"  data-toggle="tooltip" data-placement="bottom" title="Setting"><i class="fa fa-cogs fa-lg"></i></a>
 | 
				
			||||||
            {{else}}<a id="gogs-nav-signin" class="gogs-nav-item navbar-right navbar-btn btn btn-danger" href="/user/login/">Sign in</a>{{end}}
 | 
					            {{if .IsAdmin}}<a class="navbar-right gogs-nav-item{{if .PageIsAdmin}} active{{end}}" href="/admin"  data-toggle="tooltip" data-placement="bottom" title="Admin"><i class="fa fa-gear fa-lg"></i></a>{{end}}
 | 
				
			||||||
 | 
					            {{else}}<a id="gogs-nav-signin" class="gogs-nav-item navbar-right navbar-btn btn btn-danger" href="/user/login/">Sign In</a>
 | 
				
			||||||
 | 
					            <a id="gogs-nav-signup" class="gogs-nav-item navbar-right navbar-btn btn btn-info" href="/user/sign_up/">Sign Up</a>{{end}}
 | 
				
			||||||
        </nav>
 | 
					        </nav>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,40 +5,62 @@
 | 
				
			|||||||
                <h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / {{.Repository.Name}}</h3>
 | 
					                <h3 class="name"><i class="fa fa-book fa-lg"></i><a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> / {{.Repository.Name}}</h3>
 | 
				
			||||||
                <p class="desc">{{.Repository.Description}}{{if .Repository.Website}}<a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p>
 | 
					                <p class="desc">{{.Repository.Description}}{{if .Repository.Website}}<a href="{{.Repository.Website}}">{{.Repository.Website}}</a>{{end}}</p>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            {{if not .IsBareRepo}}
 | 
					            <div class="col-md-6 actions text-right clone-group-btn">
 | 
				
			||||||
            <div class="col-md-6 actions text-right">
 | 
					                {{if not .IsBareRepo}}
 | 
				
			||||||
                <div class="btn-group" id="gogs-repo-clone">
 | 
					                <!--<div class="btn-group" id="gogs-repo-clone">
 | 
				
			||||||
                    <button type="button" class="btn btn-default"><i class="fa fa-download fa-lg fa-m"></i></button>
 | 
					                    <button type="button" class="btn btn-default"><i class="fa fa-download fa-lg fa-m"></i></button>
 | 
				
			||||||
                    <button type="button" class="btn btn-default dropdown-toggle" data-container="body" data-toggle="popover" data-placement="bottom" data-content="<label>SSH:</label><div class='input-group'><input type='text' class='form-control' value='{{.CloneLink.SSH}}'></div>" data-html="1">
 | 
					                    <button type="button" class="btn btn-default dropdown-toggle" data-container="body" data-toggle="popover" data-placement="bottom" data-content="<label>SSH:</label><div class='input-group'><input type='text' class='form-control' value='{{.CloneLink.SSH}}'></div>" data-html="1">
 | 
				
			||||||
                        <span class="caret"></span>
 | 
					                        <span class="caret"></span>
 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
                </div>
 | 
					                </div>-->
 | 
				
			||||||
                <div class="btn-group" id="gogs-repo-watching">
 | 
					                <div class="btn-group" id="gogs-repo-clone">
 | 
				
			||||||
                    <button type="button" class="btn btn-default"><i class="fa fa-eye fa-lg fa-m"></i></button>
 | 
					                    <button type="button" class="btn btn-default"><i class="fa fa-download fa-lg fa-m"></i></button>
 | 
				
			||||||
                    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
 | 
					                    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
 | 
				
			||||||
                        <span class="caret"></span>
 | 
					                        <span class="caret"></span>
 | 
				
			||||||
                        <span class="sr-only">Toggle Dropdown</span>
 | 
					 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
                    <div class="dropdown-menu" role="menu">
 | 
					                    <div class="dropdown-menu clone-group-btn dropdown-menu-right">
 | 
				
			||||||
                        <div class="dropdown-item text-left" data-val="not-watching">
 | 
					                        <div class="input-group">
 | 
				
			||||||
                            <h4 role="presentation" class="dropdown-header">Not Watching</h4>
 | 
					                            <span class="input-group-btn">
 | 
				
			||||||
 | 
					                                <button class="btn btn-default" data-link="{{.CloneLink.SSH}}" type="button">SSH</button>
 | 
				
			||||||
 | 
					                                <button class="btn btn-default" data-link="{{.CloneLink.HTTPS}}" type="button">HTTPS</button>
 | 
				
			||||||
 | 
					                            </span>
 | 
				
			||||||
 | 
					                            <input type="text" class="form-control clone-group-url" value="" readonly/>
 | 
				
			||||||
 | 
					                            <span class="input-group-btn">
 | 
				
			||||||
 | 
					                                <button class="btn btn-default" type="button"><i class="fa fa-copy" data-toggle="tooltip" title="copy to clipboard" data-placement="top"></i></button>
 | 
				
			||||||
 | 
					                            </span>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                        <p class="help-block text-center">Need help cloning? Visit <a href="#">Help</a>!</p>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="btn-group {{if .IsRepositoryWatching}}watching{{else}}no-watching{{end}}" id="gogs-repo-watching" data-watch="/{{.SignedUser.Name}}/{{.Repository.Name}}/action/watch" data-unwatch="/{{.SignedUser.Name}}/{{.Repository.Name}}/action/unwatch">
 | 
				
			||||||
 | 
					                    {{if .IsRepositoryWatching}}
 | 
				
			||||||
 | 
					                    <button type="button" class="btn btn-default"><i class="fa fa-eye fa-lg fa-m"></i></button>
 | 
				
			||||||
 | 
					                    {{else}}
 | 
				
			||||||
 | 
					                    <button type="button" class="btn btn-default"><i class="fa fa-eye-slash fa-lg fa-m"></i></button>
 | 
				
			||||||
 | 
					                    {{end}}
 | 
				
			||||||
 | 
					                    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
 | 
				
			||||||
 | 
					                        <span class="caret"></span>
 | 
				
			||||||
 | 
					                    </button>
 | 
				
			||||||
 | 
					                    <div class="dropdown-menu">
 | 
				
			||||||
 | 
					                        <div class="dropdown-item text-left to-unwatch">
 | 
				
			||||||
 | 
					                            <h4 role="presentation" class="dropdown-header {{if not .IsRepositoryWatching}}text-primary{{end}}">Not Watching</h4>
 | 
				
			||||||
                            <p class="description">You only receive notifications for conversations in which you participate or are @mentioned.</p>
 | 
					                            <p class="description">You only receive notifications for conversations in which you participate or are @mentioned.</p>
 | 
				
			||||||
                            <p class="divider"></p>
 | 
					                            <p class="divider"></p>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                        <div class="dropdown-item text-left" data-val="watching">
 | 
					                        <div class="dropdown-item text-left to-watch">
 | 
				
			||||||
                            <h4 role="presentation" class="dropdown-header">Watching</h4>
 | 
					                            <h4 role="presentation" class="dropdown-header {{if .IsRepositoryWatching}}text-primary{{end}}">Watching</h4>
 | 
				
			||||||
                            <p class="description">You receive notifications for all conversations in this repository.</p>
 | 
					                            <p class="description">You receive notifications for all conversations in this repository.</p>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="btn-group">
 | 
					                <div class="btn-group">
 | 
				
			||||||
                    <button type="button" class="btn btn-default"><i class="fa fa-star"></i>Star  {{.Repository.NumStars}}</button>
 | 
					                    <button type="button" class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Star"><i class="fa fa-star"></i> {{.Repository.NumStars}}</button>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					                {{end}}
 | 
				
			||||||
                <div class="btn-group">
 | 
					                <div class="btn-group">
 | 
				
			||||||
                    <button type="button" class="btn btn-default"><i class="fa fa-code-fork"></i>Fork  {{.Repository.NumForks}}</button>
 | 
					                    <a type="button" {{if not .IsRepositoryOwner}}href="/{{.Username}}/{{.Reponame}}/fork"{{end}} class="btn btn-default" data-toggle="tooltip" data-placement="top" title="Fork"><i class="fa fa-code-fork fa-lg"></i> {{.Repository.NumForks}}</a>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            {{end}}
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@@ -10,20 +10,24 @@
 | 
				
			|||||||
            <li class="list-group-item"><a href="#">Notifications</a></li>-->
 | 
					            <li class="list-group-item"><a href="#">Notifications</a></li>-->
 | 
				
			||||||
        </ul>
 | 
					        </ul>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div id="gogs-repo-setting-container" class="col-md-9">
 | 
					    <div id="gogs-repo-setting-container" class="col-md-9">
 | 
				
			||||||
        {{if .ErrorMsg}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}}
 | 
					        {{if .ErrorMsg}}<p class="alert alert-danger">{{.ErrorMsg}}</p>{{end}}
 | 
				
			||||||
        <div class="panel panel-default">
 | 
					        <div class="panel panel-default">
 | 
				
			||||||
            <div class="panel-heading">
 | 
					            <div class="panel-heading">
 | 
				
			||||||
                Repository Options
 | 
					                Repository Options
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <div class="panel-body">
 | 
					            <div class="panel-body">
 | 
				
			||||||
                
 | 
					                
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="panel panel-warning">
 | 
					        <div class="panel panel-warning">
 | 
				
			||||||
            <div class="panel-heading">
 | 
					            <div class="panel-heading">
 | 
				
			||||||
                Danger Zone
 | 
					                Danger Zone
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            <div class="panel-body">
 | 
					            <div class="panel-body">
 | 
				
			||||||
                <button type="button" class="btn btn-default pull-right" href="#delete-repository-modal" data-toggle="modal">
 | 
					                <button type="button" class="btn btn-default pull-right" href="#delete-repository-modal" data-toggle="modal">
 | 
				
			||||||
                    Delete this repository
 | 
					                    Delete this repository
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
<div id="gogs-body" class="container">
 | 
					<div id="gogs-body" class="container">
 | 
				
			||||||
    <div id="gogs-source">
 | 
					    <div id="gogs-source">
 | 
				
			||||||
        {{if .IsBareRepo}}
 | 
					        {{if .IsBareRepo}}
 | 
				
			||||||
        Need to fill in some guide.
 | 
					        {{template "repo/single_bare" .}}
 | 
				
			||||||
        {{else}}
 | 
					        {{else}}
 | 
				
			||||||
        <div class="source-toolbar">
 | 
					        <div class="source-toolbar">
 | 
				
			||||||
            {{ $n := len .Treenames}}
 | 
					            {{ $n := len .Treenames}}
 | 
				
			||||||
@@ -15,7 +15,7 @@
 | 
				
			|||||||
                    <b class="caret"></b></a>
 | 
					                    <b class="caret"></b></a>
 | 
				
			||||||
                <ul class="dropdown-menu">
 | 
					                <ul class="dropdown-menu">
 | 
				
			||||||
                    {{range .Branches}}
 | 
					                    {{range .Branches}}
 | 
				
			||||||
                    <li><a {{if eq . $.Branchname}}class="current" {{end}}href="{{$.BranchLink}}">{{.}}</a></li>
 | 
					                    <li><a {{if eq . $.Branchname}}class="current" {{end}}href="/{{$.Username}}/{{$.Reponame}}/src/{{.}}">{{.}}</a></li>
 | 
				
			||||||
                    {{end}}
 | 
					                    {{end}}
 | 
				
			||||||
                </ul>
 | 
					                </ul>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										31
									
								
								templates/repo/single_bare.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								templates/repo/single_bare.tmpl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					<div class="panel panel-default guide-box clone-group-btn">
 | 
				
			||||||
 | 
					    <div class="panel-heading guide-head">
 | 
				
			||||||
 | 
					        <h4>Quick Guide</h4>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="panel-body guide-content text-center">
 | 
				
			||||||
 | 
					        <h3>Clone this repository</h3>
 | 
				
			||||||
 | 
					        <div class="input-group col-md-8 col-md-offset-2 guide-buttons">
 | 
				
			||||||
 | 
					            <span class="input-group-btn">
 | 
				
			||||||
 | 
					                <button class="btn btn-default" data-link="{{.CloneLink.SSH}}" type="button">SSH</button>
 | 
				
			||||||
 | 
					                <button class="btn btn-default" data-link="{{.CloneLink.HTTPS}}" type="button">HTTPS</button>
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					            <input type="text" class="form-control clone-group-url" id="guide-clone-url" value="" readonly/>
 | 
				
			||||||
 | 
					            <span class="input-group-btn">
 | 
				
			||||||
 | 
					                <button class="btn btn-default" type="button"><i class="fa fa-copy" data-toggle="tooltip" title="copy to clipboard" data-placement="top"></i></button>
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <p>We recommend every repository include a <strong>README</strong>, <strong>LICENSE</strong>, and <strong>.gitignore</strong>.</p>
 | 
				
			||||||
 | 
					        <hr/>
 | 
				
			||||||
 | 
					        <h3>Create a new repository on the command line</h3>
 | 
				
			||||||
 | 
					            <pre class="text-left"><code>touch README.md
 | 
				
			||||||
 | 
					git init
 | 
				
			||||||
 | 
					git add README.md
 | 
				
			||||||
 | 
					git commit -m "first commit"
 | 
				
			||||||
 | 
					git remote add origin <span class="clone-url"></span>
 | 
				
			||||||
 | 
					git push -u origin master</code></pre>
 | 
				
			||||||
 | 
					        <hr/>
 | 
				
			||||||
 | 
					        <h3>Push an existing repository from the command line</h3>
 | 
				
			||||||
 | 
					        <pre class="text-left"><code>git remote add origin <span class="clone-url"></span>
 | 
				
			||||||
 | 
					git push -u origin master</code></pre>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
@@ -1,6 +1,10 @@
 | 
				
			|||||||
<div class="panel panel-default file-content">
 | 
					<div class="panel panel-default file-content">
 | 
				
			||||||
    <div class="panel-heading file-head">
 | 
					    <div class="panel-heading file-head">
 | 
				
			||||||
        <i class="icon fa fa-book"></i> {{.FileName}}
 | 
					        {{if .ReadmeExist}}
 | 
				
			||||||
 | 
					            <i class="icon fa fa-book"></i>
 | 
				
			||||||
 | 
					        {{else}}
 | 
				
			||||||
 | 
					            <i class="icon fa fa-file-text-o"></i>
 | 
				
			||||||
 | 
					        {{end}}{{.FileName}}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    {{if .FileIsLarge}}
 | 
					    {{if .FileIsLarge}}
 | 
				
			||||||
        <div class="panel-footer">
 | 
					        <div class="panel-footer">
 | 
				
			||||||
@@ -12,8 +16,15 @@
 | 
				
			|||||||
                {{.FileContent|str2html}}
 | 
					                {{.FileContent|str2html}}
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        {{else}}
 | 
					        {{else}}
 | 
				
			||||||
            <div class="panel-body file-body markdown">
 | 
					            <div class="panel-body file-body file-code">
 | 
				
			||||||
                <pre><code>{{.FileContent}}</code></pre>
 | 
					                <table>
 | 
				
			||||||
 | 
					                    <tbody>
 | 
				
			||||||
 | 
					                        <tr>
 | 
				
			||||||
 | 
					                            <td class="lines-num"></td>
 | 
				
			||||||
 | 
					                            <td class="lines-code markdown"><pre class="linenums lang-{{.FileExt}}"><code>{{.FileContent}}</code></pre></td>
 | 
				
			||||||
 | 
					                        </tr>
 | 
				
			||||||
 | 
					                    </tbody>
 | 
				
			||||||
 | 
					                </table>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        {{end}}
 | 
					        {{end}}
 | 
				
			||||||
    {{end}}
 | 
					    {{end}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,9 +15,8 @@
 | 
				
			|||||||
                            <li><a href="/{{.RepositoryLink}}/release">Release</a></li>
 | 
					                            <li><a href="/{{.RepositoryLink}}/release">Release</a></li>
 | 
				
			||||||
                            <li><a href="//{{.RepositoryLink}}/wiki">Wiki</a></li>
 | 
					                            <li><a href="//{{.RepositoryLink}}/wiki">Wiki</a></li>
 | 
				
			||||||
                        </ul>
 | 
					                        </ul>
 | 
				
			||||||
                    </li>
 | 
					                    </li>{{end}}
 | 
				
			||||||
                </ul>
 | 
					                </ul>
 | 
				
			||||||
                {{end}}
 | 
					 | 
				
			||||||
                <ul class="nav navbar-nav navbar-right">
 | 
					                <ul class="nav navbar-nav navbar-right">
 | 
				
			||||||
                    {{if not .IsBareRepo}}
 | 
					                    {{if not .IsBareRepo}}
 | 
				
			||||||
                    <li class="dropdown">
 | 
					                    <li class="dropdown">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,8 @@
 | 
				
			|||||||
        {{if .IsActivatePage}}
 | 
					        {{if .IsActivatePage}}
 | 
				
			||||||
            {{if .ServiceNotEnabled}}
 | 
					            {{if .ServiceNotEnabled}}
 | 
				
			||||||
            <p>Sorry, Register Mail Confirmation has been disabled.</p>
 | 
					            <p>Sorry, Register Mail Confirmation has been disabled.</p>
 | 
				
			||||||
 | 
					            {{else if .ResendLimited}}
 | 
				
			||||||
 | 
					            <p>Sorry, you are sending activation e-mail too frequently, please wait 3 minutes.</p>
 | 
				
			||||||
            {{else}}
 | 
					            {{else}}
 | 
				
			||||||
            <p>New confirmation e-mail has been sent to <b>{{.SignedUser.Email}}</b>, please check your inbox within {{.Hours}} hours to complete your registeration.</p>
 | 
					            <p>New confirmation e-mail has been sent to <b>{{.SignedUser.Email}}</b>, please check your inbox within {{.Hours}} hours to complete your registeration.</p>
 | 
				
			||||||
            <hr/>
 | 
					            <hr/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,8 +33,9 @@
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="panel-body">
 | 
					            <div class="panel-body">
 | 
				
			||||||
                <ul class="list-group">{{range .MyRepos}}
 | 
					                <ul class="list-group">{{range .MyRepos}}
 | 
				
			||||||
                    <li class="list-group-item"><i class="fa fa-book"></i><a href="/{{$.SignedUserName}}/{{.Name}}">{{.Name}}</a>
 | 
					                    <li class="list-group-item"><a href="/{{$.SignedUserName}}/{{.Name}}">
 | 
				
			||||||
                        <span class="stars pull-right"><i class="fa fa-star"></i>{{.NumStars}}</span>
 | 
					                        <span class="stars pull-right"><i class="fa fa-star"></i>{{.NumStars}}</span>
 | 
				
			||||||
 | 
					                        <i class="fa fa-book"></i>{{.Name}}</a>
 | 
				
			||||||
                    </li>{{end}}
 | 
					                    </li>{{end}}
 | 
				
			||||||
                </ul>
 | 
					                </ul>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,8 @@
 | 
				
			|||||||
    <div id="gogs-user-setting-container" class="col-md-9">
 | 
					    <div id="gogs-user-setting-container" class="col-md-9">
 | 
				
			||||||
        <div id="gogs-setting-pwd">
 | 
					        <div id="gogs-setting-pwd">
 | 
				
			||||||
            <h4>Account Profile</h4>
 | 
					            <h4>Account Profile</h4>
 | 
				
			||||||
            <form class="form-horizontal" id="gogs-password-form" method="post" action="/user/setting">{{if .IsSuccess}}
 | 
					            <form class="form-horizontal" id="gogs-password-form" method="post" action="/user/setting">
 | 
				
			||||||
                <p class="alert alert-success">Your profile has been successfully updated.</p>{{else if .HasError}}<p class="alert alert-danger form-error">{{.ErrorMsg}}</p>{{end}}
 | 
					                {{if .IsSuccess}}<p class="alert alert-success">Your profile has been successfully updated.</p>{{else if .HasError}}<p class="alert alert-danger form-error">{{.ErrorMsg}}</p>{{end}}
 | 
				
			||||||
                <p>Your Email will be public and used for Account related notifications and any web based operations made via the web.</p>
 | 
					                <p>Your Email will be public and used for Account related notifications and any web based operations made via the web.</p>
 | 
				
			||||||
                <div class="form-group">
 | 
					                <div class="form-group">
 | 
				
			||||||
                    <label class="col-md-2 control-label">Email</label>
 | 
					                    <label class="col-md-2 control-label">Email</label>
 | 
				
			||||||
@@ -29,7 +29,7 @@
 | 
				
			|||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <div class="form-group">
 | 
					                <div class="form-group {{if .Err_Avatar}}has-error has-feedback{{end}}">
 | 
				
			||||||
                    <label class="col-md-2 control-label">Gravatar Email<strong class="text-danger">*</strong></label>
 | 
					                    <label class="col-md-2 control-label">Gravatar Email<strong class="text-danger">*</strong></label>
 | 
				
			||||||
                    <div class="col-md-8">
 | 
					                    <div class="col-md-8">
 | 
				
			||||||
                        <input type="text" name="avatar" class="form-control" placeholder="Type your Gravatar e-mail address" required="required" value="{{.Owner.AvatarEmail}}">
 | 
					                        <input type="text" name="avatar" class="form-control" placeholder="Type your Gravatar e-mail address" required="required" value="{{.Owner.AvatarEmail}}">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,7 +32,7 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="form-group text-center" id="gogs-social-login">
 | 
					        <div class="form-group text-center" id="gogs-social-login">
 | 
				
			||||||
            <a class="btn btn-default btn-lg">Social Login</a>
 | 
					            <a class="btn btn-danger btn-lg">Register new account</a>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,9 @@
 | 
				
			|||||||
{{template "base/navbar" .}}
 | 
					{{template "base/navbar" .}}
 | 
				
			||||||
<div class="container" id="gogs-body" data-page="user-signup">
 | 
					<div class="container" id="gogs-body" data-page="user-signup">
 | 
				
			||||||
	<form action="/user/sign_up" method="post" class="form-horizontal gogs-card" id="gogs-login-card">
 | 
						<form action="/user/sign_up" method="post" class="form-horizontal gogs-card" id="gogs-login-card">
 | 
				
			||||||
 | 
							{{if .DisenableRegisteration}}
 | 
				
			||||||
 | 
							Sorry, registeration has been disenabled, you can only get account from administrator.
 | 
				
			||||||
 | 
							{{else}}
 | 
				
			||||||
        <h3>Sign Up</h3>
 | 
					        <h3>Sign Up</h3>
 | 
				
			||||||
	    <div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div>
 | 
						    <div class="alert alert-danger form-error{{if .HasError}}{{else}} hidden{{end}}">{{.ErrorMsg}}</div>
 | 
				
			||||||
		<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}">
 | 
							<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}">
 | 
				
			||||||
@@ -43,6 +46,7 @@
 | 
				
			|||||||
                <a href="/user/login">Already have an account? Sign in now!</a>
 | 
					                <a href="/user/login">Already have an account? Sign in now!</a>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
	    </div>
 | 
						    </div>
 | 
				
			||||||
 | 
						    {{end}}
 | 
				
			||||||
	</form>
 | 
						</form>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
{{template "base/footer" .}}
 | 
					{{template "base/footer" .}}
 | 
				
			||||||
							
								
								
									
										25
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								web.go
									
									
									
									
									
								
							@@ -16,11 +16,14 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/gogits/binding"
 | 
						"github.com/gogits/binding"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"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/log"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/mailer"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
	"github.com/gogits/gogs/routers"
 | 
						"github.com/gogits/gogs/routers"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/routers/admin"
 | 
				
			||||||
	"github.com/gogits/gogs/routers/dev"
 | 
						"github.com/gogits/gogs/routers/dev"
 | 
				
			||||||
	"github.com/gogits/gogs/routers/repo"
 | 
						"github.com/gogits/gogs/routers/repo"
 | 
				
			||||||
	"github.com/gogits/gogs/routers/user"
 | 
						"github.com/gogits/gogs/routers/user"
 | 
				
			||||||
@@ -35,6 +38,16 @@ gogs web`,
 | 
				
			|||||||
	Flags:  []cli.Flag{},
 | 
						Flags:  []cli.Flag{},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// globalInit is for global configuration reload-able.
 | 
				
			||||||
 | 
					func globalInit() {
 | 
				
			||||||
 | 
						base.NewConfigContext()
 | 
				
			||||||
 | 
						mailer.NewMailerContext()
 | 
				
			||||||
 | 
						models.LoadModelsConfig()
 | 
				
			||||||
 | 
						models.LoadRepoConfig()
 | 
				
			||||||
 | 
						models.NewRepoContext()
 | 
				
			||||||
 | 
						models.NewEngine()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Check run mode(Default of martini is Dev).
 | 
					// Check run mode(Default of martini is Dev).
 | 
				
			||||||
func checkRunMode() {
 | 
					func checkRunMode() {
 | 
				
			||||||
	switch base.Cfg.MustValue("", "RUN_MODE") {
 | 
						switch base.Cfg.MustValue("", "RUN_MODE") {
 | 
				
			||||||
@@ -58,6 +71,7 @@ func newMartini() *martini.ClassicMartini {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func runWeb(*cli.Context) {
 | 
					func runWeb(*cli.Context) {
 | 
				
			||||||
 | 
						globalInit()
 | 
				
			||||||
	base.NewServices()
 | 
						base.NewServices()
 | 
				
			||||||
	checkRunMode()
 | 
						checkRunMode()
 | 
				
			||||||
	log.Info("%s %s", base.AppName, base.AppVer)
 | 
						log.Info("%s %s", base.AppName, base.AppVer)
 | 
				
			||||||
@@ -73,7 +87,8 @@ func runWeb(*cli.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	m.Use(middleware.InitContext())
 | 
						m.Use(middleware.InitContext())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reqSignIn, ignSignIn := middleware.SignInRequire(true), middleware.SignInRequire(false)
 | 
						reqSignIn := middleware.SignInRequire(true)
 | 
				
			||||||
 | 
						ignSignIn := middleware.SignInRequire(base.Service.RequireSignInView)
 | 
				
			||||||
	reqSignOut := middleware.SignOutRequire()
 | 
						reqSignOut := middleware.SignOutRequire()
 | 
				
			||||||
	// Routers.
 | 
						// Routers.
 | 
				
			||||||
	m.Get("/", ignSignIn, routers.Home)
 | 
						m.Get("/", ignSignIn, routers.Home)
 | 
				
			||||||
@@ -99,6 +114,14 @@ func runWeb(*cli.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	m.Get("/help", routers.Help)
 | 
						m.Get("/help", routers.Help)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						adminReq := middleware.AdminRequire()
 | 
				
			||||||
 | 
						m.Get("/admin", reqSignIn, adminReq, admin.Dashboard)
 | 
				
			||||||
 | 
						m.Get("/admin/users", reqSignIn, adminReq, admin.Users)
 | 
				
			||||||
 | 
						m.Any("/admin/users/new", reqSignIn, adminReq, binding.BindIgnErr(auth.RegisterForm{}), admin.NewUser)
 | 
				
			||||||
 | 
						m.Any("/admin/users/:userid", reqSignIn, adminReq, binding.BindIgnErr(auth.AdminEditUserForm{}), admin.EditUser)
 | 
				
			||||||
 | 
						m.Get("/admin/repos", reqSignIn, adminReq, admin.Repositories)
 | 
				
			||||||
 | 
						m.Get("/admin/config", reqSignIn, adminReq, admin.Config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Post("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.SettingPost)
 | 
						m.Post("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.SettingPost)
 | 
				
			||||||
	m.Get("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.Setting)
 | 
						m.Get("/:username/:reponame/settings", reqSignIn, middleware.RepoAssignment(true), repo.Setting)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user