works™️

This commit is contained in:
KennyTV 2020-09-28 13:08:56 +02:00 committed by Nassim
parent a55ca6ca1c
commit 018e23a2be
17 changed files with 44 additions and 58 deletions

View File

@ -2,7 +2,7 @@ import $ from 'jquery';
//=====> EXTERNAL CONSTANTS
var namespace = window.namespace;
var namespace = window.NAMESPACE;
var keyGenText = window.keyGenText;
var keyRevokeText = window.keyRevokeText;

View File

@ -2,7 +2,6 @@ import $ from 'jquery';
//=====> EXTERNAL CONSTANTS
var PLUGIN_ID = window.PLUGIN_ID;
var NAMESPACE = window.NAMESPACE;
//=====> HELPER FUNCTIONS
@ -14,7 +13,7 @@ function bindExpand(e) {
var $this = $(this);
$.ajax({
method: 'get',
url: '/api/v1/projects/' + namespace + '/pages?parentId=' + pageId,
url: '/api/v1/projects/' + NAMESPACE + '/pages?parentId=' + pageId,
dataType: 'json',
success: function(childPages) {
console.log(childPages);

View File

@ -225,7 +225,7 @@ public class VersionsController extends HangarController {
return _showCreator(author, slug, pendingVersion);
}
private final Pattern URL_PATTERN = Pattern.compile("(https?://(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?://(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})");
private static final Pattern URL_PATTERN = Pattern.compile("(https?://(?:www\\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|www\\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\\.[^\\s]{2,}|https?://(?:www\\.|(?!www))[a-zA-Z0-9]+\\.[^\\s]{2,}|www\\.[a-zA-Z0-9]+\\.[^\\s]{2,})");
@ProjectPermission(NamedPermission.CREATE_VERSION)
@UserLock(route = Routes.PROJECTS_SHOW, args = "{#author, #slug}")
@ -370,9 +370,8 @@ public class VersionsController extends HangarController {
if (channelOptional.isEmpty()) {
if (projectChannels.size() >= hangarConfig.projects.getMaxChannels()) {
alertMsg = "error.channel.maxChannels";
alertArgs = new String[] {String.valueOf(hangarConfig.projects.getMaxChannels())};
}
else if (projectChannels.stream().anyMatch(ch -> ch.getColor() == channelColor)) {
alertArgs = new String[]{String.valueOf(hangarConfig.projects.getMaxChannels())};
} else if (projectChannels.stream().anyMatch(ch -> ch.getColor() == channelColor)) {
alertMsg = "error.channel.duplicateColor";
}
if (alertMsg != null) {
@ -518,9 +517,9 @@ public class VersionsController extends HangarController {
String curlInstruction;
CsrfToken csrfToken = (CsrfToken) request.getAttribute("_csrf");
if (csrfToken == null) {
curlInstruction = messageSource.getMessage("version.download.confirm.curl.nocsrf", new String[] {Routes.VERSIONS_CONFIRM_DOWNLOAD.getRouteUrl(author, slug, version, downloadType.ordinal() + "", token, null)}, LocaleContextHolder.getLocale());
curlInstruction = messageSource.getMessage("version.download.confirm.curl.nocsrf", new String[]{Routes.VERSIONS_CONFIRM_DOWNLOAD.getRouteUrl(author, slug, version, downloadType.ordinal() + "", token, null)}, LocaleContextHolder.getLocale());
} else {
curlInstruction = messageSource.getMessage("version.download.confirm.curl", new String[] {Routes.VERSIONS_CONFIRM_DOWNLOAD.getRouteUrl(author, slug, version, downloadType.ordinal() + "", token, null), csrfToken.getToken()}, LocaleContextHolder.getLocale());
curlInstruction = messageSource.getMessage("version.download.confirm.curl", new String[]{Routes.VERSIONS_CONFIRM_DOWNLOAD.getRouteUrl(author, slug, version, downloadType.ordinal() + "", token, null), csrfToken.getToken()}, LocaleContextHolder.getLocale());
}
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"README.txt\"");

View File

@ -1,6 +1,5 @@
package io.papermc.hangar.controller.api;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.papermc.hangar.model.ApiAuthInfo;
import io.papermc.hangar.model.NamedPermission;
import io.papermc.hangar.model.Permission;
@ -15,7 +14,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.function.BiPredicate;
@ -24,17 +22,12 @@ import java.util.function.BiPredicate;
public class PermissionsApiController implements PermissionsApi {
private final PermissionService permissionService;
private final ObjectMapper objectMapper;
private final ApiAuthInfo apiAuthInfo;
private final HttpServletRequest request;
@Autowired
public PermissionsApiController(PermissionService permissionService, ObjectMapper objectMapper, ApiAuthInfo apiAuthInfo, HttpServletRequest request) {
public PermissionsApiController(PermissionService permissionService, ApiAuthInfo apiAuthInfo) {
this.permissionService = permissionService;
this.objectMapper = objectMapper;
this.apiAuthInfo = apiAuthInfo;
this.request = request;
}
@Override
@ -60,7 +53,7 @@ public class PermissionsApiController implements PermissionsApi {
Permission perms = permissionService.getProjectPermissions(apiAuthInfo.getUser(), author, slug);
return new ImmutablePair<>(PermissionType.PROJECT, perms);
} else {
Permission perms = permissionService.getOrganizationPermissions(apiAuthInfo.getUser(), slug);
Permission perms = permissionService.getOrganizationPermissions(apiAuthInfo.getUser(), author);
return new ImmutablePair<>(PermissionType.ORGANIZATION, perms);
}
}

View File

@ -8,13 +8,13 @@ public class ApiScope {
private final String owner;
private final String slug;
private ApiScope(ApiScopeType apiScopeType, String owner, @Nullable String slug) {
private ApiScope(ApiScopeType apiScopeType, @Nullable String owner, @Nullable String slug) {
this.type = apiScopeType;
this.owner = owner;
this.slug = slug;
}
private ApiScope(ApiScopeType apiScopeType, String owner) {
private ApiScope(ApiScopeType apiScopeType, @Nullable String owner) {
this(apiScopeType, owner, null);
}

View File

@ -23,12 +23,11 @@ import java.util.Map;
@Repository
public interface V1ApiDao {
//TODO plugin_id
@UseStringTemplateEngine
@SqlQuery("SELECT p.id " +
" FROM home_projects p" +
" WHERE true" +
" <if(q)>AND p.name ILIKE '<q>' OR p.description ILIKE '<q>' OR p.owner_name ILIKE '<q>' OR p.plugin_id ILIKE '<q>' <endif>" +
" <if(q)>AND p.name ILIKE '<q>' OR p.description ILIKE '<q>' OR p.owner_name ILIKE '<q>' <endif>" +
" <if(categories)>AND p.category IN (<categories>) <endif>" +
" ORDER BY :strategyFragment" +
" LIMIT :limit OFFSET :offset")
@ -38,9 +37,9 @@ public interface V1ApiDao {
@RegisterBeanMapper(ProjectsTable.class)
@SqlQuery("SELECT pr.* " +
" FROM home_projects p" +
" JOIN projects pr ON p.plugin_id = pr.plugin_id" +
" JOIN projects pr ON p.project_id = pr.project_id" +
" WHERE true" +
" <if(q)>AND p.name ILIKE '<q>' OR p.description ILIKE '<q>' OR p.owner_name ILIKE '<q>' OR p.plugin_id ILIKE '<q>' <endif>" +
" <if(q)>AND p.name ILIKE '<q>' OR p.description ILIKE '<q>' OR p.owner_name ILIKE '<q>' <endif>" +
" <if(categories)>AND p.category IN (<categories>) <endif>" +
" ORDER BY :strategyFragment" +
" LIMIT :limit OFFSET :offset")

View File

@ -62,7 +62,7 @@ public class ProjectData extends JoinableData<UserProjectRolesTable, ProjectsTab
}
public String getFullSlug() {
return "/" + getProject().getOwnerName() + "/" + getProject().getSlug();
return getProject().getOwnerName() + "/" + getProject().getSlug();
}
public UsersTable getProjectOwner() {

View File

@ -63,7 +63,6 @@ public class AuthenticationService extends HangarService {
private final HangarDao<ApiKeyDao> apiKeyDao;
private final AuthenticationManager authenticationManager;
private final RoleService roleService;
private final SessionService sessionService;
private final PermissionService permissionService;
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper;
@ -74,7 +73,7 @@ public class AuthenticationService extends HangarService {
private static final Pattern API_KEY_PATTERN = Pattern.compile("(" + UUID_REGEX + ").(" + UUID_REGEX + ")");
@Autowired
public AuthenticationService(HttpServletRequest request, ApiAuthInfo apiAuthInfo, HangarConfig hangarConfig, HangarDao<UserDao> userDao, HangarDao<SessionsDao> sessionsDao, HangarDao<ApiKeyDao> apiKeyDao, AuthenticationManager authenticationManager, RoleService roleService, SessionService sessionService, PermissionService permissionService, RestTemplate restTemplate, ObjectMapper objectMapper, Supplier<Optional<UsersTable>> currentUser) {
public AuthenticationService(HttpServletRequest request, ApiAuthInfo apiAuthInfo, HangarConfig hangarConfig, HangarDao<UserDao> userDao, HangarDao<SessionsDao> sessionsDao, HangarDao<ApiKeyDao> apiKeyDao, AuthenticationManager authenticationManager, RoleService roleService, PermissionService permissionService, RestTemplate restTemplate, ObjectMapper objectMapper, Supplier<Optional<UsersTable>> currentUser) {
this.request = request;
this.apiAuthInfo = apiAuthInfo;
this.hangarConfig = hangarConfig;
@ -83,7 +82,6 @@ public class AuthenticationService extends HangarService {
this.apiKeyDao = apiKeyDao;
this.authenticationManager = authenticationManager;
this.roleService = roleService;
this.sessionService = sessionService;
this.permissionService = permissionService;
this.restTemplate = restTemplate;
this.objectMapper = objectMapper;

View File

@ -87,15 +87,14 @@ public class PluginUploadService {
throw new HangarException("error.version.illegalVersion");
}
ProjectChannelsTable channel = channelService.getFirstChannel(project);
PendingVersion pendingVersion = startVersion(plugin, project.getId(), project.getForumSync(), channel.getName());
boolean exists = versionService.exists(pendingVersion);
if (exists && hangarConfig.projects.isFileValidate()) {
throw new HangarException("error.version.duplicate");
}
cacheManager.getCache(CacheConfig.PENDING_VERSION_CACHE).put(project.getId() + "/" + pendingVersion.getVersionString(), pendingVersion);
return pendingVersion;
}

View File

@ -138,7 +138,6 @@ public class ProjectFactory {
public ProjectVersionsTable createVersion(HttpServletRequest request, ProjectData project, PendingVersion pendingVersion) {
ProjectChannelsTable channel = projectChannelDao.get().getProjectChannel(project.getProject().getId(), pendingVersion.getChannelName(), null);
if (versionService.exists(pendingVersion) && hangarConfig.projects.isFileValidate()) {
throw new HangarException("error.version.duplicate");
}
@ -163,6 +162,7 @@ public class ProjectFactory {
pendingVersion.isCreateForumPost(),
pendingVersion.getExternalUrl()
));
if (pendingVersion.getPlugin() != null) {
pendingVersion.getPlugin().getData().createTags(version.getId(), versionService); // TODO not sure what this is for
}
@ -178,6 +178,7 @@ public class ProjectFactory {
new String[]{"notification.project.newVersion", project.getProject().getName(), version.getVersionString()},
project.getNamespace() + "/versions/" + version.getVersionString()
));
if (pendingVersion.getPlugin() != null) {
try {
uploadPlugin(project, pendingVersion.getPlugin(), version);
@ -187,13 +188,11 @@ public class ProjectFactory {
}
}
// first project upload
if (project.getVisibility() == Visibility.NEW) {
projectService.changeVisibility(project.getProject(), Visibility.PUBLIC, "First upload");
userActionLogService.project(request, LoggedActionType.PROJECT_VISIBILITY_CHANGE.with(ProjectContext.of(project.getProject().getId())), Visibility.PUBLIC.getName(), Visibility.NEW.getName());
// TODO Add forum job
}
projectService.refreshHomePage();
@ -206,13 +205,12 @@ public class ProjectFactory {
Path oldPath = plugin.getPath();
Path versionDir = projectFiles.getVersionDir(project.getProjectOwner().getName(), project.getProject().getName(), version.getVersionString());
Path newPath = versionDir.resolve(oldPath.getFileName());
if (Files.notExists(newPath)) {
Files.createDirectories(newPath.getParent());
}
Files.move(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING); // TODO maybe remove the replace_existing in prod?
Files.deleteIfExists(oldPath);
if (Files.notExists(newPath)) {
throw new HangarException("error.plugin.fileName");
}

View File

@ -38,6 +38,11 @@ public class AlertUtil {
return mav;
}
public static ModelAndView showAlert(ModelAndView mav, AlertType alertType, String alertMessage, String... args) {
applyAlert(mav.getModelMap(), alertType, alertMessage, (Object[]) args);
return mav;
}
public static RedirectAttributes showAlert(RedirectAttributes attributes, AlertType alertType, String alertMsg, String...args) {
attributes.addFlashAttribute(TYPE, alertType);
attributes.addFlashAttribute(MSG, alertMsg);

View File

@ -135,8 +135,8 @@ public enum Routes {
APIV1_SHOW_STATUS_Z("apiv1.showStatusZ", Paths.APIV1_SHOW_STATUS_Z, of(), of()),
APIV1_SHOW_USER("apiv1.showUser", Paths.APIV1_SHOW_USER, of("user"), of()),
APIV1_LIST_PAGES("apiv1.listPages", Paths.APIV1_LIST_PAGES, of("author", "slug"), of("parentId")),
APIV1_DEPLOY_VERSION("apiv1.deployVersion", Paths.APIV1_DEPLOY_VERSION, of("author", "slugt", "name"), of()),
APIV1_LIST_TAGS("apiv1.listTags", Paths.APIV1_LIST_TAGS, of("plugin", "versionName"), of()),
APIV1_DEPLOY_VERSION("apiv1.deployVersion", Paths.APIV1_DEPLOY_VERSION, of("author", "slug", "name"), of()),
APIV1_LIST_TAGS("apiv1.listTags", Paths.APIV1_LIST_TAGS, of("author", "slug", "versionName"), of()),
APIV1_LIST_PLATFORMS("apiv1.listPlatforms", Paths.APIV1_LIST_PLATFORMS, of(), of());
private static final Map<String, Routes> ROUTES = new HashMap<>();

View File

@ -250,7 +250,7 @@ version.create.selectFile = Select file
version.create.externalUrl = External download URL
version.create.publish = Publish
version.create.tos = By clicking "Publish" you are agreeing to Hangar's <a href="https://docs.spongepowered.org/stable/en/about/tos.html">Terms of Service</a>.
version.create.info = Release a new version for <strong>{0}</strong> (slug: {1}).
version.create.info = Release a new version for <strong>{0}</strong>.
version.create.unstable = Mark this version as unstable
version.recommended = Recommended version
version.approved = Approved

View File

@ -18,7 +18,6 @@
window.PROJECT_NAME = "${p.project.name}";
window.PROJECT_OWNER = "${p.project.ownerName}";
window.PROJECT_SLUG = "${p.project.slug}";
window.pluginId = "${p.project.pluginId}";
window.keyGenText = "<@spring.message "project.settings.genKey" />";
window.keyRevokeText = "<@spring.message "project.settings.revokeKey" />";
</script>

View File

@ -37,7 +37,7 @@
<div class="create-body card-body">
<div class="minor create-blurb">
<span><@spring.messageArgs code="version.create.info" args=[projectName, projectSlug] /></span>
<span><@spring.messageArgs code="version.create.info" args=[projectName] /></span>
</div>
<#if pending??>
@ -203,18 +203,7 @@
<@alertFile.alertFile />
</@form.form>
<#if !pending??>
<@form.form action=Routes.VERSIONS_CREATE_EXTERNAL_URL.getRouteUrl(ownerName, projectSlug) method="POST" id="form-url-upload" class="form-inline">
<@csrf.formField />
<div class="input-group float-right" style="width: 50%">
<input type="text" class="form-control" id="externalUrl" name="externalUrl" placeholder="<@spring.message "version.create.externalUrl" />" style="width: 70%">
<div class="input-group-append">
<button class="btn btn-info" type="submit">Create Version</button>
</div>
</div>
</@form.form>
<#else>
<#if pending??>
<#assign version = pending>
<#assign formAction>
<#if version.versionString??>${Routes.VERSIONS_PUBLISH.getRouteUrl(ownerName, projectSlug, version.versionString)}<#else>${Routes.VERSIONS_PUBLISH_URL.getRouteUrl(ownerName, projectSlug)}</#if>
@ -224,8 +213,17 @@
<input type="hidden" class="channel-color-input" name="channel-color-input" value="${config.channels.colorDefault.hex}">
<div><input type="submit" name="create" value="<@spring.message "version.create.publish" />" class="btn btn-primary"></div>
</@form.form>
<#else>
<@form.form action=Routes.VERSIONS_CREATE_EXTERNAL_URL.getRouteUrl(ownerName, projectSlug) method="POST" id="form-url-upload" class="form-inline">
<@csrf.formField />
<div class="input-group float-right" style="width: 50%">
<input type="text" class="form-control" id="externalUrl" name="externalUrl" placeholder="<@spring.message "version.create.externalUrl" />" style="width: 70%">
<div class="input-group-append">
<button class="btn btn-info" type="submit">Create Version</button>
</div>
</div>
</@form.form>
</#if>
</div>
</div>
<span class="float-left tos"><i><@spring.messageArgs code="version.create.tos" args=["#"] /></i></span>

View File

@ -43,7 +43,7 @@ Base template for Project overview.
<div class="alert alert-danger" role="alert" style="margin: 0.2em 0 0 0">
<#if p.visibility == Visibility.NEEDSCHANGES>
<#if sp.perms(Permission.EditPage)>
<a class="btn btn-success float-right" href="${p.fullSlug}/manage/sendforapproval">Send for approval</a>
<a class="btn btn-success float-right" href="/${p.fullSlug}/manage/sendforapproval">Send for approval</a>
</#if>
<strong><@spring.message "visibility.notice." + p.visibility.getName() /></strong>
<br>

View File

@ -19,9 +19,8 @@ class RouteHelperTest {
assertEquals("/staff?sort=ASC&page=1", Routes.getRouteUrlOf("users.showStaff", "ASC", "1"));
assertEquals("/staff?page=1", Routes.getRouteUrlOf("users.showStaff", "", "1"));
assertEquals("/staff?sort=ASC", Routes.getRouteUrlOf("users.showStaff", "ASC", ""));
assertEquals("/api/v1/projects/Essentials/tags/1.33.7", Routes.getRouteUrlOf("apiv1.listTags", "Essentials", "1.33.7"));
assertEquals("/api/v1/projects/Essentials/pages?parentId=2", Routes.getRouteUrlOf("apiv1.listPages", "Essentials", "2"));
assertEquals("/api/v1/projects/Essentials/pages", Routes.getRouteUrlOf("apiv1.listPages", "Essentials", ""));
assertEquals("/api/v1/projects/Essentials/EssentialsX/tags/1.33.7", Routes.getRouteUrlOf("apiv1.listTags", "Essentials", "EssentialsX", "1.33.7"));
assertEquals("/api/v1/projects/Essentials/EssentialsX/pages?parentId=2", Routes.getRouteUrlOf("apiv1.listPages", "Essentials", "EssentialsX", "2"));
assertEquals("/api/v1/projects/Essentials/EssentialsX/pages", Routes.getRouteUrlOf("apiv1.listPages", "Essentials", "EssentialsX", ""));
}
}