/** * This file is part of git-as-svn. It is subject to the license terms * in the LICENSE file found in the top-level directory of this distribution * and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn, * including this file, may be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file. */ package svnserver.ext.gitlfs; import com.google.common.collect.ImmutableMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jose4j.jwt.NumericDate; import org.tmatesoft.svn.core.SVNException; import ru.bozaro.gitlfs.common.Constants; import ru.bozaro.gitlfs.common.data.Link; import ru.bozaro.gitlfs.server.ServerError; import svnserver.auth.User; import svnserver.auth.UserDB; import svnserver.context.SharedContext; import svnserver.ext.gitlfs.config.LfsConfig; import svnserver.ext.web.server.WebServer; import svnserver.ext.web.token.TokenHelper; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URI; import java.util.Date; import java.util.Map; /** * Helper for git-lfs-authenticate implementation. * * @author Artem V. Navrotskiy <bozaro@users.noreply.github.com> */ public class LfsAuthHelper { public static Link createToken( @NotNull SharedContext context, @NotNull URI baseLfsUrl, @Nullable String username, @Nullable String external, boolean anonymous, int tokenExpireSec, float tokenEnsureTime ) throws ServerError { try { final UserDB userDB = context.sure(UserDB.class); final User user; if (anonymous) { user = User.getAnonymous(); } else if (external == null && username == null) { throw new ServerError(HttpServletResponse.SC_BAD_REQUEST, "Parameter \"username\" or \"external\" is not defined"); } else { user = username != null ? userDB.lookupByUserName(username) : userDB.lookupByExternal(external); } if (user == null) { //throw new NotFoundException(); throw new ServerError(HttpServletResponse.SC_NOT_FOUND, "User not found"); } return createToken(context, baseLfsUrl, user, tokenExpireSec, tokenEnsureTime); } catch (SVNException | IOException e) { throw new ServerError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Can't get user information. See server log for more details", e); } } @NotNull public static NumericDate getExpire(int tokenExpireSec) { // Calculate expire time and token. NumericDate expireAt = NumericDate.now(); expireAt.addSeconds(tokenExpireSec <= 0 ? LfsConfig.DEFAULT_TOKEN_EXPIRE_SEC : tokenExpireSec); return expireAt; } @NotNull public static Map<String, String> createTokenHeader(@NotNull SharedContext context, @NotNull User user, @NotNull NumericDate expireAt) throws IOException { WebServer webServer = WebServer.get(context); final String accessToken = TokenHelper.createToken(webServer.createEncryption(), user, expireAt); return ImmutableMap.<String, String>builder() .put(Constants.HEADER_AUTHORIZATION, WebServer.AUTH_TOKEN + accessToken) .build(); } public static Link createToken( @NotNull SharedContext context, @NotNull URI baseLfsUrl, @NotNull User user, int tokenExpireSec, float tokenEnsureTime ) throws IOException { int expireSec = tokenExpireSec <= 0 ? LfsConfig.DEFAULT_TOKEN_EXPIRE_SEC : tokenExpireSec; int ensureSec = (int) Math.ceil(expireSec * tokenEnsureTime); NumericDate now = NumericDate.now(); NumericDate expireAt = NumericDate.fromSeconds(now.getValue() + expireSec); NumericDate ensureAt = NumericDate.fromSeconds(now.getValue() + ensureSec); return new Link( baseLfsUrl, createTokenHeader(context, user, expireAt), new Date(ensureAt.getValueInMillis()) ); } }