diff --git a/homework-g597-sigareva/pom.xml b/homework-g597-sigareva/pom.xml
index 0817be603..0ddfd9962 100644
--- a/homework-g597-sigareva/pom.xml
+++ b/homework-g597-sigareva/pom.xml
@@ -12,12 +12,41 @@
homework-g597-sigareva
+
+ 1.4.2.RELEASE
+
+
ru.mipt.java2016
homework-base
1.0.0
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+ ${spring.boot.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+ ${spring.boot.version}
+
+
+ com.zaxxer
+ HikariCP
+ 2.5.1
+
+
+ com.h2database
+ h2
+ 1.4.193
+
ru.mipt.java2016
homework-tests
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingDao.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingDao.java
new file mode 100644
index 000000000..95d454dac
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingDao.java
@@ -0,0 +1,93 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+@Repository
+public class BillingDao {
+ private static final Logger LOG = LoggerFactory.getLogger(BillingDao.class);
+
+ @Autowired
+ private DataSource dataSource;
+
+ private JdbcTemplate jdbcTemplate;
+
+ @PostConstruct
+ public void postConstruct() {
+ jdbcTemplate = new JdbcTemplate(dataSource, false);
+ initSchema();
+ }
+
+ public void initSchema() {
+ LOG.trace("Initializing schema");
+ jdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS billing");
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.users " +
+ "(username VARCHAR PRIMARY KEY, password VARCHAR, enabled BOOLEAN)");
+ jdbcTemplate.execute("DELETE FROM billing.users WHERE username = 'username'");
+ jdbcTemplate.update("INSERT INTO billing.users VALUES ('username', 'password', TRUE)");
+ }
+
+ public BillingUser loadUser(String username) throws EmptyResultDataAccessException {
+ LOG.trace("Querying for user " + username);
+ return jdbcTemplate.queryForObject(
+ "SELECT username, password, enabled FROM billing.users WHERE username = ?",
+ new Object[]{username},
+ new RowMapper() {
+ @Override
+ public BillingUser mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new BillingUser(
+ rs.getString("username"),
+ rs.getString("password"),
+ rs.getBoolean("enabled")
+ );
+ }
+ }
+ );
+ }
+
+ public Double getVariable(String username, String variableName) throws EmptyResultDataAccessException {
+ LOG.trace("Querying for user " + username);
+ return jdbcTemplate.queryForObject(
+ "SELECT username, variableName, value FROM billing.usersVariables WHERE username = '" + username + "' " +
+ "AND variableName = '" + variableName + "'",
+ new Object[]{},
+ new RowMapper() {
+ @Override
+ public Double mapRow(ResultSet rs, int rowNum) throws SQLException {
+ return new Double(
+ rs.getString("value")
+ );
+ }
+ }
+ );
+ }
+
+ public void registerNewUser(String user, String password) {
+ jdbcTemplate.update("INSERT INTO billing.users VALUES ('" + user + "', '" + password + "', TRUE)");
+ }
+
+ public void addValue(String user, String variableName, String value) {
+ System.out.println(user);
+ System.out.println(variableName);
+ jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS billing.usersVariables " +
+ "(username VARCHAR, variableName VARCHAR PRIMARY KEY, value FLOAT)");
+ jdbcTemplate.execute("DELETE FROM billing.usersVariables WHERE variableName = '" + variableName + "' " +
+ "AND username = '" + user + "'");
+ jdbcTemplate.update("INSERT INTO billing.usersVariables VALUES ('" + user + "', '" + variableName + "', '" + value + "')");
+ }
+
+ public void deleteVariable(String user, String variableName) {
+ jdbcTemplate.execute("DELETE FROM billing.usersVariables WHERE variableName = '" + variableName + "' " +
+ "AND username = '" + user + "'");
+ }
+}
\ No newline at end of file
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingDatabaseConfiguration.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingDatabaseConfiguration.java
new file mode 100644
index 000000000..ba1ff210e
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingDatabaseConfiguration.java
@@ -0,0 +1,26 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+
+@Configuration
+public class BillingDatabaseConfiguration {
+ @Bean
+ public DataSource billingDataSource(
+ @Value("${ru.mipt.java2016.homework.g597.sigareva.task4.jdbcUrl}") String jdbcUrl,
+ @Value("${ru.mipt.java2016.homework.g597.sigareva.task4.username:}") String username,
+ @Value("${ru.mipt.java2016.homework.g597.sigareva.task4.password:}") String password
+ ) {
+ HikariConfig config = new HikariConfig();
+ config.setDriverClassName(org.h2.Driver.class.getName());
+ config.setJdbcUrl(jdbcUrl);
+ config.setUsername(username);
+ config.setPassword(password);
+ return new HikariDataSource(config);
+ }
+}
\ No newline at end of file
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingUser.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingUser.java
new file mode 100644
index 000000000..4ee119f56
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/BillingUser.java
@@ -0,0 +1,69 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+public class BillingUser {
+ private final String username;
+ private final String password;
+ private final boolean enabled;
+
+ public BillingUser(String username, String password, boolean enabled) {
+ if (username == null) {
+ throw new IllegalArgumentException("Null username is not allowed");
+ }
+ if (password == null) {
+ throw new IllegalArgumentException("Null password is not allowed");
+ }
+ this.username = username;
+ this.password = password;
+ this.enabled = enabled;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ @Override
+ public String toString() {
+ return "BillingUser{" +
+ "username='" + username + '\'' +
+ ", password='" + password + '\'' +
+ ", enabled=" + enabled +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ BillingUser that = (BillingUser) o;
+
+ if (enabled != that.enabled) {
+ return false;
+ }
+ if (!username.equals(that.username)) {
+ return false;
+ }
+ return password.equals(that.password);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = username.hashCode();
+ result = 31 * result + password.hashCode();
+ result = 31 * result + (enabled ? 1 : 0);
+ return result;
+ }
+}
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/CalculatorController.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/CalculatorController.java
new file mode 100644
index 000000000..4ae2aea17
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/CalculatorController.java
@@ -0,0 +1,75 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.web.bind.annotation.*;
+import ru.mipt.java2016.homework.base.task1.Calculator;
+import ru.mipt.java2016.homework.base.task1.ParsingException;
+
+import java.io.IOException;
+import java.util.Vector;
+
+@RestController
+public class CalculatorController {
+ private static final Logger LOG = LoggerFactory.getLogger(CalculatorController.class);
+ @Autowired
+ private MyCalculator calculator;
+
+ @Autowired
+ private BillingDao billingDao;
+
+ @RequestMapping(path = "/ping", method = RequestMethod.GET, produces = "text/plain")
+ public String echo() {
+ return "OK\n";
+ }
+
+ @RequestMapping(path = "/", method = RequestMethod.GET, produces = "text/html")
+ public String main(@RequestParam(required = false) String name) {
+ if (name == null) {
+ name = "world";
+ }
+ return "" +
+ "FediqApp" +
+ "Hello, " + name + "!
" +
+ "";
+ }
+
+ @RequestMapping(path = "/eval", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain")
+ public String eval(Authentication userName, @RequestBody String expression) throws ParsingException { // + AUTH
+ LOG.debug("Evaluation request: [" + expression + "]");
+ double result = calculator.calculate(expression, userName.getName()); // username
+ LOG.trace("Result: " + result);
+ return Double.toString(result) + "\n";
+ }
+
+ @RequestMapping(path = "/registration", method = RequestMethod.POST, consumes = "text/plain", produces = "text/plain")
+ public void registration(@RequestParam(value = "arguments") Vector arguments) throws IOException {
+ try {
+ if (arguments.size() != 2) {
+ throw new IOException("Mistake");
+ } else {
+ billingDao.registerNewUser(arguments.firstElement(), arguments.lastElement());
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Can't understand");
+ }
+ }
+
+ @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.PUT, consumes = "text/plain", produces = "text/plain")
+ public void addingVariable(Authentication userName, @PathVariable String variableName, @RequestBody String value) throws IOException {
+ billingDao.addValue(userName.getName(), variableName, value);
+ }
+
+ @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.DELETE, consumes = "text/plain", produces = "text/plain")
+ public void deleteVariable(Authentication userName, @PathVariable String variableName) throws IOException {
+ billingDao.deleteVariable(userName.getName(), variableName);
+ }
+
+ @RequestMapping(path = "/variable/{variableName}", method = RequestMethod.GET/*, consumes = "text/plain", produces = "text/plain"*/)
+ public String getVariable(Authentication userName, @PathVariable String variableName) throws IOException {
+ System.out.println("ALIVE");
+ return billingDao.getVariable(userName.getName(), variableName).toString();
+ }
+}
\ No newline at end of file
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/MyApplication.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/MyApplication.java
new file mode 100644
index 000000000..fe7550d6d
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/MyApplication.java
@@ -0,0 +1,41 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+ import org.springframework.beans.factory.annotation.Value;
+ import org.springframework.boot.Banner;
+ import org.springframework.boot.SpringApplication;
+ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+ import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
+ import org.springframework.context.annotation.Bean;
+ import org.springframework.context.annotation.ComponentScan;
+ import org.springframework.context.annotation.Configuration;
+
+/**
+ * curl http://localhost:9001/eval \
+ * -X POST \
+ * -H "Content-Type: text/plain" \
+ * -H "Authorization: Basic $(echo -n "username:password" | base64)" \
+ * --data-raw "44*3+2"
+ */
+
+@EnableAutoConfiguration
+@Configuration
+@ComponentScan(basePackageClasses = MyApplication.class)
+public class MyApplication {
+
+ @Bean
+ public MyCalculator calculator() {
+ return new MyCalculator();
+ }
+
+ @Bean
+ public EmbeddedServletContainerCustomizer customizer(
+ @Value("${ru.mipt.java2016.homework.g597.sigareva.task4.httpPort:9001}") int port) {
+ return container -> container.setPort(port);
+ }
+
+ public static void main(String[] args) {
+ SpringApplication application = new SpringApplication(MyApplication.class);
+ application.setBannerMode(Banner.Mode.OFF);
+ application.run(args);
+ }
+}
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/MyCalculator.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/MyCalculator.java
new file mode 100644
index 000000000..243e752c1
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/MyCalculator.java
@@ -0,0 +1,215 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+import java.util.Vector;
+
+public class MyCalculator {
+ Map Variables = new HashMap<>();
+
+ static final String operations = "()+-/*_,";
+ static final String expression = "2 * (3 - 7)";
+
+ static Stack operationsStack;
+ static Stack resultStack;
+
+ @Autowired
+ private BillingDao billingDao;
+
+ StringBuilder newExpression = new StringBuilder(expression);
+
+ public boolean checkSymbols(StringBuilder newExpression) {
+ boolean rightSymbolFlag = false;
+
+ for (int i = 0; i < newExpression.length(); ++i) {
+ rightSymbolFlag = false;
+
+ if (Character.isDigit(newExpression.charAt(i))) {
+ rightSymbolFlag = true;
+ }
+
+ for (char j = 'a'; j <= 'z'; ++j) {
+ if (newExpression.charAt(i) == j) {
+ rightSymbolFlag = true;
+ }
+ }
+
+ for (int j = 0; j < operations.length(); ++j) {
+ if (operations.charAt(j) == newExpression.charAt(i)) {
+ rightSymbolFlag = true;
+ }
+ }
+
+ if (!rightSymbolFlag) {
+ break;
+ }
+ }
+ return rightSymbolFlag;
+ }
+
+
+ public double calculate(String expression, String username) { // username
+ String newExpression = new String();
+
+ newExpression = expression.replaceAll(" ", "");
+ if (newExpression.charAt(0) == '('){
+ return calculate(expression.substring(1, expression.length() - 1), username);
+ }
+ StringBuilder resultExpression = new StringBuilder();
+ if (newExpression.charAt(0) == '-') {
+ resultExpression.append("0");
+ }
+ resultExpression.append(newExpression.charAt(0));
+
+ for (int i = 1; i < newExpression.length(); ++i) {
+ if (newExpression.charAt(i - 1) == '(' && newExpression.charAt(i) == '-') {
+ resultExpression.append("0");
+ }
+ resultExpression.append(newExpression.charAt(i));
+ }
+
+ StringBuilder name = new StringBuilder();
+ StringBuilder newResult = new StringBuilder();
+
+ for (int i = 0; i < resultExpression.length(); ++i){
+ boolean operatorFlag = false;
+ for (int j = 0; j < operations.length(); ++j) {
+ if (resultExpression.charAt(i) == operations.charAt(j)) {
+ operatorFlag = true;
+ }
+ }
+ if(operatorFlag) {
+ if (name.length() > 0) {
+ try {
+ Double value = billingDao.getVariable(username, name.toString());
+ newResult.append(value.toString());
+ } catch (EmptyResultDataAccessException e) {
+ newResult.append(name);
+ }
+ name = new StringBuilder();
+ }
+ newResult.append(resultExpression.charAt(i));
+ } else {
+ name.append(resultExpression.charAt(i));
+ }
+ }
+
+ if (name.length() > 0) {
+ try {
+ Double value = billingDao.getVariable(username, name.toString());
+ newResult.append(value.toString());
+ } catch (EmptyResultDataAccessException e) {
+ newResult.append(name);
+ }
+ name = new StringBuilder();
+ }
+
+ resultExpression = newResult;
+ System.out.println(resultExpression);
+
+ Integer balance = 0;
+ for (int i = 0; i < resultExpression.length(); ++i) {
+ if (resultExpression.charAt(i) == '(') {
+ ++balance;
+ }
+ if (newExpression.charAt(i) == ')') {
+ --balance;
+ }
+ if (resultExpression.charAt(i) == '+' && balance == 0) {
+ String firstPartOfExpression = resultExpression.substring(0, i);
+ String secondPartOfString = resultExpression.substring(i + 1, resultExpression.length());
+ return calculate(firstPartOfExpression, username) + calculate(secondPartOfString, username);
+ }
+ if (resultExpression.charAt(i) == '-' && balance == 0) {
+ String firstPartOfExpression = resultExpression.substring(0, i);
+ String secondPartOfString = resultExpression.substring(i + 1, resultExpression.length());
+ return calculate(firstPartOfExpression, username) - calculate(secondPartOfString, username);
+ }
+ }
+ balance = 0;
+ for (int i = 0; i < resultExpression.length(); ++i) {
+ if (resultExpression.charAt(i) == '(') {
+ ++balance;
+ }
+ if (newExpression.charAt(i) == ')') {
+ --balance;
+ }
+ if (resultExpression.charAt(i) == '*' && balance == 0) {
+ String firstPartOfExpression = resultExpression.substring(0, i);
+ String secondPartOfString = resultExpression.substring(i + 1, resultExpression.length());
+ return calculate(firstPartOfExpression, username) * calculate(secondPartOfString, username);
+ }
+ if (resultExpression.charAt(i) == '/' && balance == 0) {
+ String firstPartOfExpression = resultExpression.substring(0, i);
+ String secondPartOfString = resultExpression.substring(i + 1, resultExpression.length());
+ return calculate(firstPartOfExpression, username) / calculate(secondPartOfString, username);
+ }
+ }
+ /*if (resultExpression.charAt(0) == '(') {
+ return calculate(resultExpression.substring(1, resultExpression.length() - 1));
+ } else {*/
+ if (Character.isDigit((resultExpression.charAt(0)))) {
+ return Double.parseDouble(resultExpression.toString());
+ } else {
+ String functionName = resultExpression.substring(0, resultExpression.indexOf("("));
+ String arguments = resultExpression.substring(resultExpression.indexOf("(") + 1, resultExpression.length() - 1);
+ Vector functionArguments = new Vector<>();
+ Integer argumentBalance = 0;
+ Integer start = 0;
+ for (int i = 0; i < arguments.length(); ++i) {
+ if (arguments.charAt(i) == '(') {
+ ++argumentBalance;
+ }
+ if (arguments.charAt(i) == ')') {
+ --argumentBalance;
+ }
+ if (arguments.charAt(i) == ',' && argumentBalance == 0) {
+ functionArguments.add(calculate(arguments.substring(start, i), username));
+ start = i + 1;
+ }
+ }
+ functionArguments.add(calculate(arguments.substring(start, arguments.length()), username));
+ if (functionName.equals("sin")) {
+ return Math.sin(functionArguments.lastElement());
+ }
+ if (functionName.equals("cos")) {
+ return Math.cos(functionArguments.lastElement());
+ }
+ if (functionName.equals("tg")) {
+ return Math.tan(functionArguments.lastElement());
+ }
+ if (functionName.equals("sqrt")) {
+ return Math.sqrt(functionArguments.lastElement());
+ }
+ if (functionName.equals("pow")) {
+ return Math.pow(functionArguments.firstElement(), functionArguments.lastElement());
+ }
+ if (functionName.equals("abs")) {
+ return Math.abs(functionArguments.lastElement());
+ }
+ if (functionName.equals("sign")) {
+ return Math.signum(functionArguments.lastElement());
+ }
+ if (functionName.equals("log")) {
+ return Math.log(functionArguments.firstElement()) / Math.log(functionArguments.lastElement());
+ }
+ if (functionName.equals("log2")) {
+ return Math.log(functionArguments.lastElement()) / Math.log(2);
+ }
+ if (functionName.equals("rnd")) {
+ return Math.random();
+ }
+ if (functionName.equals("max")) {
+ return Math.max(functionArguments.firstElement(), functionArguments.lastElement());
+ }
+ if (functionName.equals("min")) {
+ return Math.min(functionArguments.firstElement(), functionArguments.lastElement());
+ }
+ return 0;
+ }
+ }
+}
diff --git a/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/SecurityServiceConfiguration.java b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/SecurityServiceConfiguration.java
new file mode 100644
index 000000000..d51ddd873
--- /dev/null
+++ b/homework-g597-sigareva/src/main/java/ru/mipt/java2016/homework/g597/sigareva/task4/SecurityServiceConfiguration.java
@@ -0,0 +1,55 @@
+package ru.mipt.java2016.homework.g597.sigareva.task4;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+import java.util.Collections;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityServiceConfiguration extends WebSecurityConfigurerAdapter {
+ private static final Logger LOG = LoggerFactory.getLogger(SecurityServiceConfiguration.class);
+
+ @Autowired
+ private BillingDao billingDao;
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ LOG.info("Configuring security");
+ http
+ .httpBasic().realmName("Calculator").and()
+ .formLogin().disable()
+ .logout().disable()
+ .csrf().disable()
+ .authorizeRequests()
+ .antMatchers("/eval/**").authenticated()
+ .anyRequest().permitAll();
+ }
+
+ @Autowired
+ public void registerGlobalAuthentication(AuthenticationManagerBuilder auth) throws Exception {
+ LOG.info("Registering global user details service");
+ auth.userDetailsService(username -> {
+ try {
+ BillingUser user = billingDao.loadUser(username);
+ return new User(
+ user.getUsername(),
+ user.getPassword(),
+ Collections.singletonList(() -> "AUTH")
+ );
+ } catch (EmptyResultDataAccessException e) {
+ LOG.warn("No such user: " + username);
+ throw new UsernameNotFoundException(username);
+ }
+ });
+ }
+}
\ No newline at end of file