<commit_before>package controllers;

import actions.AnonymousCheckAction;
import actions.NullProjectCheckAction;

import com.avaje.ebean.ExpressionList;
import com.avaje.ebean.Junction;
import com.avaje.ebean.Page;

import controllers.annotation.IsAllowed;
import info.schleichardt.play2.mailplugin.Mailer;
import models.*;
import models.Project.State;
import models.enumeration.Operation;
import models.enumeration.RequestState;
import models.enumeration.ResourceType;
import models.enumeration.RoleType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.HtmlEmail;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.jsoup.Jsoup;
import org.tmatesoft.svn.core.SVNException;

import play.Logger;
import play.data.Form;
import play.data.validation.ValidationError;
import play.db.ebean.Transactional;
import play.i18n.Messages;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Http.MultipartFormData;
import play.mvc.Http.MultipartFormData.FilePart;
import play.mvc.Result;
import play.mvc.With;
import playRepository.Commit;
import playRepository.PlayRepository;
import playRepository.RepositoryService;
import scala.reflect.io.FileOperationException;
import utils.*;
import validation.ExConstraints.RestrictedValidator;
import views.html.project.create;
import views.html.project.delete;
import views.html.project.overview;
import views.html.project.setting;
import views.html.project.transfer;

import javax.servlet.ServletException;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static play.data.Form.form;
import static play.libs.Json.toJson;


/**
 * ProjectApp
 *
 */
public class ProjectApp extends Controller {

    private static final int LOGO_FILE_LIMIT_SIZE = 1024*1000*5; //5M

    /** 프로젝트 로고로 사용할 수 있는 이미지 확장자 */
    public static final String[] LOGO_TYPE = {"jpg", "jpeg", "png", "gif", "bmp"};

    /** 자동완성에서 보여줄 최대 프로젝트 개수 */
    private static final int MAX_FETCH_PROJECTS = 1000;

    private static final int COMMIT_HISTORY_PAGE = 0;

    private static final int COMMIT_HISTORY_SHOW_LIMIT = 10;

    private static final int RECENLTY_ISSUE_SHOW_LIMIT = 10;

    private static final int RECENLTY_POSTING_SHOW_LIMIT = 10;

    private static final int RECENT_PULL_REQUEST_SHOW_LIMIT = 10;

    private static final int PROJECT_COUNT_PER_PAGE = 10;

    private static final String HTML = "text/html";

    private static final String JSON = "application/json";

    /**
     * getProject
     * @param userName
     * @param projectName
     * @return
     */
    public static Project getProject(String userName, String projectName) {
        return Project.findByOwnerAndProjectName(userName, projectName);
    }

    @With(AnonymousCheckAction.class)
    @IsAllowed(Operation.UPDATE)
    public static Result projectOverviewUpdate(String ownerId, String projectName){
        JsonNode json = request().body().asJson();
        Project targetProject = Project.findByOwnerAndProjectName(ownerId, projectName);
        ObjectNode result = Json.newObject();
        if (targetProject == null) {
            return notFound(ErrorViews.NotFound.render("error.notfound"));
        }
        targetProject.overview = json.findPath("overview").getTextValue();
        targetProject.save();
        result.put("overview", targetProject.overview);
        return ok(result);
    }

    /**
     * 프로젝트 Overview 페이지를 처리한다.<p />
     *
     * {@code loginId}와 {@code projectName}으로 프로젝트 정보를 가져온다.<br />
     * 읽기 권한이 없을 경우는 unauthorized로 응답한다.<br />
     * 해당 프로젝트의 최근 커밋, 이슈, 포스팅 목록을 가져와서 히스토리를 만든다.<br />
     *
     * @param loginId
     * @param projectName
     * @return 프로젝트, 히스토리 정보
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws ServletException the servlet exception
     * @throws SVNException the svn exception
     * @throws GitAPIException the git api exception
     */
    @IsAllowed(Operation.READ)
    public static Result project(String loginId, String projectName) throws IOException, ServletException, SVNException, GitAPIException {
        Project project = Project.findByOwnerAndProjectName(loginId, projectName);
        project.fixInvalidForkData();

        PlayRepository repository = RepositoryService.getRepository(project);

        List<Commit> commits = null;
        try {
            commits = repository.getHistory(COMMIT_HISTORY_PAGE, COMMIT_HISTORY_SHOW_LIMIT, null, null);
        } catch (NoHeadException e) {
        // NOOP
        }

        List<Issue> issues = Issue.findRecentlyCreated(project, RECENLTY_ISSUE_SHOW_LIMIT);
        List<Posting> postings = Posting.findRecentlyCreated(project, RECENLTY_POSTING_SHOW_LIMIT);
        List<PullRequest> pullRequests = PullRequest.findRecentlyReceived(project, RECENT_PULL_REQUEST_SHOW_LIMIT);

        List<History> histories = History.makeHistory(loginId, project, commits, issues, postings, pullRequests);
        UserApp.currentUser().visits(project);
        return ok(overview.render("title.projectHome", project, histories));
    }

    /**
     * 신규 프로젝트 생성 페이지로 이동한다.<p />
     *
     * 비로그인 상태({@link models.User#anonymous})이면 로그인 경고메세지와 함께 로그인페이지로 redirect 된다.<br />
     * 로그인 상태이면 프로젝트 생성 페이지로 이동한다.<br />
     *
     * @return 익명사용자이면 로그인페이지, 로그인 상태이면 프로젝트 생성페이지
     */
    public static Result newProjectForm() {
        if (UserApp.currentUser().isAnonymous()) {
            flash(Constants.WARNING, "user.login.alert");
            return redirect(routes.UserApp.loginForm());
        } else {
            List<OrganizationUser> orgUserList = OrganizationUser.findByAdmin(UserApp.currentUser().id);
            return ok(create.render("title.newProject", form(Project.class), orgUserList));
        }
    }

    /**
     * 프로젝트 설정(업데이트) 페이지로 이동한다.<p />
     *
     * {@code loginId}와 {@code projectName}으로 프로젝트 정보를 가져온다.<br />
     * 업데이트 권한이 없을 경우는 unauthorized로 응답한다.<br />
     *
     * @param loginId
     * @param projectName
     * @return 프로젝트 정보
     */
    @IsAllowed(Operation.UPDATE)
    public static Result settingForm(String loginId, String projectName) throws Exception {
        Project project = Project.findByOwnerAndProjectName(loginId, projectName);
        Form<Project> projectForm = form(Project.class).fill(project);
        PlayRepository repository = RepositoryService.getRepository(project);
        return ok(setting.render("title.projectSetting", projectForm, project, repository.getBranches()));
    }

    /**
     * 신규 프로젝트 생성(관리자Role 설정/코드 저장소를 생성)하고 Overview 페이지로 redirect 된다.<p />
     *
     * {@code loginId}와 {@code projectName}으로 프로젝트 정보를 조회하여 <br />
     * 프로젝트가 이미 존재할 경우 경고메세지와 함께 badRequest로 응답한다.<br />
     * 프로젝트폼 입력데이터에 오류가 있을 경우 경고메시지와 함께 badRequest로 응답한다.<br />
     *
     * @return 프로젝트 존재시 경고메세지, 입력폼 오류시 경고메세지, 프로젝트 생성시 프로젝트 정보
     * @throws Exception
     */
    @Transactional
    public static Result newProject() throws Exception {
        if(!AccessControl.isCreatable(UserApp.currentUser())){
           return forbidden(ErrorViews.Forbidden.render("'" + UserApp.currentUser().name + "' has no permission"));
        }
        Form<Project> filledNewProjectForm = form(Project.class).bindFromRequest();

        String owner = filledNewProjectForm.field("owner").value();
        Organization organization = Organization.findByName(owner);
        User user = User.findByLoginId(owner);

        ValidationResult validation = validateForm(filledNewProjectForm, organization, user);
        if (validation.hasError()) {
            return validation.getResult();
        }

        Project project = filledNewProjectForm.get();
        if (Organization.isNameExist(owner)) {
            project.organization = organization;
        } else {
            ProjectUser.assignRole(UserApp.currentUser().id, Project.create(project), RoleType.MANAGER);
        }
        Project.create(project);
        RepositoryService.createRepository(project);
        return redirect(routes.ProjectApp.project(project.owner, project.name));
    }

    private static ValidationResult validateForm(Form<Project> newProjectForm, Organization organization, User user) {
        Result result = null;
        boolean hasError = false;
        List<OrganizationUser> orgUserList = OrganizationUser.findByAdmin(UserApp.currentUser().id);

        String owner = newProjectForm.field("owner").value();
        String name = newProjectForm.field("name").value();
        boolean ownerIsUser = User.isLoginIdExist(owner);
        boolean ownerIsOrganization = Organization.isNameExist(owner);

        if (!ownerIsUser && !ownerIsOrganization) {
            newProjectForm.reject("owner", "project.owner.invalidate");
            hasError = true;
            result = badRequest(create.render("title.newProject", newProjectForm, orgUserList));
        }
<commit_msg>project: fix duplicated site-admin role assignment<commit_after>package controllers;

import actions.AnonymousCheckAction;
import actions.NullProjectCheckAction;

import com.avaje.ebean.ExpressionList;
import com.avaje.ebean.Junction;
import com.avaje.ebean.Page;

import controllers.annotation.IsAllowed;
import info.schleichardt.play2.mailplugin.Mailer;
import models.*;
import models.Project.State;
import models.enumeration.Operation;
import models.enumeration.RequestState;
import models.enumeration.ResourceType;
import models.enumeration.RoleType;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.HtmlEmail;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.node.ObjectNode;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.jsoup.Jsoup;
import org.tmatesoft.svn.core.SVNException;

import play.Logger;
import play.data.Form;
import play.data.validation.ValidationError;
import play.db.ebean.Transactional;
import play.i18n.Messages;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Http;
import play.mvc.Http.MultipartFormData;
import play.mvc.Http.MultipartFormData.FilePart;
import play.mvc.Result;
import play.mvc.With;
import playRepository.Commit;
import playRepository.PlayRepository;
import playRepository.RepositoryService;
import scala.reflect.io.FileOperationException;
import utils.*;
import validation.ExConstraints.RestrictedValidator;
import views.html.project.create;
import views.html.project.delete;
import views.html.project.overview;
import views.html.project.setting;
import views.html.project.transfer;

import javax.servlet.ServletException;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static play.data.Form.form;
import static play.libs.Json.toJson;


/**
 * ProjectApp
 *
 */
public class ProjectApp extends Controller {

    private static final int LOGO_FILE_LIMIT_SIZE = 1024*1000*5; //5M

    /** 프로젝트 로고로 사용할 수 있는 이미지 확장자 */
    public static final String[] LOGO_TYPE = {"jpg", "jpeg", "png", "gif", "bmp"};

    /** 자동완성에서 보여줄 최대 프로젝트 개수 */
    private static final int MAX_FETCH_PROJECTS = 1000;

    private static final int COMMIT_HISTORY_PAGE = 0;

    private static final int COMMIT_HISTORY_SHOW_LIMIT = 10;

    private static final int RECENLTY_ISSUE_SHOW_LIMIT = 10;

    private static final int RECENLTY_POSTING_SHOW_LIMIT = 10;

    private static final int RECENT_PULL_REQUEST_SHOW_LIMIT = 10;

    private static final int PROJECT_COUNT_PER_PAGE = 10;

    private static final String HTML = "text/html";

    private static final String JSON = "application/json";

    /**
     * getProject
     * @param userName
     * @param projectName
     * @return
     */
    public static Project getProject(String userName, String projectName) {
        return Project.findByOwnerAndProjectName(userName, projectName);
    }

    @With(AnonymousCheckAction.class)
    @IsAllowed(Operation.UPDATE)
    public static Result projectOverviewUpdate(String ownerId, String projectName){
        JsonNode json = request().body().asJson();
        Project targetProject = Project.findByOwnerAndProjectName(ownerId, projectName);
        ObjectNode result = Json.newObject();
        if (targetProject == null) {
            return notFound(ErrorViews.NotFound.render("error.notfound"));
        }
        targetProject.overview = json.findPath("overview").getTextValue();
        targetProject.save();
        result.put("overview", targetProject.overview);
        return ok(result);
    }

    /**
     * 프로젝트 Overview 페이지를 처리한다.<p />
     *
     * {@code loginId}와 {@code projectName}으로 프로젝트 정보를 가져온다.<br />
     * 읽기 권한이 없을 경우는 unauthorized로 응답한다.<br />
     * 해당 프로젝트의 최근 커밋, 이슈, 포스팅 목록을 가져와서 히스토리를 만든다.<br />
     *
     * @param loginId
     * @param projectName
     * @return 프로젝트, 히스토리 정보
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws ServletException the servlet exception
     * @throws SVNException the svn exception
     * @throws GitAPIException the git api exception
     */
    @IsAllowed(Operation.READ)
    public static Result project(String loginId, String projectName) throws IOException, ServletException, SVNException, GitAPIException {
        Project project = Project.findByOwnerAndProjectName(loginId, projectName);
        project.fixInvalidForkData();

        PlayRepository repository = RepositoryService.getRepository(project);

        List<Commit> commits = null;
        try {
            commits = repository.getHistory(COMMIT_HISTORY_PAGE, COMMIT_HISTORY_SHOW_LIMIT, null, null);
        } catch (NoHeadException e) {
        // NOOP
        }

        List<Issue> issues = Issue.findRecentlyCreated(project, RECENLTY_ISSUE_SHOW_LIMIT);
        List<Posting> postings = Posting.findRecentlyCreated(project, RECENLTY_POSTING_SHOW_LIMIT);
        List<PullRequest> pullRequests = PullRequest.findRecentlyReceived(project, RECENT_PULL_REQUEST_SHOW_LIMIT);

        List<History> histories = History.makeHistory(loginId, project, commits, issues, postings, pullRequests);
        UserApp.currentUser().visits(project);
        return ok(overview.render("title.projectHome", project, histories));
    }

    /**
     * 신규 프로젝트 생성 페이지로 이동한다.<p />
     *
     * 비로그인 상태({@link models.User#anonymous})이면 로그인 경고메세지와 함께 로그인페이지로 redirect 된다.<br />
     * 로그인 상태이면 프로젝트 생성 페이지로 이동한다.<br />
     *
     * @return 익명사용자이면 로그인페이지, 로그인 상태이면 프로젝트 생성페이지
     */
    public static Result newProjectForm() {
        if (UserApp.currentUser().isAnonymous()) {
            flash(Constants.WARNING, "user.login.alert");
            return redirect(routes.UserApp.loginForm());
        } else {
            List<OrganizationUser> orgUserList = OrganizationUser.findByAdmin(UserApp.currentUser().id);
            return ok(create.render("title.newProject", form(Project.class), orgUserList));
        }
    }

    /**
     * 프로젝트 설정(업데이트) 페이지로 이동한다.<p />
     *
     * {@code loginId}와 {@code projectName}으로 프로젝트 정보를 가져온다.<br />
     * 업데이트 권한이 없을 경우는 unauthorized로 응답한다.<br />
     *
     * @param loginId
     * @param projectName
     * @return 프로젝트 정보
     */
    @IsAllowed(Operation.UPDATE)
    public static Result settingForm(String loginId, String projectName) throws Exception {
        Project project = Project.findByOwnerAndProjectName(loginId, projectName);
        Form<Project> projectForm = form(Project.class).fill(project);
        PlayRepository repository = RepositoryService.getRepository(project);
        return ok(setting.render("title.projectSetting", projectForm, project, repository.getBranches()));
    }

    /**
     * 신규 프로젝트 생성(관리자Role 설정/코드 저장소를 생성)하고 Overview 페이지로 redirect 된다.<p />
     *
     * {@code loginId}와 {@code projectName}으로 프로젝트 정보를 조회하여 <br />
     * 프로젝트가 이미 존재할 경우 경고메세지와 함께 badRequest로 응답한다.<br />
     * 프로젝트폼 입력데이터에 오류가 있을 경우 경고메시지와 함께 badRequest로 응답한다.<br />
     *
     * @return 프로젝트 존재시 경고메세지, 입력폼 오류시 경고메세지, 프로젝트 생성시 프로젝트 정보
     * @throws Exception
     */
    @Transactional
    public static Result newProject() throws Exception {
        if(!AccessControl.isCreatable(UserApp.currentUser())){
           return forbidden(ErrorViews.Forbidden.render("'" + UserApp.currentUser().name + "' has no permission"));
        }
        Form<Project> filledNewProjectForm = form(Project.class).bindFromRequest();

        String owner = filledNewProjectForm.field("owner").value();
        Organization organization = Organization.findByName(owner);
        User user = User.findByLoginId(owner);

        ValidationResult validation = validateForm(filledNewProjectForm, organization, user);
        if (validation.hasError()) {
            return validation.getResult();
        }

        Project project = filledNewProjectForm.get();
        if (Organization.isNameExist(owner)) {
            project.organization = organization;
            Project.create(project);
        } else {
            ProjectUser.assignRole(UserApp.currentUser().id, Project.create(project), RoleType.MANAGER);
        }
        RepositoryService.createRepository(project);
        return redirect(routes.ProjectApp.project(project.owner, project.name));
    }

    private static ValidationResult validateForm(Form<Project> newProjectForm, Organization organization, User user) {
        Result result = null;
        boolean hasError = false;
        List<OrganizationUser> orgUserList = OrganizationUser.findByAdmin(UserApp.currentUser().id);

        String owner = newProjectForm.field("owner").value();
        String name = newProjectForm.field("name").value();
        boolean ownerIsUser = User.isLoginIdExist(owner);
        boolean ownerIsOrganization = Organization.isNameExist(owner);

        if (!ownerIsUser && !ownerIsOrganization) {
            newProjectForm.reject("owner", "project.owner.invalidate");
            hasError = true;
            result = badRequest(create.render("title.newProject", newProjectForm, orgUserList));
        }

{'fraction_non_alphanumeric': 0.10260328548818425, 'fraction_numerical': 0.0031654205097418546, 'mean_word_length': 3.490075961774075, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5425908', 'n_tokens_mistral': 5998, 'n_tokens_neox': 6390, 'n_words': 1199}