mirror of
https://github.com/linuxserver/fleet.git
synced 2026-02-20 05:11:08 +08:00
Log In
- Added log in functionality - Updated gradle wrapper to latest
This commit is contained in:
parent
bd1946f84e
commit
248be84b5d
49
build.gradle
49
build.gradle
@ -1,11 +1,9 @@
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'com.eriwen.gradle.js' version '2.14.1'
|
||||
id 'com.eriwen.gradle.css' version '2.14.0'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
sourceCompatibility = 11
|
||||
targetCompatibility = 11
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
@ -70,48 +68,7 @@ jar {
|
||||
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
|
||||
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
|
||||
}
|
||||
|
||||
combineJs {
|
||||
|
||||
encoding = "UTF-8"
|
||||
|
||||
source = [
|
||||
'src/main/resources/assets/js/jquery-3.3.1.min.js',
|
||||
'src/main/resources/assets/js/bootstrap.bundle.min.js',
|
||||
'src/main/resources/assets/js/fontawesome-all.min.js',
|
||||
'src/main/resources/assets/js/jquery.tablesorter.js',
|
||||
'src/main/resources/assets/js/fleet.js'
|
||||
]
|
||||
|
||||
dest = file('src/main/resources/assets/js/all.js')
|
||||
}
|
||||
|
||||
minifyJs {
|
||||
|
||||
source = combineJs
|
||||
dest = file('src/main/resources/assets/js/all.min.js')
|
||||
closure {
|
||||
warningLevel = 'QUIET'
|
||||
}
|
||||
}
|
||||
|
||||
combineCss {
|
||||
|
||||
source = [
|
||||
'src/main/resources/assets/css/bootstrap.css',
|
||||
'src/main/resources/assets/css/fleet.css',
|
||||
'src/main/resources/assets/css/fontawesome-all.css'
|
||||
]
|
||||
|
||||
dest = file('src/main/resources/assets/css/all.css')
|
||||
}
|
||||
|
||||
minifyCss {
|
||||
|
||||
source = combineCss
|
||||
dest = file('src/main/resources/assets/css/all.min.css')
|
||||
exclude 'META-INF/INDEX.LIST', 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
|
||||
}
|
||||
|
||||
task configureLogConfiguration(type: Copy) {
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@ -17,12 +17,9 @@
|
||||
|
||||
package io.linuxserver.fleet.auth;
|
||||
|
||||
import io.linuxserver.fleet.auth.AuthenticationResult;
|
||||
import io.linuxserver.fleet.auth.security.PasswordEncoder;
|
||||
|
||||
public interface AuthenticationDelegate {
|
||||
|
||||
AuthenticationResult authenticate(String username, String password);
|
||||
|
||||
PasswordEncoder getPasswordEncoder();
|
||||
String encodePassword(String rawPassword);
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ public class DefaultAuthenticationDelegate implements AuthenticationDelegate {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasswordEncoder getPasswordEncoder() {
|
||||
return authenticator.getPasswordEncoder();
|
||||
public String encodePassword(final String rawPassword) {
|
||||
return authenticator.getPasswordEncoder().encode(rawPassword);
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ public class DefaultUserAuthenticator implements UserAuthenticator {
|
||||
final User user = userService.lookUpUser(userCredentials.getUsername());
|
||||
|
||||
if (null != user && getPasswordEncoder().matches(userCredentials.getPassword(), user.getPassword())) {
|
||||
return new AuthenticationResult(true, new AuthenticatedUser(user.getUsername()));
|
||||
return new AuthenticationResult(true, new AuthenticatedUser(user));
|
||||
}
|
||||
|
||||
return AuthenticationResult.notAuthenticated();
|
||||
|
||||
@ -17,11 +17,7 @@
|
||||
|
||||
package io.linuxserver.fleet.core;
|
||||
|
||||
import io.linuxserver.fleet.auth.AuthenticationDelegate;
|
||||
import io.linuxserver.fleet.auth.AuthenticationResult;
|
||||
import io.linuxserver.fleet.auth.DefaultAuthenticationDelegate;
|
||||
import io.linuxserver.fleet.auth.authenticator.DefaultUserAuthenticator;
|
||||
import io.linuxserver.fleet.auth.security.PBKDF2PasswordEncoder;
|
||||
import io.linuxserver.fleet.core.config.WebConfiguration;
|
||||
import io.linuxserver.fleet.v2.client.docker.DockerApiClient;
|
||||
import io.linuxserver.fleet.v2.client.docker.dockerhub.DockerHubApiClient;
|
||||
@ -53,7 +49,6 @@ public class FleetAppController extends AbstractAppController implements Service
|
||||
private final ScheduleService scheduleService;
|
||||
private final SynchronisationService syncService;
|
||||
private final UserService userService;
|
||||
private final AuthenticationDelegate authenticationDelegate;
|
||||
private final FileManager fileManager;
|
||||
|
||||
public FleetAppController() {
|
||||
@ -64,9 +59,6 @@ public class FleetAppController extends AbstractAppController implements Service
|
||||
dockerApiDelegate = new DockerApiDelegate(this);
|
||||
syncService = new SynchronisationService(this);
|
||||
userService = new UserService(this, new DefaultUserDAO(getDatabaseProvider()));
|
||||
|
||||
authenticationDelegate = new DefaultAuthenticationDelegate(new DefaultUserAuthenticator(userService,
|
||||
new PBKDF2PasswordEncoder(getAppProperties().getAppSecret())));
|
||||
}
|
||||
|
||||
private static FleetAppController instance;
|
||||
@ -164,8 +156,8 @@ public class FleetAppController extends AbstractAppController implements Service
|
||||
return fileManager;
|
||||
}
|
||||
|
||||
public final AuthenticationResult authenticateUser(final String username, final String password) {
|
||||
return authenticationDelegate.authenticate(username, password);
|
||||
public final AuthenticationResult authenticateCredentials(final String username, final String password) {
|
||||
return userService.authenticateCredentials(username, password);
|
||||
}
|
||||
|
||||
public final void trackBranch(final ImageKey imageKey, final String branchName) {
|
||||
|
||||
@ -19,21 +19,22 @@ package io.linuxserver.fleet.v2.db;
|
||||
|
||||
import io.linuxserver.fleet.core.db.DatabaseProvider;
|
||||
import io.linuxserver.fleet.db.query.InsertUpdateResult;
|
||||
import io.linuxserver.fleet.db.query.InsertUpdateStatus;
|
||||
import io.linuxserver.fleet.v2.key.UserKey;
|
||||
import io.linuxserver.fleet.v2.types.User;
|
||||
import io.linuxserver.fleet.v2.types.internal.UserOutlineRequest;
|
||||
import io.linuxserver.fleet.v2.web.AppRole;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DefaultUserDAO extends AbstractDAO implements UserDAO {
|
||||
|
||||
private static final String GetUser = "{CALL User_Get(?)}";
|
||||
private static final String GetUserByName = "{CALL User_GetByName(?)}";
|
||||
private static final String GetAllUser = "{CALL User_GetAll()}";
|
||||
private static final String CreateUser = "{CALL User_Save(?,?,?,?,?)}";
|
||||
private static final String GetAllUsers = "{CALL User_GetAll()}";
|
||||
private static final String CreateUser = "{CALL User_CreateOutline(?,?,?,?)}";
|
||||
|
||||
public DefaultUserDAO(DatabaseProvider databaseProvider) {
|
||||
super(databaseProvider);
|
||||
@ -41,33 +42,121 @@ public class DefaultUserDAO extends AbstractDAO implements UserDAO {
|
||||
|
||||
@Override
|
||||
public User fetchUser(final UserKey userKey) {
|
||||
return null;
|
||||
|
||||
try (final Connection connection = getConnection()) {
|
||||
|
||||
try (final CallableStatement call = connection.prepareCall(GetUser)) {
|
||||
|
||||
call.setInt(1, userKey.getId());
|
||||
|
||||
final ResultSet results = call.executeQuery();
|
||||
if (results.next()) {
|
||||
return makeOneUser(results);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
getLogger().error("fetchAllUsers unable to complete request", e);
|
||||
throw new RuntimeException("fetchAllUsers", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User lookUpUser(final String username) {
|
||||
return null;
|
||||
|
||||
try (final Connection connection = getConnection()) {
|
||||
|
||||
try (final CallableStatement call = connection.prepareCall(GetUserByName)) {
|
||||
|
||||
call.setString(1, username);
|
||||
|
||||
final ResultSet results = call.executeQuery();
|
||||
if (results.next()) {
|
||||
return makeOneUser(results);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
getLogger().error("fetchAllUsers unable to complete request", e);
|
||||
throw new RuntimeException("fetchAllUsers", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertUpdateResult<User> createUser(final UserOutlineRequest request) {
|
||||
return null;
|
||||
|
||||
try (final Connection connection = getConnection()) {
|
||||
|
||||
try (final CallableStatement call = connection.prepareCall(CreateUser)) {
|
||||
|
||||
int i = 1;
|
||||
call.setString(i++, request.getUsername());
|
||||
call.setString(i++, request.getPassword());
|
||||
call.setString(i++, request.getRole().name());
|
||||
|
||||
final int statusIndex = i;
|
||||
call.registerOutParameter(statusIndex, Types.VARCHAR);
|
||||
|
||||
final ResultSet results = call.executeQuery();
|
||||
|
||||
final DbUpdateStatus status = DbUpdateStatus.valueOf(call.getString(statusIndex));
|
||||
if (results.next() && status.isInserted()) {
|
||||
return new InsertUpdateResult<>(makeOneUser(results));
|
||||
}
|
||||
|
||||
if (status.isExists()) {
|
||||
return new InsertUpdateResult<>(InsertUpdateStatus.FAILED, "User already exists");
|
||||
}
|
||||
}
|
||||
|
||||
return new InsertUpdateResult<>(InsertUpdateStatus.FAILED, "Unknown error");
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
getLogger().error("createUser unable to complete request", e);
|
||||
throw new RuntimeException("createUser", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<User> fetchAllUsers() {
|
||||
return null;
|
||||
|
||||
final List<User> users = new ArrayList<>();
|
||||
|
||||
try (final Connection connection = getConnection()) {
|
||||
|
||||
try (final CallableStatement call = connection.prepareCall(GetAllUsers)) {
|
||||
|
||||
final ResultSet results = call.executeQuery();
|
||||
while (results.next()) {
|
||||
users.add(makeOneUser(results));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
getLogger().error("fetchAllUsers unable to complete request", e);
|
||||
throw new RuntimeException("fetchAllUsers", e);
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertUpdateResult<Void> removeUser(User user) {
|
||||
public InsertUpdateResult<Void> removeUser(final User user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private User makeOneUser(final ResultSet results) throws SQLException {
|
||||
|
||||
return new User(new UserKey(results.getInt("UserId")),
|
||||
results.getString("UserName"),
|
||||
results.getString("Username"),
|
||||
results.getString("UserPassword"),
|
||||
results.getTimestamp("ModifiedTime").toLocalDateTime(),
|
||||
AppRole.valueOf(results.getString("UserRole")));
|
||||
|
||||
@ -17,21 +17,75 @@
|
||||
|
||||
package io.linuxserver.fleet.v2.service;
|
||||
|
||||
import io.linuxserver.fleet.auth.AuthenticationDelegate;
|
||||
import io.linuxserver.fleet.auth.AuthenticationResult;
|
||||
import io.linuxserver.fleet.auth.DefaultAuthenticationDelegate;
|
||||
import io.linuxserver.fleet.auth.authenticator.DefaultUserAuthenticator;
|
||||
import io.linuxserver.fleet.auth.security.PBKDF2PasswordEncoder;
|
||||
import io.linuxserver.fleet.core.FleetAppController;
|
||||
import io.linuxserver.fleet.db.query.InsertUpdateResult;
|
||||
import io.linuxserver.fleet.v2.db.UserDAO;
|
||||
import io.linuxserver.fleet.v2.key.UserKey;
|
||||
import io.linuxserver.fleet.v2.types.User;
|
||||
import io.linuxserver.fleet.v2.types.internal.UserOutlineRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserService extends AbstractAppService {
|
||||
|
||||
private final UserDAO userDAO;
|
||||
private final UserDAO userDAO;
|
||||
private final AuthenticationDelegate authDelegate;
|
||||
|
||||
public UserService(final FleetAppController controller,
|
||||
final UserDAO userDAO) {
|
||||
super(controller);
|
||||
this.userDAO = userDAO;
|
||||
this.userDAO = userDAO;
|
||||
this.authDelegate = new DefaultAuthenticationDelegate(new DefaultUserAuthenticator(this,
|
||||
new PBKDF2PasswordEncoder(getProperties().getAppSecret())));
|
||||
createInitialAdminUser();
|
||||
}
|
||||
|
||||
public final AuthenticationResult authenticateCredentials(final String username, final String password) {
|
||||
return authDelegate.authenticate(username, password);
|
||||
}
|
||||
|
||||
public final User lookUpUser(final String username) {
|
||||
return userDAO.lookUpUser(username);
|
||||
}
|
||||
|
||||
public final User fetchUser(final UserKey userKey) {
|
||||
return userDAO.fetchUser(userKey);
|
||||
}
|
||||
|
||||
public final List<User> fetchAllUsers() {
|
||||
return userDAO.fetchAllUsers();
|
||||
}
|
||||
|
||||
public final User createUser(final UserOutlineRequest userOutlineRequest) {
|
||||
|
||||
final InsertUpdateResult<User> result = userDAO.createUser(userOutlineRequest);
|
||||
if (result.isError()) {
|
||||
|
||||
getLogger().error("Unable to create new user: {}", result.getStatusMessage());
|
||||
throw new RuntimeException("Unable to create new user: " + result.getStatusMessage());
|
||||
}
|
||||
return result.getResult();
|
||||
}
|
||||
|
||||
private void createInitialAdminUser() {
|
||||
|
||||
if (fetchAllUsers().isEmpty()) {
|
||||
|
||||
getLogger().info("There are no users! Creating initial user with default credentials");
|
||||
final UserOutlineRequest encodedUser = UserOutlineRequest.InitialFirstLoadUser.cloneWithPassword(
|
||||
authDelegate.encodePassword(UserOutlineRequest.InitialFirstLoadUser.getPassword())
|
||||
);
|
||||
|
||||
createUser(encodedUser);
|
||||
|
||||
getLogger().warn("!!!!!!!!");
|
||||
getLogger().warn("DEFAULT USER CREATED. CHANGE THE PASSWORD OR CREATE A NEW USER!");
|
||||
getLogger().warn("!!!!!!!!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,6 +34,10 @@ public class UserOutlineRequest {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
public final UserOutlineRequest cloneWithPassword(final String password) {
|
||||
return new UserOutlineRequest(getUsername(), password, getRole());
|
||||
}
|
||||
|
||||
public final String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@ -66,37 +66,40 @@ public class WebRouteController {
|
||||
|
||||
webInstance.routes(() -> {
|
||||
|
||||
get(Locations.Login, new LoginController(app), roles(AppRole.Anyone));
|
||||
final LoginController loginController = new LoginController(app);
|
||||
get( Locations.Login, loginController, roles(AppRole.Anyone));
|
||||
post(Locations.Login, loginController, roles(AppRole.Anyone));
|
||||
|
||||
get(Locations.Home, new HomeController( app), roles(AppRole.Anyone));
|
||||
get(Locations.Image, new ImageController(app), roles(AppRole.Anyone));
|
||||
|
||||
get(Locations.Admin.Repositories, new AdminRepositoryController(app), roles(AppRole.Anyone));
|
||||
get(Locations.Admin.Images, new AdminImageController( app), roles(AppRole.Anyone));
|
||||
get(Locations.Admin.Schedules, new AdminScheduleController( app), roles(AppRole.Anyone));
|
||||
get(Locations.Admin.Repositories, new AdminRepositoryController(app), roles(AppRole.Admin));
|
||||
get(Locations.Admin.Images, new AdminImageController( app), roles(AppRole.Admin));
|
||||
get(Locations.Admin.Schedules, new AdminScheduleController( app), roles(AppRole.Admin));
|
||||
|
||||
final AdminImageEditController imageEditController = new AdminImageEditController(app);
|
||||
get(Locations.Admin.ImageEdit, imageEditController, roles(AppRole.Anyone));
|
||||
post(Locations.Admin.ImageEdit, imageEditController, roles(AppRole.Anyone));
|
||||
get( Locations.Admin.ImageEdit, imageEditController, roles(AppRole.Admin));
|
||||
post(Locations.Admin.ImageEdit, imageEditController, roles(AppRole.Admin));
|
||||
|
||||
path(Locations.Internal.Api, () -> {
|
||||
|
||||
path(Locations.Internal.Repository, () -> {
|
||||
|
||||
put(apiController::updateRepositorySpec, roles(AppRole.Anyone));
|
||||
post(apiController::addNewRepository, roles(AppRole.Anyone));
|
||||
delete(apiController::deleteRepository, roles(AppRole.Anyone));
|
||||
put( apiController::updateRepositorySpec, roles(AppRole.Admin));
|
||||
post( apiController::addNewRepository, roles(AppRole.Admin));
|
||||
delete(apiController::deleteRepository, roles(AppRole.Admin));
|
||||
|
||||
path(Locations.Internal.Sync, () -> {
|
||||
put(apiController::syncRepository, roles(AppRole.Anyone));
|
||||
put(apiController::syncRepository, roles(AppRole.Admin));
|
||||
});
|
||||
});
|
||||
|
||||
path(Locations.Internal.Image, () -> {
|
||||
|
||||
put(apiController::updateImageSpec, roles(AppRole.Anyone));
|
||||
put(apiController::updateImageSpec, roles(AppRole.Admin));
|
||||
|
||||
path(Locations.Internal.Sync, () -> {
|
||||
put(apiController::syncImage, roles(AppRole.Anyone));
|
||||
put(apiController::syncImage, roles(AppRole.Admin));
|
||||
});
|
||||
|
||||
path(Locations.Internal.Stats, () -> {
|
||||
@ -104,12 +107,12 @@ public class WebRouteController {
|
||||
});
|
||||
|
||||
path(Locations.Internal.Track, () -> {
|
||||
put(apiController::trackNewBranch, roles(AppRole.Anyone));
|
||||
put(apiController::trackNewBranch, roles(AppRole.Admin));
|
||||
});
|
||||
});
|
||||
|
||||
path(Locations.Internal.Schedule, () -> {
|
||||
put(apiController::runSchedule, roles(AppRole.Anyone));
|
||||
put(apiController::runSchedule, roles(AppRole.Admin));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -21,7 +21,7 @@ import io.javalin.core.security.AccessManager;
|
||||
import io.javalin.core.security.Role;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import io.linuxserver.fleet.v2.types.User;
|
||||
import io.linuxserver.fleet.auth.AuthenticatedUser;
|
||||
import io.linuxserver.fleet.v2.web.AppRole;
|
||||
import io.linuxserver.fleet.v2.web.Locations;
|
||||
import io.linuxserver.fleet.v2.web.SessionAttributes;
|
||||
@ -38,12 +38,24 @@ public class DefaultAccessManager implements AccessManager {
|
||||
handler.handle(ctx);
|
||||
} else {
|
||||
|
||||
final User user = ctx.sessionAttribute(SessionAttributes.AuthenticatedUser);
|
||||
final AuthenticatedUser user = ctx.sessionAttribute(SessionAttributes.AuthenticatedUser);
|
||||
if (null == user) {
|
||||
ctx.redirect(Locations.Login);
|
||||
} else {
|
||||
} else if (isUserRoleValid(user, permittedRoles)){
|
||||
handler.handle(ctx);
|
||||
} else {
|
||||
ctx.status(401);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUserRoleValid(final AuthenticatedUser user, final Set<Role> permittedRoles) {
|
||||
|
||||
for (Role role : permittedRoles) {
|
||||
if (user.getRoles().contains(role)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,20 +45,32 @@ public class LoginController extends AbstractPageHandler {
|
||||
if (null != ctx.formParam("invalidate")) {
|
||||
doLogOut(ctx);
|
||||
} else {
|
||||
doLogIn(ctx);
|
||||
|
||||
final boolean loggedIn = doLogIn(ctx);
|
||||
if (!loggedIn) {
|
||||
|
||||
final PageModelSpec pageModelSpec = new PageModelSpec("views/pages/login.ftl");
|
||||
pageModelSpec.addModelAttribute("loginFailed", "Username or password was incorrect.");
|
||||
return pageModelSpec;
|
||||
}
|
||||
}
|
||||
|
||||
return new PageModelSpec("redirect:/");
|
||||
}
|
||||
|
||||
private void doLogIn(final Context ctx) {
|
||||
private boolean doLogIn(final Context ctx) {
|
||||
|
||||
final String username = ctx.formParam("username");
|
||||
final String password = ctx.formParam("password");
|
||||
|
||||
final AuthenticationResult result = getController().authenticateUser(username, password);
|
||||
final AuthenticationResult result = getController().authenticateCredentials(username, password);
|
||||
if (result.isAuthenticated()) {
|
||||
|
||||
ctx.sessionAttribute(SessionAttributes.AuthenticatedUser, result.getUser());
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
136
src/main/resources/db/migration/V2.4__UpdateUserSprocs.sql
Normal file
136
src/main/resources/db/migration/V2.4__UpdateUserSprocs.sql
Normal file
@ -0,0 +1,136 @@
|
||||
DELIMITER //
|
||||
|
||||
CREATE OR REPLACE VIEW `User_View` AS (
|
||||
|
||||
SELECT
|
||||
`id` AS `UserId`,
|
||||
`username` AS `Username`,
|
||||
`password` AS `UserPassword`,
|
||||
`modified` AS `ModifiedTime`,
|
||||
`role` AS `UserRole`
|
||||
FROM
|
||||
Users
|
||||
);
|
||||
//
|
||||
|
||||
CREATE OR REPLACE PROCEDURE `User_CreateOutline`
|
||||
(
|
||||
in_username VARCHAR(255),
|
||||
in_password VARCHAR(255),
|
||||
in_role ENUM('Admin'),
|
||||
|
||||
OUT out_status ENUM('Inserted', 'NoChange', 'Exists')
|
||||
)
|
||||
BEGIN
|
||||
|
||||
IF NOT EXISTS(SELECT 1 FROM User_View WHERE `Username` = in_username) THEN
|
||||
|
||||
INSERT INTO Users
|
||||
(
|
||||
`username`,
|
||||
`password`,
|
||||
`role`
|
||||
)
|
||||
VALUES
|
||||
(
|
||||
in_username,
|
||||
in_password,
|
||||
in_role
|
||||
);
|
||||
|
||||
SET out_status = 'Inserted';
|
||||
|
||||
SELECT * FROM User_View WHERE `UserId` = LAST_INSERT_ID();
|
||||
|
||||
ELSE
|
||||
SET out_status = 'Exists';
|
||||
END IF;
|
||||
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE OR REPLACE PROCEDURE `User_Save`
|
||||
(
|
||||
in_id INT,
|
||||
in_username VARCHAR(255),
|
||||
in_password VARCHAR(255),
|
||||
in_role ENUM('Admin'),
|
||||
|
||||
OUT out_status ENUM('Updated', 'NoChange')
|
||||
)
|
||||
BEGIN
|
||||
|
||||
IF EXISTS(SELECT 1 FROM User_View WHERE `Username` = in_username) THEN
|
||||
|
||||
UPDATE Users
|
||||
SET
|
||||
`password` = in_password,
|
||||
`role` = in_role
|
||||
WHERE
|
||||
`id` = in_id;
|
||||
|
||||
SET out_status = 'Updated';
|
||||
|
||||
SELECT * FROM User_View WHERE `UserId` = in_id;
|
||||
|
||||
ELSE
|
||||
SET out_status = 'NoChange';
|
||||
END IF;
|
||||
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE OR REPLACE PROCEDURE `User_GetAll` ()
|
||||
BEGIN
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
User_View;
|
||||
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE OR REPLACE PROCEDURE `User_Get`
|
||||
(
|
||||
in_id INT
|
||||
)
|
||||
BEGIN
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
User_View
|
||||
WHERE
|
||||
`UserId` = in_id;
|
||||
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE OR REPLACE PROCEDURE `User_GetByName`
|
||||
(
|
||||
in_username VARCHAR(255)
|
||||
)
|
||||
BEGIN
|
||||
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
User_View
|
||||
WHERE
|
||||
`Username` = in_username;
|
||||
END;
|
||||
//
|
||||
|
||||
CREATE OR REPLACE PROCEDURE `User_Delete`
|
||||
(
|
||||
in_id INT
|
||||
)
|
||||
BEGIN
|
||||
|
||||
DELETE FROM Users WHERE `id` = in_id;
|
||||
|
||||
END;
|
||||
//
|
||||
|
||||
DELIMITER ;
|
||||
@ -1,5 +1,5 @@
|
||||
#Sun Jan 19 10:53:51 GMT 2020
|
||||
app.build.date=2020-01-19T10\:53\:51
|
||||
#Sun Jan 19 13:34:43 GMT 2020
|
||||
app.build.date=2020-01-19T13\:34\:43
|
||||
app.build.os=Linux
|
||||
app.build.user=josh
|
||||
app.version=2.0.0
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
<#import "../ui/elements/table.ftl" as table />
|
||||
<#import "../ui/elements/button.ftl" as button />
|
||||
|
||||
<@base.base title="Images" context="home" showTitle=false>
|
||||
<@base.base title="Images" context="home" showTitle=false availableRepositories=availableRepositories>
|
||||
|
||||
<section class="section is-paddingless-top">
|
||||
<div class="container">
|
||||
|
||||
60
src/main/resources/views/pages/login.ftl
Normal file
60
src/main/resources/views/pages/login.ftl
Normal file
@ -0,0 +1,60 @@
|
||||
<#--
|
||||
Copyright (c) 2019 LinuxServer.io
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<#import "../prebuilt/base.ftl" as base />
|
||||
<#import "../prebuilt/fleet-title.ftl" as title />
|
||||
<#import "../ui/elements/box.ftl" as box />
|
||||
<#import "../ui/form/input.ftl" as input />
|
||||
<#import "../ui/elements/button.ftl" as button />
|
||||
<#import "../ui/components/message.ftl" as message />
|
||||
<#import "../ui/layout/container.ftl" as container />
|
||||
|
||||
<@base.base title="Log In" showNav=false context="login" hasHero=false>
|
||||
|
||||
<section class="hero is-fullheight">
|
||||
<div class="hero-body">
|
||||
<@container.container isFluid=true>
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-one-third-desktop is-two-thirds-tablet is-full-mobile">
|
||||
|
||||
<form class="needs-validation" novalidate action="/login" method="post">
|
||||
<@box.box>
|
||||
|
||||
<@title.title boldValue="fleet" />
|
||||
|
||||
<@input.text id="username" icon="user" placeholder="Username" isRequired=true />
|
||||
<@input.password id="password" icon="lock" placeholder="Password" isRequired=true />
|
||||
|
||||
<@button.submit id="SubmitLogin" extraClasses="is-fullwidth">
|
||||
Log In
|
||||
</@button.submit>
|
||||
|
||||
<#if loginFailed?has_content>
|
||||
<@message.message colour="danger" extraClasses="has-margin-top">
|
||||
${loginFailed?html}
|
||||
</@message.message>
|
||||
</#if>
|
||||
|
||||
</@box.box>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</@container.container>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</@base.base>
|
||||
@ -21,7 +21,7 @@
|
||||
<#import "../ui/form/input.ftl" as input />
|
||||
<#import "../prebuilt/system-alert.ftl" as systemAlert />
|
||||
|
||||
<#macro base title context showTitle=true backgroundColour="white" hasHero=false>
|
||||
<#macro base title context showTitle=true showNav=true backgroundColour="white" hasHero=false availableRepositories=[]>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@ -42,6 +42,7 @@
|
||||
|
||||
<body class="has-background-${backgroundColour} has-text-grey-dark">
|
||||
|
||||
<#if showNav>
|
||||
<@navbar.navbar id="MainNav" hasShadow=false itemPlacement="end" colour=(hasHero?string('dark', 'normal-colour')) extraClasses=''>
|
||||
|
||||
<#if context="home">
|
||||
@ -58,28 +59,29 @@
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
<@navbar.dropdown icon="shield-alt" displayText="Admin" isRight=true>
|
||||
<@navbar.item displayText="Repositories" icon="cubes" link="/admin/repositories" isActive=(context=='admin_repositories') />
|
||||
<@navbar.item displayText="Schedules" icon="clock" link="/admin/schedules" isActive=(context=='admin_schedules') />
|
||||
<@navbar.item displayText="Users" icon="users" link="/admin/users" isActive=(context=='admin_users') />
|
||||
<@navbar.item displayText="System Settings" icon="cog" link="/admin/system" isActive=(context=='admin_system') />
|
||||
</@navbar.dropdown>
|
||||
|
||||
<#if __AuthenticatedUser?has_content>
|
||||
|
||||
<@navbar.dropdown displayText=__AuthenticatedUser.name isRight=true>
|
||||
<@navbar.item displayText="Log Out" icon="sign-out-alt" />
|
||||
<@navbar.dropdown icon="shield-alt" displayText="Admin" isRight=true>
|
||||
<@navbar.item displayText="Repositories" icon="cubes" link="/admin/repositories" isActive=(context=='admin_repositories') />
|
||||
<@navbar.item displayText="Schedules" icon="clock" link="/admin/schedules" isActive=(context=='admin_schedules') />
|
||||
<#-- <@navbar.item displayText="Users" icon="users" link="/admin/users" isActive=(context=='admin_users') />-->
|
||||
<#-- <@navbar.item displayText="System Settings" icon="cog" link="/admin/system" isActive=(context=='admin_system') />-->
|
||||
</@navbar.dropdown>
|
||||
|
||||
<@navbar.dropdown displayText=__AuthenticatedUser.name isRight=true icon="user">
|
||||
<@navbar.item displayText="Log Out" icon="sign-out-alt" icon="sign-out-alt" link="/login?invalidate=true" />
|
||||
</@navbar.dropdown>
|
||||
|
||||
<#else>
|
||||
<@navbar.buttons size="small">
|
||||
<@button.link id="LogIn" link="/login" size="small" colour="white">
|
||||
<@button.link id="LogIn" link="/login" size="small" colour="light">
|
||||
<i class="fas fa-sign-in-alt"></i> Log In
|
||||
</@button.link>
|
||||
</@navbar.buttons>
|
||||
</#if>
|
||||
|
||||
</@navbar.navbar>
|
||||
</#if>
|
||||
|
||||
<div id="NotificationWrapper">
|
||||
<div id="Notifications"></div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user