mirror of
				https://github.com/gitbucket/gitbucket.git
				synced 2025-10-31 10:36:05 +01:00 
			
		
		
		
	Implementing authentication.
This commit is contained in:
		| @@ -1,9 +1,9 @@ | |||||||
| package app | package app | ||||||
|  |  | ||||||
|  | import model.Account | ||||||
| import org.scalatra._ | import org.scalatra._ | ||||||
| import org.scalatra.json._ | import org.scalatra.json._ | ||||||
| import org.json4s._ | import org.json4s._ | ||||||
| import org.json4s.jackson._ |  | ||||||
| import jp.sf.amateras.scalatra.forms._ | import jp.sf.amateras.scalatra.forms._ | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -13,11 +13,35 @@ abstract class ControllerBase extends ScalatraFilter with ClientSideValidationFo | |||||||
|    |    | ||||||
|   implicit val jsonFormats = DefaultFormats |   implicit val jsonFormats = DefaultFormats | ||||||
|    |    | ||||||
|   implicit def context: Context = Context(servletContext.getContextPath, LoginUser) |   implicit def context: Context = Context(servletContext.getContextPath, LoginAccount) | ||||||
|    |    | ||||||
|   // TODO get from session |   private def LoginAccount: Option[Account] = { | ||||||
|   private val LoginUser = "admin" //System.getProperty("user.name") |     session.get("LOGIN_ACCOUNT") match { | ||||||
|  |       case Some(x: Account) => Some(x) | ||||||
|  |       case _ => None | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected def usersOnly(action: => Any) = { | ||||||
|  |     { | ||||||
|  |       context.loginAccount match { | ||||||
|  |         case Some(x) => action | ||||||
|  |         case None    => redirect("/signin") | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected def usersOnly[T](action: T => Any) = { | ||||||
|  |     (form: T) => { | ||||||
|  |       context.loginAccount match { | ||||||
|  |         case Some(x) => action(form) | ||||||
|  |         case None    => redirect("/signin") | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | //  protected def adminOnly() | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| case class Context(path: String, loginUser: String) | case class Context(path: String, loginAccount: Option[Account]) | ||||||
| @@ -8,12 +8,13 @@ import org.eclipse.jgit.lib._ | |||||||
| import org.apache.commons.io._ | import org.apache.commons.io._ | ||||||
| import jp.sf.amateras.scalatra.forms._ | import jp.sf.amateras.scalatra.forms._ | ||||||
|  |  | ||||||
| class CreateRepositoryController extends CreateRepositoryControllerBase with ProjectService with AccountService | class CreateRepositoryController extends CreateRepositoryControllerBase | ||||||
|  |   with ProjectService with AccountService with WikiService | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Creates new repository. |  * Creates new repository. | ||||||
|  */ |  */ | ||||||
| trait CreateRepositoryControllerBase extends ControllerBase { self: ProjectService => | trait CreateRepositoryControllerBase extends ControllerBase { self: ProjectService with WikiService => | ||||||
|  |  | ||||||
|   case class RepositoryCreationForm(name: String, description: String) // TODO Option |   case class RepositoryCreationForm(name: String, description: String) // TODO Option | ||||||
|  |  | ||||||
| @@ -25,19 +26,21 @@ trait CreateRepositoryControllerBase extends ControllerBase { self: ProjectServi | |||||||
|   /** |   /** | ||||||
|    * Show the new repository form. |    * Show the new repository form. | ||||||
|    */ |    */ | ||||||
|   get("/new") { |   get("/new")(usersOnly { | ||||||
|     html.newrepo() |     html.newrepo() | ||||||
|   } |   }) | ||||||
|    |    | ||||||
|   /** |   /** | ||||||
|    * Create new repository. |    * Create new repository. | ||||||
|    */ |    */ | ||||||
|   post("/new", form) { form => |   post("/new", form)(usersOnly { form => | ||||||
|  |     val loginUserName = context.loginAccount.get.userName | ||||||
|  |  | ||||||
|     // Insert to the database at first |     // Insert to the database at first | ||||||
|     createProject(form.name, context.loginUser, Some(form.description)) |     createProject(form.name, loginUserName, Some(form.description)) | ||||||
|  |  | ||||||
|     // Create the actual repository |     // Create the actual repository | ||||||
|     val gitdir = getRepositoryDir(context.loginUser, form.name) |     val gitdir = getRepositoryDir(loginUserName, form.name) | ||||||
|     val repository = new RepositoryBuilder().setGitDir(gitdir).setBare.build |     val repository = new RepositoryBuilder().setGitDir(gitdir).setBare.build | ||||||
|  |  | ||||||
|     repository.create |     repository.create | ||||||
| @@ -46,7 +49,7 @@ trait CreateRepositoryControllerBase extends ControllerBase { self: ProjectServi | |||||||
|     config.setBoolean("http", null, "receivepack", true) |     config.setBoolean("http", null, "receivepack", true) | ||||||
|     config.save |     config.save | ||||||
|  |  | ||||||
|     val tmpdir = getInitRepositoryDir(context.loginUser, form.name) |     val tmpdir = getInitRepositoryDir(loginUserName, form.name) | ||||||
|     try { |     try { | ||||||
|       // Clone the repository |       // Clone the repository | ||||||
|       Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call |       Git.cloneRepository.setURI(gitdir.toURI.toString).setDirectory(tmpdir).call | ||||||
| @@ -67,9 +70,12 @@ trait CreateRepositoryControllerBase extends ControllerBase { self: ProjectServi | |||||||
|       FileUtils.deleteDirectory(tmpdir) |       FileUtils.deleteDirectory(tmpdir) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Create Wiki repository | ||||||
|  |     createWikiRepository(context.loginAccount.get, form.name) | ||||||
|  |  | ||||||
|     // redirect to the repository |     // redirect to the repository | ||||||
|     redirect("/%s/%s".format(context.loginUser, form.name)) |     redirect("/%s/%s".format(loginUserName, form.name)) | ||||||
|   } |   }) | ||||||
|    |    | ||||||
|   /** |   /** | ||||||
|    * Constraint for the repository name. |    * Constraint for the repository name. | ||||||
| @@ -78,7 +84,7 @@ trait CreateRepositoryControllerBase extends ControllerBase { self: ProjectServi | |||||||
|     def validate(name: String, value: String): Option[String] = { |     def validate(name: String, value: String): Option[String] = { | ||||||
|       if(!value.matches("^[a-zA-Z0-9\\-_]+$")){ |       if(!value.matches("^[a-zA-Z0-9\\-_]+$")){ | ||||||
|         Some("Repository name contains invalid character.") |         Some("Repository name contains invalid character.") | ||||||
|       } else if(getRepositories(context.loginUser, servletContext).contains(value)){ |       } else if(getRepositories(context.loginAccount.get.userName, servletContext).contains(value)){ | ||||||
|         Some("Repository already exists.") |         Some("Repository already exists.") | ||||||
|       } else { |       } else { | ||||||
|         None |         None | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| package app | package app | ||||||
|  |  | ||||||
|  | import service._ | ||||||
| import jp.sf.amateras.scalatra.forms._ | import jp.sf.amateras.scalatra.forms._ | ||||||
|  |  | ||||||
| class SignInController extends ControllerBase { | class SignInController extends SignInControllerBase with AccountService | ||||||
|  |  | ||||||
|  | trait SignInControllerBase extends ControllerBase { self: AccountService => | ||||||
|    |    | ||||||
|   case class SignInForm(email: String, password: String) |   case class SignInForm(email: String, password: String) | ||||||
|    |    | ||||||
| @@ -16,7 +19,18 @@ class SignInController extends ControllerBase { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   post("/signin", form){ form => |   post("/signin", form){ form => | ||||||
|     // TODO check email and password |     val account = getAccountByUserName(form.email) | ||||||
|     redirect("/%s".format(context.loginUser)) |     if(account.isEmpty || account.get.password != form.password){ | ||||||
|  |       redirect("/signin") | ||||||
|  |     } else { | ||||||
|  |       session.setAttribute("LOGIN_ACCOUNT", account.get) | ||||||
|  |       redirect("/%s".format(account.get.userName)) | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   get("/signout"){ | ||||||
|  |     session.invalidate | ||||||
|  |     redirect("/signin") | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -94,7 +94,7 @@ trait WikiControllerBase extends ControllerBase { self: WikiService with Project | |||||||
|     val repository = params("repository") |     val repository = params("repository") | ||||||
|      |      | ||||||
|     saveWikiPage(owner, repository, form.currentPageName, form.pageName,  |     saveWikiPage(owner, repository, form.currentPageName, form.pageName,  | ||||||
|         form.content, context.loginUser, form.message.getOrElse("")) |         form.content, context.loginAccount.get, form.message.getOrElse("")) | ||||||
|      |      | ||||||
|     redirect("%s/%s/wiki/%s".format(owner, repository, form.pageName)) |     redirect("%s/%s/wiki/%s".format(owner, repository, form.pageName)) | ||||||
|   } |   } | ||||||
| @@ -111,7 +111,7 @@ trait WikiControllerBase extends ControllerBase { self: WikiService with Project | |||||||
|     val repository = params("repository") |     val repository = params("repository") | ||||||
|      |      | ||||||
|     saveWikiPage(owner, repository, form.currentPageName, form.pageName,  |     saveWikiPage(owner, repository, form.currentPageName, form.pageName,  | ||||||
|         form.content, context.loginUser, form.message.getOrElse("")) |         form.content, context.loginAccount.get, form.message.getOrElse("")) | ||||||
|      |      | ||||||
|     redirect("%s/%s/wiki/%s".format(owner, repository, form.pageName)) |     redirect("%s/%s/wiki/%s".format(owner, repository, form.pageName)) | ||||||
|   } |   } | ||||||
| @@ -121,7 +121,7 @@ trait WikiControllerBase extends ControllerBase { self: WikiService with Project | |||||||
|     val repository = params("repository") |     val repository = params("repository") | ||||||
|     val page       = params("page") |     val page       = params("page") | ||||||
|      |      | ||||||
|     deleteWikiPage(owner, repository, page, context.loginUser, "Delete %s".format(page)) |     deleteWikiPage(owner, repository, page, context.loginAccount.get.userName, "Delete %s".format(page)) | ||||||
|      |      | ||||||
|     redirect("%s/%s/wiki".format(owner, repository)) |     redirect("%s/%s/wiki".format(owner, repository)) | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -34,17 +34,16 @@ object WikiService { | |||||||
| } | } | ||||||
|  |  | ||||||
| trait WikiService { | trait WikiService { | ||||||
|    |  | ||||||
|   import WikiService._ |   import WikiService._ | ||||||
|    |    | ||||||
|   // TODO synchronized? |   // TODO synchronized? | ||||||
|   def createWikiRepository(owner: String, repository: String): Unit = { |   def createWikiRepository(owner: model.Account, repository: String): Unit = { | ||||||
|     val dir = Directory.getWikiRepositoryDir(owner, repository) |     val dir = Directory.getWikiRepositoryDir(owner.userName, repository) | ||||||
|     if(!dir.exists){ |     if(!dir.exists){ | ||||||
|       val repo = new RepositoryBuilder().setGitDir(dir).setBare.build |       val repo = new RepositoryBuilder().setGitDir(dir).setBare.build | ||||||
|       try { |       try { | ||||||
|         repo.create |         repo.create | ||||||
|         saveWikiPage(owner, repository, "Home", "Home", "Welcome to the %s wiki!!".format(repository), owner, "Initial Commit") |         saveWikiPage(owner.userName, repository, "Home", "Home", "Welcome to the %s wiki!!".format(repository), owner, "Initial Commit") | ||||||
|       } finally { |       } finally { | ||||||
|         repo.close |         repo.close | ||||||
|       } |       } | ||||||
| @@ -55,9 +54,6 @@ trait WikiService { | |||||||
|    * Returns the wiki page. |    * Returns the wiki page. | ||||||
|    */ |    */ | ||||||
|   def getWikiPage(owner: String, repository: String, pageName: String): Option[WikiPageInfo] = { |   def getWikiPage(owner: String, repository: String, pageName: String): Option[WikiPageInfo] = { | ||||||
|     // TODO create wiki repository in the repository setting changing. |  | ||||||
|     createWikiRepository(owner, repository) |  | ||||||
|      |  | ||||||
|     JGitUtil.withGit(Directory.getWikiRepositoryDir(owner, repository)){ git => |     JGitUtil.withGit(Directory.getWikiRepositoryDir(owner, repository)){ git => | ||||||
|       try { |       try { | ||||||
|         JGitUtil.getFileList(git, "master", ".").find(_.name == pageName + ".md").map { file => |         JGitUtil.getFileList(git, "master", ".").find(_.name == pageName + ".md").map { file => | ||||||
| @@ -82,10 +78,7 @@ trait WikiService { | |||||||
|    * Save the wiki page. |    * Save the wiki page. | ||||||
|    */ |    */ | ||||||
|   def saveWikiPage(owner: String, repository: String, currentPageName: String, newPageName: String, |   def saveWikiPage(owner: String, repository: String, currentPageName: String, newPageName: String, | ||||||
|       content: String, committer: String, message: String): Unit = { |       content: String, committer: model.Account, message: String): Unit = { | ||||||
|      |  | ||||||
|     // TODO create wiki repository in the repository setting changing. |  | ||||||
|     createWikiRepository(owner, repository) |  | ||||||
|  |  | ||||||
|     val workDir = Directory.getWikiWorkDir(owner, repository) |     val workDir = Directory.getWikiWorkDir(owner, repository) | ||||||
|      |      | ||||||
| @@ -118,8 +111,7 @@ trait WikiService { | |||||||
|      |      | ||||||
|       // commit and push |       // commit and push | ||||||
|       if(added || deleted){ |       if(added || deleted){ | ||||||
|         // TODO committer's mail address |         git.commit.setCommitter(committer.userName, committer.mailAddress).setMessage(message).call | ||||||
|         git.commit.setAuthor(committer, committer + "@devnull").setMessage(message).call |  | ||||||
|         git.push.call |         git.push.call | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -129,8 +121,6 @@ trait WikiService { | |||||||
|    * Delete the wiki page. |    * Delete the wiki page. | ||||||
|    */ |    */ | ||||||
|   def deleteWikiPage(owner: String, repository: String, pageName: String, committer: String, message: String): Unit = { |   def deleteWikiPage(owner: String, repository: String, pageName: String, committer: String, message: String): Unit = { | ||||||
|     // TODO create wiki repository in the repository setting changing. |  | ||||||
|     createWikiRepository(owner, repository) |  | ||||||
|      |      | ||||||
|     val workDir = Directory.getWikiWorkDir(owner, repository) |     val workDir = Directory.getWikiWorkDir(owner, repository) | ||||||
|      |      | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| @main("GitBucket"){ | @main("GitBucket"){ | ||||||
|   <h1>GitBucket</h1> |   <h1>GitBucket</h1> | ||||||
|   <ul> |   <ul> | ||||||
|     <li><a href="@path/@context.loginUser">User page</a></li> |     <li><a href="@path/@context.loginAccount.get.userName">User page</a></li> | ||||||
|     <li><a href="@path/new">Create new repository</a></li> |     <li><a href="@path/new">Create new repository</a></li> | ||||||
|   </ul> |   </ul> | ||||||
| } | } | ||||||
| @@ -31,10 +31,14 @@ | |||||||
|           <a class="brand" href="#">GitBucket</a> |           <a class="brand" href="#">GitBucket</a> | ||||||
|           <div class="nav-collapse collapse"> |           <div class="nav-collapse collapse"> | ||||||
|             <ul class="nav pull-right"> |             <ul class="nav pull-right"> | ||||||
|  |               @if(loginAccount.isDefined){ | ||||||
|                 <li><a href="@path/new">New repo</a></li> |                 <li><a href="@path/new">New repo</a></li> | ||||||
|               <li><a href="@path/@context.loginUser">Account</a></li> |                 <li><a href="@path/@loginAccount.get.userName">Account</a></li> | ||||||
|                 <li><a href="#users">Users</a></li> |                 <li><a href="#users">Users</a></li> | ||||||
|               <li><a href="#contact">Sign out</a></li> |                 <li><a href="@path/signout">Sign out</a></li> | ||||||
|  |               } else { | ||||||
|  |                 <li><a href="@path/signin">Sign in</a></li> | ||||||
|  |               } | ||||||
|             </ul> |             </ul> | ||||||
|           </div><!--/.nav-collapse --> |           </div><!--/.nav-collapse --> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ | |||||||
|         </ul> |         </ul> | ||||||
|         @repositories.map { repository => |         @repositories.map { repository => | ||||||
|         <div class="block"> |         <div class="block"> | ||||||
|           <div class="block-header-2"><a href="@path/@user/@repository.name">@repository.name</a></div> |           <div class="block-header-2"><a href="@path/@repository.owner/@repository.name">@repository.name</a></div> | ||||||
|           <div>@repository.project.description</div> |           <div>@repository.project.description</div> | ||||||
|           <div><span class="description small">Last updated: @repository.project.lastActivityDate</span></div> |           <div><span class="description small">Last updated: @repository.project.lastActivityDate</span></div> | ||||||
|         </div> |         </div> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user