forked from github/wulkanowy-mirror
Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
9c97962e89 | |||
a4445a8a97 | |||
3f54d13b6b | |||
5685e73e46 | |||
e9b357e92d | |||
62bc00cd68 | |||
54e6aee82e | |||
3000c077c4 | |||
7d5072b529 | |||
052d5e3911 | |||
0014b74c6b | |||
08dd316aee | |||
95caa21f2a | |||
cd6e14b13b | |||
2cf262130e | |||
23183c9d7a | |||
be8ee4c835 |
@ -199,24 +199,40 @@ jobs:
|
|||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
|
|
||||||
build_check_tests:
|
build-test-deploy:
|
||||||
jobs:
|
jobs:
|
||||||
- build
|
- build:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
- lint:
|
- lint:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- app-test:
|
- app-test:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- api-test:
|
- api-test:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- instrumented:
|
- instrumented:
|
||||||
requires:
|
filters:
|
||||||
- build
|
tags:
|
||||||
|
only: /.*/
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- sonarcube:
|
- sonarcube:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
requires:
|
requires:
|
||||||
- build
|
- build
|
||||||
- lint
|
- lint
|
||||||
@ -228,4 +244,6 @@ workflows:
|
|||||||
- instrumented
|
- instrumented
|
||||||
filters:
|
filters:
|
||||||
tags:
|
tags:
|
||||||
only: /.*/
|
only: /\d+\.\d+\.\d+/
|
||||||
|
branches:
|
||||||
|
ignore: /.*/
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
[](https://www.bitrise.io/app/daeff1893f3c8128)
|
[](https://www.bitrise.io/app/daeff1893f3c8128)
|
||||||
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
[](https://codecov.io/gh/wulkanowy/wulkanowy)
|
||||||
[](https://bettercodehub.com/)
|
[](https://bettercodehub.com/)
|
||||||
[](https://scrutinizer-ci.com/g/wulkanowy/wulkanowy/?branch=master)
|
[](https://scrutinizer-ci.com/g/wulkanowy/wulkanowy/?branch=master)
|
||||||
[](https://snyk.io/test/github/wulkanowy/wulkanowy?targetFile=app%2Fbuild.gradle)
|
|
||||||
[](https://bintray.com/wulkanowy/wulkanowy/api)
|
[](https://bintray.com/wulkanowy/wulkanowy/api)
|
||||||
|
[](https://discord.gg/vccAQBr)
|
||||||
|
|
||||||
|
[Pobierz wersję beta](https://play.google.com/store/apps/details?id=io.github.wulkanowy&utm_source=vcs)
|
||||||
|
|
||||||
[Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-debug-bitrise-signed.apk)
|
[Pobierz wersję rozwojową](https://bitrise-redirector.herokuapp.com/v0.1/apps/daeff1893f3c8128/builds/master/artifacts/app-debug-bitrise-signed.apk)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public class Client {
|
|||||||
|
|
||||||
private String symbol;
|
private String symbol;
|
||||||
|
|
||||||
private Date lastSuccessRequest = null;
|
private Date lastSuccessRequest;
|
||||||
|
|
||||||
private Cookies cookies = new Cookies();
|
private Cookies cookies = new Cookies();
|
||||||
|
|
||||||
@ -58,13 +58,12 @@ public class Client {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cookies = new Cookies();
|
|
||||||
this.symbol = new Login(this).login(email, password, symbol);
|
this.symbol = new Login(this).login(email, password, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLoggedIn() {
|
private boolean isLoggedIn() {
|
||||||
return getCookies().size() > 0 && lastSuccessRequest != null &&
|
return getCookies().size() > 0 && lastSuccessRequest != null &&
|
||||||
29 > TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - lastSuccessRequest.getTime());
|
5 > TimeUnit.MILLISECONDS.toMinutes(new Date().getTime() - lastSuccessRequest.getTime());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ public class Client {
|
|||||||
return getPageByUrl(url, loginBefore, null);
|
return getPageByUrl(url, loginBefore, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Document getPageByUrl(String url, boolean loginBefore, Map<String, String> cookies) throws IOException, VulcanException {
|
public synchronized Document getPageByUrl(String url, boolean loginBefore, Map<String, String> cookies) throws IOException, VulcanException {
|
||||||
if (loginBefore) {
|
if (loginBefore) {
|
||||||
login();
|
login();
|
||||||
}
|
}
|
||||||
@ -128,7 +127,7 @@ public class Client {
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Document postPageByUrl(String url, String[][] params) throws IOException, VulcanException {
|
public synchronized Document postPageByUrl(String url, String[][] params) throws IOException, VulcanException {
|
||||||
Connection connection = Jsoup.connect(getFilledUrl(url));
|
Connection connection = Jsoup.connect(getFilledUrl(url));
|
||||||
|
|
||||||
for (String[] data : params) {
|
for (String[] data : params) {
|
||||||
@ -143,6 +142,8 @@ public class Client {
|
|||||||
|
|
||||||
this.cookies.addItems(response.cookies());
|
this.cookies.addItems(response.cookies());
|
||||||
|
|
||||||
|
response.bufferUp(); // fixes cert parsing issues #109
|
||||||
|
|
||||||
return checkForErrors(response.parse());
|
return checkForErrors(response.parse());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,8 +195,8 @@ public class Client {
|
|||||||
throw new NotLoggedInErrorException(singIn);
|
throw new NotLoggedInErrorException(singIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("Błąd strony".equals(title)) {
|
if (title.startsWith("Błąd")) {
|
||||||
throw new VulcanException("Nieznany błąd");
|
throw new NotLoggedInErrorException(title + " " + doc.selectFirst("p, body"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
|
@ -106,7 +106,11 @@ public class StudentAndParent implements SnP {
|
|||||||
|
|
||||||
Document doc = client.getPageByUrl(getBaseUrl() + url, true, cookies);
|
Document doc = client.getPageByUrl(getBaseUrl() + url, true, cookies);
|
||||||
|
|
||||||
if ("Witryna ucznia i rodzica – Strona główna".equals(doc.select("title").first().text())) {
|
if (!doc.title().startsWith("Witryna ucznia i rodzica")) {
|
||||||
|
throw new VulcanException("Expected SnP page, got page with title: " + doc.title());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.title().endsWith("Strona główna")) {
|
||||||
throw new VulcanException("Sesja została nieprawidłowo zainicjowana");
|
throw new VulcanException("Sesja została nieprawidłowo zainicjowana");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class AttendanceTable {
|
|||||||
for (int i = 1; i < size; i++) {
|
for (int i = 1; i < size; i++) {
|
||||||
Lesson lesson = new Lesson();
|
Lesson lesson = new Lesson();
|
||||||
lesson.setDate(days.get(i - 1).getDate());
|
lesson.setDate(days.get(i - 1).getDate());
|
||||||
lesson.setNumber(hours.get(0).text());
|
lesson.setNumber(Integer.valueOf(hours.get(0).text()));
|
||||||
|
|
||||||
addLessonDetails(lesson, hours.get(i));
|
addLessonDetails(lesson, hours.get(i));
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ package io.github.wulkanowy.api.generic;
|
|||||||
|
|
||||||
public class Lesson {
|
public class Lesson {
|
||||||
|
|
||||||
private String number = "";
|
private int number = 0;
|
||||||
|
|
||||||
private String subject = "";
|
private String subject = "";
|
||||||
|
|
||||||
@ -48,12 +48,13 @@ public class Lesson {
|
|||||||
|
|
||||||
private boolean isExemption = false;
|
private boolean isExemption = false;
|
||||||
|
|
||||||
public String getNumber() {
|
public int getNumber() {
|
||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNumber(String number) {
|
public Lesson setNumber(int number) {
|
||||||
this.number = number;
|
this.number = number;
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getSubject() {
|
public String getSubject() {
|
||||||
|
@ -56,7 +56,7 @@ public class GradesList {
|
|||||||
String descriptions = row.select("td:nth-child(3)").text();
|
String descriptions = row.select("td:nth-child(3)").text();
|
||||||
|
|
||||||
String symbol = descriptions.split(", ")[0];
|
String symbol = descriptions.split(", ")[0];
|
||||||
String description = descriptions.replaceFirst(symbol, "").replaceFirst(", ", "");
|
String description = descriptions.replaceFirst(Pattern.quote(symbol), "").replaceFirst(", ", "");
|
||||||
String color = getColor(row.select("td:nth-child(2) span.ocenaCzastkowa").attr("style"));
|
String color = getColor(row.select("td:nth-child(2) span.ocenaCzastkowa").attr("style"));
|
||||||
String date = formatDate(row.select("td:nth-child(5)").text());
|
String date = formatDate(row.select("td:nth-child(5)").text());
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import io.github.wulkanowy.api.VulcanException;
|
|||||||
|
|
||||||
public class Login {
|
public class Login {
|
||||||
|
|
||||||
private static final String LOGIN_PAGE_URL = "{schema}://cufs.{host}/{symbol}/Account/LogOn" +
|
static final String LOGIN_PAGE_URL = "{schema}://cufs.{host}/{symbol}/Account/LogOn" +
|
||||||
"?ReturnUrl=%2F{symbol}%2FFS%2FLS%3Fwa%3Dwsignin1.0%26wtrealm%3D" +
|
"?ReturnUrl=%2F{symbol}%2FFS%2FLS%3Fwa%3Dwsignin1.0%26wtrealm%3D" +
|
||||||
"{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx%26wctx%3D" +
|
"{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx%26wctx%3D" +
|
||||||
"{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx";
|
"{schema}%253a%252f%252fuonetplus.{host}%252f{symbol}%252fLoginEndpoint.aspx";
|
||||||
@ -36,27 +36,29 @@ public class Login {
|
|||||||
{"Password", password}
|
{"Password", password}
|
||||||
};
|
};
|
||||||
|
|
||||||
String nextUrl = LOGIN_PAGE_URL;
|
Document nextDoc = sendCredentialsData(credentials, LOGIN_PAGE_URL);
|
||||||
Document loginPage = client.getPageByUrl(nextUrl, false);
|
|
||||||
|
|
||||||
Element formFirst = loginPage.select("#form1").first();
|
Element errorMessage = nextDoc.selectFirst(".ErrorMessage, #ErrorTextLabel");
|
||||||
if (null != formFirst) { // on adfs login
|
|
||||||
Document formSecond = client.postPageByUrl(
|
|
||||||
formFirst.attr("abs:action"),
|
|
||||||
getFormStateParams(formFirst, "", "")
|
|
||||||
);
|
|
||||||
credentials = getFormStateParams(formSecond, email, password);
|
|
||||||
nextUrl = formSecond.select("#form1").first().attr("abs:action");
|
|
||||||
}
|
|
||||||
|
|
||||||
Document html = client.postPageByUrl(nextUrl, credentials);
|
|
||||||
|
|
||||||
Element errorMessage = html.select(".ErrorMessage, #ErrorTextLabel").first();
|
|
||||||
if (null != errorMessage) {
|
if (null != errorMessage) {
|
||||||
throw new BadCredentialsException(errorMessage.text());
|
throw new BadCredentialsException(errorMessage.text());
|
||||||
}
|
}
|
||||||
|
|
||||||
return html;
|
return nextDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Document sendCredentialsData(String[][] credentials, String nextUrl) throws IOException, VulcanException {
|
||||||
|
Element formFirst = client.getPageByUrl(nextUrl, false).selectFirst("#form1");
|
||||||
|
|
||||||
|
if (null != formFirst) { // only on adfs login
|
||||||
|
Document formSecond = client.postPageByUrl(
|
||||||
|
formFirst.attr("abs:action"),
|
||||||
|
getFormStateParams(formFirst, "", "")
|
||||||
|
);
|
||||||
|
credentials = getFormStateParams(formSecond, credentials[0][1], credentials[1][1]);
|
||||||
|
nextUrl = formSecond.selectFirst("#form1").attr("abs:action");
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.postPageByUrl(nextUrl, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String[][] getFormStateParams(Element form, String email, String password) {
|
private String[][] getFormStateParams(Element form, String email, String password) {
|
||||||
@ -75,16 +77,13 @@ public class Login {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException {
|
String sendCertificate(Document doc, String defaultSymbol) throws IOException, VulcanException {
|
||||||
String certificate = doc.select("input[name=wresult]").val();
|
client.setSymbol(findSymbol(defaultSymbol, doc.select("input[name=wresult]").val()));
|
||||||
|
|
||||||
String symbol = findSymbol(defaultSymbol, certificate);
|
|
||||||
client.setSymbol(symbol);
|
|
||||||
|
|
||||||
Document targetDoc = sendCertData(doc);
|
Document targetDoc = sendCertData(doc);
|
||||||
String title = targetDoc.select("title").text();
|
String title = targetDoc.title();
|
||||||
|
|
||||||
if ("Working...".equals(title)) { // on adfs login
|
if ("Working...".equals(title)) { // on adfs login
|
||||||
title = sendCertData(targetDoc).select("title").text();
|
title = sendCertData(targetDoc).title();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("Logowanie".equals(title)) {
|
if ("Logowanie".equals(title)) {
|
||||||
@ -95,7 +94,7 @@ public class Login {
|
|||||||
throw new LoginErrorException("Expected page title `UONET+`, got " + title);
|
throw new LoginErrorException("Expected page title `UONET+`, got " + title);
|
||||||
}
|
}
|
||||||
|
|
||||||
return symbol;
|
return client.getSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Document sendCertData(Document doc) throws IOException, VulcanException {
|
private Document sendCertData(Document doc) throws IOException, VulcanException {
|
||||||
@ -108,7 +107,7 @@ public class Login {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private String findSymbol(String symbol, String certificate) {
|
private String findSymbol(String symbol, String certificate) throws AccountPermissionException {
|
||||||
if ("Default".equals(symbol)) {
|
if ("Default".equals(symbol)) {
|
||||||
return findSymbolInCertificate(certificate);
|
return findSymbolInCertificate(certificate);
|
||||||
}
|
}
|
||||||
@ -116,15 +115,19 @@ public class Login {
|
|||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
String findSymbolInCertificate(String certificate) {
|
String findSymbolInCertificate(String certificate) throws AccountPermissionException {
|
||||||
Elements instances = Jsoup
|
Elements instances = Jsoup
|
||||||
.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser())
|
.parse(certificate.replaceAll(":", ""), "", Parser.xmlParser())
|
||||||
.select("[AttributeName=\"UserInstance\"] samlAttributeValue");
|
.select("[AttributeName=\"UserInstance\"] samlAttributeValue");
|
||||||
|
|
||||||
if (instances.isEmpty()) {
|
if (instances.isEmpty()) { // on adfs login
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instances.size() < 2) { // 1st index is always `Default`
|
||||||
|
throw new AccountPermissionException("First login detected, specify symbol");
|
||||||
|
}
|
||||||
|
|
||||||
return instances.get(1).text();
|
return instances.get(1).text();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ public class Timetable {
|
|||||||
lesson.setStartTime(startEndEnd[0]);
|
lesson.setStartTime(startEndEnd[0]);
|
||||||
lesson.setEndTime(startEndEnd[1]);
|
lesson.setEndTime(startEndEnd[1]);
|
||||||
lesson.setDate(days.get(i - 2).getDate());
|
lesson.setDate(days.get(i - 2).getDate());
|
||||||
lesson.setNumber(hours.get(0).text());
|
lesson.setNumber(Integer.valueOf(hours.get(0).text()));
|
||||||
|
|
||||||
addLessonDetails(lesson, hours.get(i).select("div"));
|
addLessonDetails(lesson, hours.get(i).select("div"));
|
||||||
|
|
||||||
@ -94,14 +94,18 @@ public class Timetable {
|
|||||||
moveWarningToLessonNode(e);
|
moveWarningToLessonNode(e);
|
||||||
|
|
||||||
switch (e.size()) {
|
switch (e.size()) {
|
||||||
|
case 1:
|
||||||
|
addLessonInfoFromElement(lesson, e.first());
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
Element span = e.last().select("span").first();
|
Element span = e.last().select("span").first();
|
||||||
if (span.hasClass(LessonTypes.CLASS_MOVED_OR_CANCELED)) {
|
if (span.hasClass(LessonTypes.CLASS_MOVED_OR_CANCELED)) {
|
||||||
lesson.setNewMovedInOrChanged(true);
|
lesson.setNewMovedInOrChanged(true);
|
||||||
lesson.setDescription("poprzednio: " + getLessonAndGroupInfoFromSpan(span)[0]);
|
lesson.setDescription("poprzednio: " + getLessonAndGroupInfoFromSpan(span)[0]);
|
||||||
|
addLessonInfoFromElement(lesson, e.first());
|
||||||
|
} else {
|
||||||
|
addLessonInfoFromElement(lesson, e.last());
|
||||||
}
|
}
|
||||||
case 1:
|
|
||||||
addLessonInfoFromElement(lesson, e.first());
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
addLessonInfoFromElement(lesson, e.get(1));
|
addLessonInfoFromElement(lesson, e.get(1));
|
||||||
@ -167,7 +171,8 @@ public class Timetable {
|
|||||||
lesson.setRoom(spans.get(5).text());
|
lesson.setRoom(spans.get(5).text());
|
||||||
lesson.setMovedOrCanceled(false);
|
lesson.setMovedOrCanceled(false);
|
||||||
lesson.setNewMovedInOrChanged(true);
|
lesson.setNewMovedInOrChanged(true);
|
||||||
lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")")
|
lesson.setDescription(StringUtils.defaultString(StringUtils.substringBetween(
|
||||||
|
spans.last().text(), "(", ")"), spans.last().text())
|
||||||
+ " (poprzednio: " + spans.get(0).text() + ")");
|
+ " (poprzednio: " + spans.get(0).text() + ")");
|
||||||
} else if (9 == spans.size()) {
|
} else if (9 == spans.size()) {
|
||||||
String[] subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans.get(4));
|
String[] subjectAndGroupInfo = getLessonAndGroupInfoFromSpan(spans.get(4));
|
||||||
@ -178,13 +183,15 @@ public class Timetable {
|
|||||||
lesson.setMovedOrCanceled(false);
|
lesson.setMovedOrCanceled(false);
|
||||||
lesson.setNewMovedInOrChanged(true);
|
lesson.setNewMovedInOrChanged(true);
|
||||||
lesson.setDivisionIntoGroups(true);
|
lesson.setDivisionIntoGroups(true);
|
||||||
lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")")
|
lesson.setDescription(StringUtils.defaultString(StringUtils.substringBetween(
|
||||||
|
spans.last().text(), "(", ")"), spans.last().text())
|
||||||
+ " (poprzednio: " + getLessonAndGroupInfoFromSpan(spans.get(0))[0] + ")");
|
+ " (poprzednio: " + getLessonAndGroupInfoFromSpan(spans.get(0))[0] + ")");
|
||||||
} else if (4 <= spans.size()) {
|
} else if (4 <= spans.size()) {
|
||||||
lesson.setSubject(spans.get(0).text());
|
lesson.setSubject(spans.get(0).text());
|
||||||
lesson.setTeacher(spans.get(1).text());
|
lesson.setTeacher(spans.get(1).text());
|
||||||
lesson.setRoom(spans.get(2).text());
|
lesson.setRoom(spans.get(2).text());
|
||||||
lesson.setDescription(StringUtils.substringBetween(spans.last().text(), "(", ")"));
|
lesson.setDescription(StringUtils.defaultString(StringUtils.substringBetween(
|
||||||
|
spans.last().text(), "(", ")"), spans.last().text()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +219,8 @@ public class Timetable {
|
|||||||
|
|
||||||
return new String[]{
|
return new String[]{
|
||||||
span.text().replace(" " + groupName, ""),
|
span.text().replace(" " + groupName, ""),
|
||||||
StringUtils.substringBetween(groupName, "[", "]")
|
StringUtils.defaultString(StringUtils.substringBetween(
|
||||||
|
groupName, "[", "]"), groupName)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getAllTest() throws Exception {
|
public void getAllTest() throws Exception {
|
||||||
Assert.assertEquals(6, filled.getAll().size()); // 2 items are skipped
|
Assert.assertEquals(7, filled.getAll().size()); // 2 items are skipped
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -60,6 +60,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertEquals("BW3", list.get(3).getSymbol());
|
Assert.assertEquals("BW3", list.get(3).getSymbol());
|
||||||
Assert.assertEquals("STR", list.get(4).getSymbol());
|
Assert.assertEquals("STR", list.get(4).getSymbol());
|
||||||
Assert.assertEquals("K", list.get(5).getSymbol());
|
Assert.assertEquals("K", list.get(5).getSymbol());
|
||||||
|
Assert.assertEquals("+Odp", list.get(6).getSymbol());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -70,6 +71,7 @@ public class GradesListTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertEquals("Writing", list.get(3).getDescription());
|
Assert.assertEquals("Writing", list.get(3).getDescription());
|
||||||
Assert.assertEquals("", list.get(4).getDescription());
|
Assert.assertEquals("", list.get(4).getDescription());
|
||||||
Assert.assertEquals("Kordian", list.get(5).getDescription());
|
Assert.assertEquals("Kordian", list.get(5).getDescription());
|
||||||
|
Assert.assertEquals("Kordian", list.get(6).getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -34,6 +34,10 @@ public class LoginTest {
|
|||||||
Client client = getClient("Logowanie-success.html");
|
Client client = getClient("Logowanie-success.html");
|
||||||
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean()))
|
Mockito.when(client.getPageByUrl(Mockito.anyString(), Mockito.anyBoolean()))
|
||||||
.thenReturn(getFixtureAsDocument("Logowanie-error.html"));
|
.thenReturn(getFixtureAsDocument("Logowanie-error.html"));
|
||||||
|
Mockito.when(client.postPageByUrl(Mockito.eq(Login.LOGIN_PAGE_URL), Mockito.any(String[][].class)))
|
||||||
|
.thenReturn(getFixtureAsDocument("Logowanie-certyfikat.html"));
|
||||||
|
Mockito.doCallRealMethod().when(client).setSymbol(Mockito.anyString());
|
||||||
|
Mockito.when(client.getSymbol()).thenCallRealMethod();
|
||||||
Login login = new Login(client);
|
Login login = new Login(client);
|
||||||
|
|
||||||
Assert.assertEquals("d123", login.login("a@a", "pswd", "d123"));
|
Assert.assertEquals("d123", login.login("a@a", "pswd", "d123"));
|
||||||
@ -57,22 +61,31 @@ public class LoginTest {
|
|||||||
Login login = new Login(client);
|
Login login = new Login(client);
|
||||||
|
|
||||||
Assert.assertEquals(
|
Assert.assertEquals(
|
||||||
getFixtureAsString("cert-stock.xml").replaceAll("\\s+",""),
|
getFixtureAsString("cert-stock.xml").replaceAll("\\s+", ""),
|
||||||
login.sendCredentials("a@a", "passwd").select("input[name=wresult]").attr("value").replaceAll("\\s+","")
|
login.sendCredentials("a@a", "passwd")
|
||||||
|
.select("input[name=wresult]")
|
||||||
|
.attr("value")
|
||||||
|
.replaceAll("\\s+", "")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendCertificateNotDefaultSymbolSuccessTest() throws Exception {
|
public void sendCertificateNotDefaultSymbolSuccessTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-success.html"));
|
Client client = getClient("Logowanie-success.html");
|
||||||
|
Mockito.doCallRealMethod().when(client).setSymbol(Mockito.anyString());
|
||||||
|
Mockito.when(client.getSymbol()).thenCallRealMethod();
|
||||||
|
Login login = new Login(client);
|
||||||
|
|
||||||
Assert.assertEquals("wulkanowyschool321",
|
Assert.assertEquals("wulkanowyschool321", login.sendCertificate(
|
||||||
login.sendCertificate(new Document(""), "wulkanowyschool321"));
|
getFixtureAsDocument("Logowanie-certyfikat.html"), "wulkanowyschool321"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendCertificateDefaultSymbolSuccessTest() throws Exception {
|
public void sendCertificateDefaultSymbolSuccessTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-success.html"));
|
Client client = getClient("Logowanie-success.html");
|
||||||
|
Mockito.doCallRealMethod().when(client).setSymbol(Mockito.anyString());
|
||||||
|
Mockito.when(client.getSymbol()).thenCallRealMethod();
|
||||||
|
Login login = new Login(client);
|
||||||
|
|
||||||
Assert.assertEquals("demo12345",
|
Assert.assertEquals("demo12345",
|
||||||
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "Default"));
|
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "Default"));
|
||||||
@ -80,16 +93,18 @@ public class LoginTest {
|
|||||||
|
|
||||||
@Test(expected = AccountPermissionException.class)
|
@Test(expected = AccountPermissionException.class)
|
||||||
public void sendCertificateAccountPermissionTest() throws Exception {
|
public void sendCertificateAccountPermissionTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-brak-dostepu.html"));
|
Client client = getClient("Logowanie-brak-dostepu.html");
|
||||||
|
|
||||||
login.sendCertificate(getFixtureAsDocument("cert-stock.xml"), "demo123");
|
Login login = new Login(client);
|
||||||
|
|
||||||
|
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "demo123");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = LoginErrorException.class)
|
@Test(expected = LoginErrorException.class)
|
||||||
public void sendCertificateLoginErrorTest() throws Exception {
|
public void sendCertificateLoginErrorTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-certyfikat.html")); // change to other document
|
Login login = new Login(getClient("Logowanie-certyfikat.html")); // change to other document
|
||||||
|
|
||||||
login.sendCertificate(getFixtureAsDocument("cert-stock.xml"), "demo123");
|
login.sendCertificate(getFixtureAsDocument("Logowanie-certyfikat.html"), "demo123");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -101,10 +116,10 @@ public class LoginTest {
|
|||||||
Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate));
|
Assert.assertEquals("demo12345", login.findSymbolInCertificate(certificate));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = AccountPermissionException.class)
|
||||||
public void findSymbolInInvalidCertificateTest() throws Exception {
|
public void findSymbolInCertificateWithoutSecondInstanceTest() throws Exception {
|
||||||
Login login = new Login(getClient("Logowanie-certyfikat.html"));
|
Login login = new Login(getClient("Logowanie-certyfikat.html"));
|
||||||
|
|
||||||
Assert.assertEquals("", login.findSymbolInCertificate("<xml></xml>")); // change to real cert with empty symbols
|
login.findSymbolInCertificate(getFixtureAsString("cert-no-symbols.xml"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,11 +83,11 @@ public class TimetableTest extends StudentAndParentTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getLessonNumberTest() throws Exception {
|
public void getLessonNumberTest() throws Exception {
|
||||||
Assert.assertEquals("2", std.getWeekTable().getDay(0).getLesson(1).getNumber());
|
Assert.assertEquals(2, std.getWeekTable().getDay(0).getLesson(1).getNumber());
|
||||||
Assert.assertEquals("5", std.getWeekTable().getDay(2).getLesson(4).getNumber());
|
Assert.assertEquals(5, std.getWeekTable().getDay(2).getLesson(4).getNumber());
|
||||||
Assert.assertEquals("0", full.getWeekTable().getDay(0).getLesson(0).getNumber());
|
Assert.assertEquals(0, full.getWeekTable().getDay(0).getLesson(0).getNumber());
|
||||||
Assert.assertEquals("13", full.getWeekTable().getDay(4).getLesson(13).getNumber());
|
Assert.assertEquals(13, full.getWeekTable().getDay(4).getLesson(13).getNumber());
|
||||||
Assert.assertEquals("3", holidays.getWeekTable().getDay(3).getLesson(3).getNumber());
|
Assert.assertEquals(3, holidays.getWeekTable().getDay(3).getLesson(3).getNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -151,6 +151,7 @@ public class TimetableTest extends StudentAndParentTestCase {
|
|||||||
Assert.assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getWeekTable().getDay(3).getLesson(1).getDescription());
|
Assert.assertEquals("zastępstwo (poprzednio: Wychowanie fizyczne)", full.getWeekTable().getDay(3).getLesson(1).getDescription());
|
||||||
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(0).getDescription());
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(0).getDescription());
|
||||||
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
||||||
|
Assert.assertEquals("bez nawiasów (poprzednio: Religia)", full.getWeekTable().getDay(4).getLesson(3).getDescription());
|
||||||
Assert.assertEquals("poprzednio: Wychowanie fizyczne", full.getWeekTable().getDay(4).getLesson(2).getDescription());
|
Assert.assertEquals("poprzednio: Wychowanie fizyczne", full.getWeekTable().getDay(4).getLesson(2).getDescription());
|
||||||
Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription());
|
Assert.assertEquals("egzamin", full.getWeekTable().getDay(3).getLesson(0).getDescription());
|
||||||
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
Assert.assertEquals("", full.getWeekTable().getDay(4).getLesson(1).getDescription());
|
||||||
|
@ -100,6 +100,14 @@
|
|||||||
<td>06.02.2017</td>
|
<td>06.02.2017</td>
|
||||||
<td>Amelia Stępień</td>
|
<td>Amelia Stępień</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Język polski</td>
|
||||||
|
<td class="break-word"><span class="ocenaCzastkowa" style="color:#6ECD07;">5</span></td>
|
||||||
|
<td class="break-word">+Odp, Kordian</td>
|
||||||
|
<td>5,00</td>
|
||||||
|
<td>11.05.2017</td>
|
||||||
|
<td>Amelia Stępień</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</main>
|
</main>
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="MainDiv">
|
<div id="MainDiv">
|
||||||
<form>
|
<form>
|
||||||
|
<div class="LogOnBoard">
|
||||||
|
<h1 id="h1Default">Logowanie</h1>
|
||||||
|
</div>
|
||||||
<div class="ErrorMessage center">
|
<div class="ErrorMessage center">
|
||||||
Zła nazwa użytkownika lub hasło
|
Zła nazwa użytkownika lub hasło
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
<trust:RequestSecurityTokenResponseCollection xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
|
||||||
|
<trust:RequestSecurityTokenResponse Context="https://uonetplus.fakelog.cf/Default/LoginEndpoint.aspx">
|
||||||
|
<trust:RequestedSecurityToken>
|
||||||
|
<saml:Assertion AssertionID="_12345678-1234-1234-1234-1234567890ab" IssueInstant="2017-10-18T22:00:29.006Z" Issuer="CUFSTokenService" MajorVersion="1" MinorVersion="1" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
|
||||||
|
<saml:AttributeStatement>
|
||||||
|
<saml:Attribute AttributeName="UserInstance" AttributeNamespace="http://schemas.fakelog.cf/ws/identity/claims">
|
||||||
|
<saml:AttributeValue>Default</saml:AttributeValue>
|
||||||
|
</saml:Attribute>
|
||||||
|
</saml:AttributeStatement>
|
||||||
|
</saml:Assertion>
|
||||||
|
</trust:RequestedSecurityToken>
|
||||||
|
</trust:RequestSecurityTokenResponse>
|
||||||
|
</trust:RequestSecurityTokenResponseCollection>
|
@ -3,6 +3,40 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Witryna ucznia i rodzica – Plan lekcji</title>
|
<title>Witryna ucznia i rodzica – Plan lekcji</title>
|
||||||
|
<style>
|
||||||
|
table, th, td {
|
||||||
|
border: 1px solid;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
table td > div:not(:last-child) {
|
||||||
|
border-bottom: 5px solid silver;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
table td div span:nth-child(1) {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
table span {
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
.x-treelabel-ppl {
|
||||||
|
background: #99f;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.x-treelabel-rlz {
|
||||||
|
background: #f3a;
|
||||||
|
}
|
||||||
|
.x-treelabel-inv {
|
||||||
|
background: #f00;
|
||||||
|
}
|
||||||
|
.x-treelabel-zas {
|
||||||
|
background: #0f0;
|
||||||
|
}
|
||||||
|
table span:not([class]),
|
||||||
|
table span[class=""] {
|
||||||
|
background: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main class="mainContainer">
|
<main class="mainContainer">
|
||||||
@ -238,7 +272,17 @@
|
|||||||
<span></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td>
|
||||||
|
<div>
|
||||||
|
<span class="x-treelabel-inv">Religia</span>
|
||||||
|
<span class="x-treelabel-inv">Cyranka Krystian</span>
|
||||||
|
<span class="x-treelabel-inv">3</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-zas">Wychowanie do życia w rodzinie</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-zas">Nowak Jadwiga</span>
|
||||||
|
<span class="x-treelabel-ppl x-treelabel-zas">3</span>
|
||||||
|
<span class="x-treelabel-rlz">bez nawiasów</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>4</td>
|
<td>4</td>
|
||||||
|
@ -41,8 +41,8 @@ android {
|
|||||||
testApplicationId "io.github.tests.wulkanowy"
|
testApplicationId "io.github.tests.wulkanowy"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 8
|
versionCode 11
|
||||||
versionName "0.4.0"
|
versionName "0.4.3"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
playAccountConfig = playAccountConfigs.defaultAccountConfig
|
playAccountConfig = playAccountConfigs.defaultAccountConfig
|
||||||
@ -91,7 +91,7 @@ play {
|
|||||||
}
|
}
|
||||||
|
|
||||||
greendao {
|
greendao {
|
||||||
schemaVersion 26
|
schemaVersion 28
|
||||||
generateTests = true
|
generateTests = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ import io.github.wulkanowy.api.Vulcan;
|
|||||||
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
|
import io.github.wulkanowy.data.db.dao.entities.DaoMaster;
|
||||||
import io.github.wulkanowy.data.db.dao.migrations.Migration23;
|
import io.github.wulkanowy.data.db.dao.migrations.Migration23;
|
||||||
import io.github.wulkanowy.data.db.dao.migrations.Migration26;
|
import io.github.wulkanowy.data.db.dao.migrations.Migration26;
|
||||||
|
import io.github.wulkanowy.data.db.dao.migrations.Migration27;
|
||||||
|
import io.github.wulkanowy.data.db.dao.migrations.Migration28;
|
||||||
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||||
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
import io.github.wulkanowy.di.annotations.ApplicationContext;
|
||||||
import io.github.wulkanowy.di.annotations.DatabaseInfo;
|
import io.github.wulkanowy.di.annotations.DatabaseInfo;
|
||||||
@ -76,6 +78,8 @@ public class DbHelper extends DaoMaster.OpenHelper {
|
|||||||
List<Migration> migrations = new ArrayList<>();
|
List<Migration> migrations = new ArrayList<>();
|
||||||
migrations.add(new Migration23());
|
migrations.add(new Migration23());
|
||||||
migrations.add(new Migration26());
|
migrations.add(new Migration26());
|
||||||
|
migrations.add(new Migration27());
|
||||||
|
migrations.add(new Migration28());
|
||||||
|
|
||||||
// Sorting just to be safe, in case other people add migrations in the wrong order.
|
// Sorting just to be safe, in case other people add migrations in the wrong order.
|
||||||
Comparator<Migration> migrationComparator = new Comparator<Migration>() {
|
Comparator<Migration> migrationComparator = new Comparator<Migration>() {
|
||||||
|
@ -5,6 +5,7 @@ import org.greenrobot.greendao.annotation.Entity;
|
|||||||
import org.greenrobot.greendao.annotation.Generated;
|
import org.greenrobot.greendao.annotation.Generated;
|
||||||
import org.greenrobot.greendao.annotation.Id;
|
import org.greenrobot.greendao.annotation.Id;
|
||||||
import org.greenrobot.greendao.annotation.Index;
|
import org.greenrobot.greendao.annotation.Index;
|
||||||
|
import org.greenrobot.greendao.annotation.OrderBy;
|
||||||
import org.greenrobot.greendao.annotation.Property;
|
import org.greenrobot.greendao.annotation.Property;
|
||||||
import org.greenrobot.greendao.annotation.ToMany;
|
import org.greenrobot.greendao.annotation.ToMany;
|
||||||
|
|
||||||
@ -35,9 +36,11 @@ public class Day {
|
|||||||
@Property(nameInDb = "free_day_name")
|
@Property(nameInDb = "free_day_name")
|
||||||
private String freeDayName = "";
|
private String freeDayName = "";
|
||||||
|
|
||||||
|
@OrderBy("number ASC")
|
||||||
@ToMany(referencedJoinProperty = "dayId")
|
@ToMany(referencedJoinProperty = "dayId")
|
||||||
private List<TimetableLesson> timetableLessons;
|
private List<TimetableLesson> timetableLessons;
|
||||||
|
|
||||||
|
@OrderBy("number ASC")
|
||||||
@ToMany(referencedJoinProperty = "dayId")
|
@ToMany(referencedJoinProperty = "dayId")
|
||||||
private List<AttendanceLesson> attendanceLessons;
|
private List<AttendanceLesson> attendanceLessons;
|
||||||
|
|
||||||
@ -50,9 +53,7 @@ public class Day {
|
|||||||
@Generated(hash = 2040040024)
|
@Generated(hash = 2040040024)
|
||||||
private transient DaoSession daoSession;
|
private transient DaoSession daoSession;
|
||||||
|
|
||||||
/**
|
/** Used for active entity operations. */
|
||||||
* Used for active entity operations.
|
|
||||||
*/
|
|
||||||
@Generated(hash = 312167767)
|
@Generated(hash = 312167767)
|
||||||
private transient DayDao myDao;
|
private transient DayDao myDao;
|
||||||
|
|
||||||
@ -185,6 +186,36 @@ public class Day {
|
|||||||
attendanceLessons = null;
|
attendanceLessons = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To-many relationship, resolved on first access (and after reset).
|
||||||
|
* Changes to to-many relations are not persisted, make changes to the target entity.
|
||||||
|
*/
|
||||||
|
@Generated(hash = 1231531946)
|
||||||
|
public List<Exam> getExams() {
|
||||||
|
if (exams == null) {
|
||||||
|
final DaoSession daoSession = this.daoSession;
|
||||||
|
if (daoSession == null) {
|
||||||
|
throw new DaoException("Entity is detached from DAO context");
|
||||||
|
}
|
||||||
|
ExamDao targetDao = daoSession.getExamDao();
|
||||||
|
List<Exam> examsNew = targetDao._queryDay_Exams(id);
|
||||||
|
synchronized (this) {
|
||||||
|
if (exams == null) {
|
||||||
|
exams = examsNew;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets a to-many relationship, making the next get call to query for a fresh result.
|
||||||
|
*/
|
||||||
|
@Generated(hash = 841969952)
|
||||||
|
public synchronized void resetExams() {
|
||||||
|
exams = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
|
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
|
||||||
* Entity must attached to an entity context.
|
* Entity must attached to an entity context.
|
||||||
@ -221,40 +252,12 @@ public class Day {
|
|||||||
myDao.update(this);
|
myDao.update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* To-many relationship, resolved on first access (and after reset).
|
|
||||||
* Changes to to-many relations are not persisted, make changes to the target entity.
|
|
||||||
*/
|
|
||||||
@Generated(hash = 1231531946)
|
|
||||||
public List<Exam> getExams() {
|
|
||||||
if (exams == null) {
|
|
||||||
final DaoSession daoSession = this.daoSession;
|
|
||||||
if (daoSession == null) {
|
|
||||||
throw new DaoException("Entity is detached from DAO context");
|
|
||||||
}
|
|
||||||
ExamDao targetDao = daoSession.getExamDao();
|
|
||||||
List<Exam> examsNew = targetDao._queryDay_Exams(id);
|
|
||||||
synchronized (this) {
|
|
||||||
if (exams == null) {
|
|
||||||
exams = examsNew;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exams;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets a to-many relationship, making the next get call to query for a fresh result.
|
|
||||||
*/
|
|
||||||
@Generated(hash = 841969952)
|
|
||||||
public synchronized void resetExams() {
|
|
||||||
exams = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** called by internal mechanisms, do not call yourself. */
|
/** called by internal mechanisms, do not call yourself. */
|
||||||
@Generated(hash = 1409317752)
|
@Generated(hash = 1409317752)
|
||||||
public void __setDaoSession(DaoSession daoSession) {
|
public void __setDaoSession(DaoSession daoSession) {
|
||||||
this.daoSession = daoSession;
|
this.daoSession = daoSession;
|
||||||
myDao = daoSession != null ? daoSession.getDayDao() : null;
|
myDao = daoSession != null ? daoSession.getDayDao() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,15 @@ import org.greenrobot.greendao.DaoException;
|
|||||||
import org.greenrobot.greendao.annotation.Entity;
|
import org.greenrobot.greendao.annotation.Entity;
|
||||||
import org.greenrobot.greendao.annotation.Generated;
|
import org.greenrobot.greendao.annotation.Generated;
|
||||||
import org.greenrobot.greendao.annotation.Id;
|
import org.greenrobot.greendao.annotation.Id;
|
||||||
|
import org.greenrobot.greendao.annotation.Index;
|
||||||
import org.greenrobot.greendao.annotation.Property;
|
import org.greenrobot.greendao.annotation.Property;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
nameInDb = "Exams",
|
nameInDb = "Exams",
|
||||||
active = true
|
active = true,
|
||||||
|
indexes = {@Index(value = "dayId,entryDate,subjectAndGroup,type,teacher", unique = true)}
|
||||||
)
|
)
|
||||||
|
|
||||||
public class Exam implements Serializable {
|
public class Exam implements Serializable {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package io.github.wulkanowy.data.db.dao.entities;
|
package io.github.wulkanowy.data.db.dao.entities;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||||
import org.greenrobot.greendao.DaoException;
|
import org.greenrobot.greendao.DaoException;
|
||||||
import org.greenrobot.greendao.annotation.Entity;
|
import org.greenrobot.greendao.annotation.Entity;
|
||||||
import org.greenrobot.greendao.annotation.Generated;
|
import org.greenrobot.greendao.annotation.Generated;
|
||||||
@ -12,7 +14,7 @@ import java.io.Serializable;
|
|||||||
@Entity(
|
@Entity(
|
||||||
nameInDb = "TimetableLessons",
|
nameInDb = "TimetableLessons",
|
||||||
active = true,
|
active = true,
|
||||||
indexes = {@Index(value = "dayId,date,startTime,endTime", unique = true)}
|
indexes = {@Index(value = "dayId,date,number,startTime,endTime", unique = true)}
|
||||||
)
|
)
|
||||||
public class TimetableLesson implements Serializable {
|
public class TimetableLesson implements Serializable {
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ public class TimetableLesson implements Serializable {
|
|||||||
private Long dayId;
|
private Long dayId;
|
||||||
|
|
||||||
@Property(nameInDb = "number")
|
@Property(nameInDb = "number")
|
||||||
private String number;
|
private int number = 0;
|
||||||
|
|
||||||
@Property(nameInDb = "subject")
|
@Property(nameInDb = "subject")
|
||||||
private String subject = "";
|
private String subject = "";
|
||||||
@ -75,18 +77,15 @@ public class TimetableLesson implements Serializable {
|
|||||||
@Generated(hash = 2040040024)
|
@Generated(hash = 2040040024)
|
||||||
private transient DaoSession daoSession;
|
private transient DaoSession daoSession;
|
||||||
|
|
||||||
/**
|
/** Used for active entity operations. */
|
||||||
* Used for active entity operations.
|
|
||||||
*/
|
|
||||||
@Generated(hash = 1119360138)
|
@Generated(hash = 1119360138)
|
||||||
private transient TimetableLessonDao myDao;
|
private transient TimetableLessonDao myDao;
|
||||||
|
|
||||||
@Generated(hash = 1955911128)
|
@Generated(hash = 1665905034)
|
||||||
public TimetableLesson(Long id, Long dayId, String number, String subject,
|
public TimetableLesson(Long id, Long dayId, int number, String subject, String teacher,
|
||||||
String teacher, String room, String description, String group,
|
String room, String description, String group, String startTime, String endTime,
|
||||||
String startTime, String endTime, String date, boolean empty,
|
String date, boolean empty, boolean divisionIntoGroups, boolean planning,
|
||||||
boolean divisionIntoGroups, boolean planning, boolean realized,
|
boolean realized, boolean movedOrCanceled, boolean newMovedInOrChanged) {
|
||||||
boolean movedOrCanceled, boolean newMovedInOrChanged) {
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.dayId = dayId;
|
this.dayId = dayId;
|
||||||
this.number = number;
|
this.number = number;
|
||||||
@ -109,7 +108,7 @@ public class TimetableLesson implements Serializable {
|
|||||||
@Generated(hash = 1878030142)
|
@Generated(hash = 1878030142)
|
||||||
public TimetableLesson() {
|
public TimetableLesson() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
@ -127,11 +126,11 @@ public class TimetableLesson implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNumber() {
|
public int getNumber() {
|
||||||
return this.number;
|
return this.number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimetableLesson setNumber(String number) {
|
public TimetableLesson setNumber(int number) {
|
||||||
this.number = number;
|
this.number = number;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -262,6 +261,32 @@ public class TimetableLesson implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
TimetableLesson lesson = (TimetableLesson) o;
|
||||||
|
|
||||||
|
return new EqualsBuilder()
|
||||||
|
.append(number, lesson.number)
|
||||||
|
.append(startTime, lesson.startTime)
|
||||||
|
.append(endTime, lesson.endTime)
|
||||||
|
.append(date, lesson.date)
|
||||||
|
.isEquals();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return new HashCodeBuilder(17, 37)
|
||||||
|
.append(number)
|
||||||
|
.append(startTime)
|
||||||
|
.append(endTime)
|
||||||
|
.append(date)
|
||||||
|
.toHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
|
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
|
||||||
* Entity must attached to an entity context.
|
* Entity must attached to an entity context.
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao.migrations;
|
||||||
|
|
||||||
|
import org.greenrobot.greendao.database.Database;
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Vulcan;
|
||||||
|
import io.github.wulkanowy.data.db.dao.DbHelper;
|
||||||
|
import io.github.wulkanowy.data.db.dao.entities.ExamDao;
|
||||||
|
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||||
|
|
||||||
|
public class Migration27 implements DbHelper.Migration {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getVersion() {
|
||||||
|
return 27;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runMigration(Database db, SharedPrefContract sharedPref, Vulcan vulcan) throws Exception {
|
||||||
|
ExamDao.dropTable(db, true);
|
||||||
|
ExamDao.createTable(db, true);
|
||||||
|
|
||||||
|
db.execSQL("UPDATE Weeks SET exams_synced = 0");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package io.github.wulkanowy.data.db.dao.migrations;
|
||||||
|
|
||||||
|
import org.greenrobot.greendao.database.Database;
|
||||||
|
|
||||||
|
import io.github.wulkanowy.api.Vulcan;
|
||||||
|
import io.github.wulkanowy.data.db.dao.DbHelper;
|
||||||
|
import io.github.wulkanowy.data.db.shared.SharedPrefContract;
|
||||||
|
|
||||||
|
public class Migration28 implements DbHelper.Migration {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getVersion() {
|
||||||
|
return 28;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runMigration(final Database db, final SharedPrefContract sharedPref, final Vulcan vulcan) throws Exception {
|
||||||
|
throw new Exception("No migrations");
|
||||||
|
}
|
||||||
|
}
|
@ -52,7 +52,7 @@ public class ResourcesRepository implements ResourcesContract {
|
|||||||
} else if (exception instanceof SocketTimeoutException) {
|
} else if (exception instanceof SocketTimeoutException) {
|
||||||
return resources.getString(R.string.generic_timeout_error);
|
return resources.getString(R.string.generic_timeout_error);
|
||||||
} else if (exception instanceof NotLoggedInErrorException || exception instanceof IOException) {
|
} else if (exception instanceof NotLoggedInErrorException || exception instanceof IOException) {
|
||||||
return resources.getString(R.string.login_denied_text);
|
return resources.getString(R.string.login_failed_text);
|
||||||
} else {
|
} else {
|
||||||
return exception.getMessage();
|
return exception.getMessage();
|
||||||
}
|
}
|
||||||
|
@ -118,12 +118,12 @@ public class AccountSync {
|
|||||||
daoSession.getSemesterDao().insertInTx(semesterList);
|
daoSession.getSemesterDao().insertInTx(semesterList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initLastUser() throws IOException, CryptoException {
|
public void initLastUser() throws CryptoException {
|
||||||
|
|
||||||
long userId = sharedPref.getCurrentUserId();
|
long userId = sharedPref.getCurrentUserId();
|
||||||
|
|
||||||
if (userId == 0) {
|
if (userId == 0) {
|
||||||
throw new IOException("Can't find saved user");
|
throw new NotRegisteredUserException("Can't find user id in SharedPreferences");
|
||||||
}
|
}
|
||||||
|
|
||||||
LogUtils.debug("Initialization current user id=" + userId);
|
LogUtils.debug("Initialization current user id=" + userId);
|
||||||
|
@ -135,6 +135,7 @@ public class ExamsSync {
|
|||||||
.where(ExamDao.Properties.DayId.eq(dayId),
|
.where(ExamDao.Properties.DayId.eq(dayId),
|
||||||
ExamDao.Properties.EntryDate.eq(examApi.getEntryDate()),
|
ExamDao.Properties.EntryDate.eq(examApi.getEntryDate()),
|
||||||
ExamDao.Properties.SubjectAndGroup.eq(examApi.getSubjectAndGroup()),
|
ExamDao.Properties.SubjectAndGroup.eq(examApi.getSubjectAndGroup()),
|
||||||
|
ExamDao.Properties.Type.eq(examApi.getType()),
|
||||||
ExamDao.Properties.Teacher.eq(examApi.getTeacher()))
|
ExamDao.Properties.Teacher.eq(examApi.getTeacher()))
|
||||||
.unique();
|
.unique();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package io.github.wulkanowy.data.sync;
|
||||||
|
|
||||||
|
public class NotRegisteredUserException extends RuntimeException {
|
||||||
|
|
||||||
|
public NotRegisteredUserException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package io.github.wulkanowy.data.sync;
|
package io.github.wulkanowy.data.sync;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -125,6 +127,16 @@ public class TimetableSync {
|
|||||||
List<TimetableLesson> lessonsFromApiEntities = DataObjectConverter
|
List<TimetableLesson> lessonsFromApiEntities = DataObjectConverter
|
||||||
.lessonsToTimetableLessonsEntities(lessons);
|
.lessonsToTimetableLessonsEntities(lessons);
|
||||||
|
|
||||||
|
List<TimetableLesson> lessonsFromDbEntities = getLessonsFromDb(dayId);
|
||||||
|
|
||||||
|
if (!lessonsFromDbEntities.isEmpty()) {
|
||||||
|
List<TimetableLesson> lessonToRemove = new ArrayList<>(CollectionUtils.removeAll(lessonsFromDbEntities, lessonsFromApiEntities));
|
||||||
|
|
||||||
|
for (TimetableLesson timetableLesson : lessonToRemove) {
|
||||||
|
daoSession.getTimetableLessonDao().delete(timetableLesson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (TimetableLesson apiLessonEntity : lessonsFromApiEntities) {
|
for (TimetableLesson apiLessonEntity : lessonsFromApiEntities) {
|
||||||
TimetableLesson lessonFromDb = getLessonFromDb(apiLessonEntity, dayId);
|
TimetableLesson lessonFromDb = getLessonFromDb(apiLessonEntity, dayId);
|
||||||
|
|
||||||
@ -148,4 +160,8 @@ public class TimetableSync {
|
|||||||
TimetableLessonDao.Properties.EndTime.eq(apiEntity.getEndTime()))
|
TimetableLessonDao.Properties.EndTime.eq(apiEntity.getEndTime()))
|
||||||
.unique();
|
.unique();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<TimetableLesson> getLessonsFromDb(long dayId) {
|
||||||
|
return daoSession.getDayDao().load(dayId).getTimetableLessons();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import io.github.wulkanowy.R;
|
|||||||
import io.github.wulkanowy.WulkanowyApp;
|
import io.github.wulkanowy.WulkanowyApp;
|
||||||
import io.github.wulkanowy.data.RepositoryContract;
|
import io.github.wulkanowy.data.RepositoryContract;
|
||||||
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
import io.github.wulkanowy.data.db.dao.entities.Grade;
|
||||||
|
import io.github.wulkanowy.data.sync.NotRegisteredUserException;
|
||||||
import io.github.wulkanowy.services.notifies.GradeNotify;
|
import io.github.wulkanowy.services.notifies.GradeNotify;
|
||||||
import io.github.wulkanowy.ui.main.MainActivity;
|
import io.github.wulkanowy.ui.main.MainActivity;
|
||||||
import io.github.wulkanowy.utils.LogUtils;
|
import io.github.wulkanowy.utils.LogUtils;
|
||||||
@ -74,9 +75,12 @@ public class SyncJob extends SimpleJobService {
|
|||||||
showNotification();
|
showNotification();
|
||||||
}
|
}
|
||||||
return JobService.RESULT_SUCCESS;
|
return JobService.RESULT_SUCCESS;
|
||||||
|
} catch (NotRegisteredUserException e) {
|
||||||
|
logError(e);
|
||||||
|
stop(getApplicationContext());
|
||||||
|
return JobService.RESULT_FAIL_NORETRY;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Crashlytics.logException(e);
|
logError(e);
|
||||||
LogUtils.error("During background synchronization an error occurred", e);
|
|
||||||
return JobService.RESULT_FAIL_RETRY;
|
return JobService.RESULT_FAIL_RETRY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,4 +120,9 @@ public class SyncJob extends SimpleJobService {
|
|||||||
gradeList.size(), gradeList.size());
|
gradeList.size(), gradeList.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logError(Exception e) {
|
||||||
|
Crashlytics.logException(e);
|
||||||
|
LogUtils.error("During background synchronization an error occurred", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import javax.inject.Inject;
|
|||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import io.github.wulkanowy.R;
|
import io.github.wulkanowy.R;
|
||||||
|
import io.github.wulkanowy.services.jobs.SyncJob;
|
||||||
import io.github.wulkanowy.ui.base.BaseActivity;
|
import io.github.wulkanowy.ui.base.BaseActivity;
|
||||||
import io.github.wulkanowy.ui.base.BasePagerAdapter;
|
import io.github.wulkanowy.ui.base.BasePagerAdapter;
|
||||||
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment;
|
import io.github.wulkanowy.ui.main.attendance.AttendanceFragment;
|
||||||
@ -140,6 +141,11 @@ public class MainActivity extends BaseActivity implements MainContract.View,
|
|||||||
viewPager.setCurrentItem(tabPosition, false);
|
viewPager.setCurrentItem(tabPosition, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startSyncService(int interval, boolean useOnlyWifi) {
|
||||||
|
SyncJob.start(getApplicationContext(), interval, useOnlyWifi);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
@ -18,6 +18,8 @@ public interface MainContract {
|
|||||||
void initiationViewPager(int tabPosition);
|
void initiationViewPager(int tabPosition);
|
||||||
|
|
||||||
void initiationBottomNav(int tabPosition);
|
void initiationBottomNav(int tabPosition);
|
||||||
|
|
||||||
|
void startSyncService(int interval, boolean useOnlyWifi);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PerActivity
|
@PerActivity
|
||||||
|
@ -32,6 +32,11 @@ public class MainPresenter extends BasePresenter<MainContract.View>
|
|||||||
|
|
||||||
getView().initiationBottomNav(tabPosition);
|
getView().initiationBottomNav(tabPosition);
|
||||||
getView().initiationViewPager(tabPosition);
|
getView().initiationViewPager(tabPosition);
|
||||||
|
|
||||||
|
if (getRepository().getSharedRepo().isServicesEnable()) {
|
||||||
|
getView().startSyncService(getRepository().getSharedRepo().getServicesInterval(),
|
||||||
|
getRepository().getSharedRepo().isMobileDisable());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -135,7 +135,7 @@ public class ExamsTabFragment extends BaseFragment implements ExamsTabContract.V
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
|
||||||
presenter.onDestroy();
|
presenter.onDestroy();
|
||||||
|
super.onDestroyView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ public class TimetableSubItem
|
|||||||
|
|
||||||
lessonName.setText(lesson.getSubject());
|
lessonName.setText(lesson.getSubject());
|
||||||
lessonTime.setText(getLessonTimeString());
|
lessonTime.setText(getLessonTimeString());
|
||||||
numberOfLesson.setText(lesson.getNumber());
|
numberOfLesson.setText(String.valueOf(lesson.getNumber()));
|
||||||
room.setText(getRoomString());
|
room.setText(getRoomString());
|
||||||
alert.setVisibility(lesson.getMovedOrCanceled() || lesson.getNewMovedInOrChanged()
|
alert.setVisibility(lesson.getMovedOrCanceled() || lesson.getNewMovedInOrChanged()
|
||||||
? View.VISIBLE : View.INVISIBLE);
|
? View.VISIBLE : View.INVISIBLE);
|
||||||
|
@ -5,7 +5,6 @@ import android.os.Bundle;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import io.github.wulkanowy.services.jobs.SyncJob;
|
|
||||||
import io.github.wulkanowy.services.notifies.NotificationService;
|
import io.github.wulkanowy.services.notifies.NotificationService;
|
||||||
import io.github.wulkanowy.ui.base.BaseActivity;
|
import io.github.wulkanowy.ui.base.BaseActivity;
|
||||||
import io.github.wulkanowy.ui.login.LoginActivity;
|
import io.github.wulkanowy.ui.login.LoginActivity;
|
||||||
@ -44,11 +43,6 @@ public class SplashActivity extends BaseActivity implements SplashContract.View
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startSyncService(int interval, boolean useOnlyWifi) {
|
|
||||||
SyncJob.start(getApplicationContext(), interval, useOnlyWifi);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelNotifications() {
|
public void cancelNotifications() {
|
||||||
new NotificationService(getApplicationContext()).cancelAll();
|
new NotificationService(getApplicationContext()).cancelAll();
|
||||||
|
@ -12,8 +12,6 @@ public interface SplashContract {
|
|||||||
|
|
||||||
void openMainActivity();
|
void openMainActivity();
|
||||||
|
|
||||||
void startSyncService(int interval, boolean useOnlyWifi);
|
|
||||||
|
|
||||||
void cancelNotifications();
|
void cancelNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,6 @@ public class SplashPresenter extends BasePresenter<SplashContract.View>
|
|||||||
super.onStart(activity);
|
super.onStart(activity);
|
||||||
getView().cancelNotifications();
|
getView().cancelNotifications();
|
||||||
|
|
||||||
if (getRepository().getSharedRepo().isServicesEnable()) {
|
|
||||||
getView().startSyncService(getRepository().getSharedRepo().getServicesInterval(),
|
|
||||||
getRepository().getSharedRepo().isMobileDisable());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getRepository().getSharedRepo().isUserLoggedIn()) {
|
if (getRepository().getSharedRepo().isUserLoggedIn()) {
|
||||||
getView().openMainActivity();
|
getView().openMainActivity();
|
||||||
} else {
|
} else {
|
||||||
|
@ -156,7 +156,7 @@ public final class DataObjectConverter {
|
|||||||
|
|
||||||
for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) {
|
for (io.github.wulkanowy.api.generic.Lesson lesson : lessonList) {
|
||||||
lessonEntityList.add(new AttendanceLesson()
|
lessonEntityList.add(new AttendanceLesson()
|
||||||
.setNumber(Integer.valueOf(lesson.getNumber()))
|
.setNumber(lesson.getNumber())
|
||||||
.setSubject(lesson.getSubject())
|
.setSubject(lesson.getSubject())
|
||||||
.setDate(lesson.getDate())
|
.setDate(lesson.getDate())
|
||||||
.setPresence(lesson.isPresence())
|
.setPresence(lesson.isPresence())
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils;
|
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public final class RootChecker {
|
|
||||||
|
|
||||||
private RootChecker() {
|
|
||||||
throw new IllegalStateException("Utility class");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isRooted() {
|
|
||||||
return checkOne() || checkTwo() || checkThree();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean checkOne() {
|
|
||||||
return Build.TAGS != null && Build.TAGS.contains("test-keys");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean checkTwo() {
|
|
||||||
return new File("/system/app/Superuser.apk").exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean checkThree() {
|
|
||||||
String[] commands = {"/system/xbin/which su", "/system/bin/which su", "which su"};
|
|
||||||
for (String command : commands) {
|
|
||||||
try {
|
|
||||||
Runtime.getRuntime().exec(command);
|
|
||||||
return true;
|
|
||||||
} catch (Exception e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -27,7 +27,6 @@ import javax.crypto.CipherOutputStream;
|
|||||||
import javax.security.auth.x500.X500Principal;
|
import javax.security.auth.x500.X500Principal;
|
||||||
|
|
||||||
import io.github.wulkanowy.utils.LogUtils;
|
import io.github.wulkanowy.utils.LogUtils;
|
||||||
import io.github.wulkanowy.utils.RootChecker;
|
|
||||||
|
|
||||||
public final class Scrambler {
|
public final class Scrambler {
|
||||||
|
|
||||||
@ -46,23 +45,16 @@ public final class Scrambler {
|
|||||||
loadKeyStore();
|
loadKeyStore();
|
||||||
generateNewKey(email, context);
|
generateNewKey(email, context);
|
||||||
return encryptString(email, plainText);
|
return encryptString(email, plainText);
|
||||||
} else {
|
|
||||||
if (RootChecker.isRooted()) {
|
|
||||||
return new String(Base64.encode(plainText.getBytes(), Base64.DEFAULT));
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException("Stored data in this devices " +
|
|
||||||
"isn't safe because android is rooted");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return new String(Base64.encode(plainText.getBytes(), Base64.DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String decrypt(String email, String encryptedText) throws CryptoException {
|
public static String decrypt(String email, String encryptedText) throws CryptoException {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||||
loadKeyStore();
|
loadKeyStore();
|
||||||
return decryptString(email, encryptedText);
|
return decryptString(email, encryptedText);
|
||||||
} else {
|
|
||||||
return new String(Base64.decode(encryptedText, Base64.DEFAULT));
|
|
||||||
}
|
}
|
||||||
|
return new String(Base64.decode(encryptedText, Base64.DEFAULT));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void loadKeyStore() throws CryptoException {
|
private static void loadKeyStore() throws CryptoException {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
Aplikacja jest we wczesnej fazie rozwoju, ciągle pracujemy nad kolejnymi funkcjami.
|
||||||
|
|
||||||
Wyróżnione cechy i funkcje:
|
Wyróżnione cechy i funkcje:
|
||||||
- Całkowicie darmowa i otwarta (brak jakichkolwiek reklam i mikropłatności)
|
- Całkowicie darmowa i otwarta (brak jakichkolwiek reklam i mikropłatności)
|
||||||
- Powiadomienia
|
- Powiadomienia
|
||||||
@ -5,4 +7,4 @@ Wyróżnione cechy i funkcje:
|
|||||||
- Aktywne wsparcie i rozwój
|
- Aktywne wsparcie i rozwój
|
||||||
|
|
||||||
GitHub: https://github.com/wulkanowy/wulkanowy
|
GitHub: https://github.com/wulkanowy/wulkanowy
|
||||||
Discord: https://discord.gg/JMG2rhJ
|
Discord: https://discord.gg/vccAQBr
|
||||||
|
@ -1,11 +1,4 @@
|
|||||||
Wersja 0.4.0:
|
Wersja 0.4.3:
|
||||||
- dodano widget planu lekcji
|
- naprawiono błąd z pokazywaniem usuniętych lekcji w planie
|
||||||
- dodano widok sprawdzianów
|
- naprawiono drobne błędy z wyrównaniem tekstu na starszych urządzeniach
|
||||||
- dodano informacje o końcowych ocenach z przedmiotu
|
- poprawiono synchronizację w tle spowodowaną błędem w komunikacji z serwerem
|
||||||
- dodano przełącznik semestru w ocenach
|
|
||||||
- dodano opcję ukrycia obecności
|
|
||||||
- dodano wyróżnik aktualnego tygodnia
|
|
||||||
- dodano podstawową obsługę niestandardowych dzienników Vulcan (np. Opolska eSzkoła)
|
|
||||||
- naprawiono animacje w ocenach
|
|
||||||
- naprawiono wyświetlanie oceny w szczególnych przypadkach
|
|
||||||
- optymalizacja aplikacji
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
style="?android:attr/progressBarStyleHorizontal"
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_below="@id/login_activity_progress_text"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:indeterminate="true"
|
android:indeterminate="true"
|
||||||
android:minHeight="30dp"
|
android:minHeight="30dp"
|
||||||
@ -35,9 +35,9 @@
|
|||||||
android:id="@+id/login_activity_progress_text"
|
android:id="@+id/login_activity_progress_text"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignBottom="@+id/login_activity_progress_bar"
|
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginBottom="42dp" />
|
android:layout_marginBottom="15dp"
|
||||||
|
android:text="@string/app_name" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
@ -44,7 +44,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="46dp"
|
android:layout_marginTop="46dp"
|
||||||
android:text="@string/attendance_no_entries"
|
android:text="@string/attendance_no_entries"
|
||||||
android:textAlignment="center"
|
android:gravity="center"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="46dp"
|
android:layout_marginTop="46dp"
|
||||||
|
android:gravity="center"
|
||||||
android:text="@string/exams_no_entries"
|
android:text="@string/exams_no_entries"
|
||||||
android:textAlignment="center"
|
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="46dp"
|
android:layout_marginTop="46dp"
|
||||||
android:text="@string/fragment_no_grades"
|
android:text="@string/fragment_no_grades"
|
||||||
android:textAlignment="center"
|
android:gravity="center"
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/timetable_tab_fragment_container"
|
android:id="@+id/timetable_tab_fragment_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -43,19 +43,19 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="46dp"
|
android:layout_marginTop="46dp"
|
||||||
|
android:gravity="center"
|
||||||
android:text="@string/info_free_week"
|
android:text="@string/info_free_week"
|
||||||
android:textAlignment="center"
|
|
||||||
android:textSize="20sp" />
|
android:textSize="20sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/timetable_tab_fragment_no_item_name"
|
android:id="@+id/timetable_tab_fragment_no_item_name"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/app_name"
|
|
||||||
android:textSize="20sp"
|
|
||||||
android:layout_below="@id/timetable_tab_fragment_no_item_image"
|
android:layout_below="@id/timetable_tab_fragment_no_item_image"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:text="@string/app_name"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:layout_marginTop="15dp" />
|
android:textSize="20sp" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<android.support.v4.widget.SwipeRefreshLayout
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<string name="login_accepted_text">Pomyślnie zalogowano</string>
|
<string name="login_accepted_text">Pomyślnie zalogowano</string>
|
||||||
<string name="login_bad_credentials_text">Niepoprawny e-mail lub hasło</string>
|
<string name="login_bad_credentials_text">Niepoprawny e-mail lub hasło</string>
|
||||||
<string name="login_bad_account_permission_text">Brak uprawnień do otwarcia dziennika. Sprawdź wprowadzoną nazwę powiatu</string>
|
<string name="login_bad_account_permission_text">Brak uprawnień do otwarcia dziennika. Sprawdź wprowadzoną nazwę powiatu</string>
|
||||||
<string name="login_denied_text">Logowanie nie powiodło się. Spróbuj zrestartować aplikację</string>
|
<string name="login_failed_text">Logowanie nie powiodło się. Spróbuj ponownie lub zrestartuj aplikację</string>
|
||||||
<string name="action_create_account">Nie masz jeszcze konta? Załóż je</string>
|
<string name="action_create_account">Nie masz jeszcze konta? Załóż je</string>
|
||||||
<string name="action_forgot_password">Zapomniałeś hasła?</string>
|
<string name="action_forgot_password">Zapomniałeś hasła?</string>
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<string name="login_accepted_text">Login is successful</string>
|
<string name="login_accepted_text">Login is successful</string>
|
||||||
<string name="login_bad_credentials_text">Bad e-mail or password</string>
|
<string name="login_bad_credentials_text">Bad e-mail or password</string>
|
||||||
<string name="login_bad_account_permission_text">No permission to open log. Check entered symbol</string>
|
<string name="login_bad_account_permission_text">No permission to open log. Check entered symbol</string>
|
||||||
<string name="login_denied_text">Login is failed. Try restart the app</string>
|
<string name="login_failed_text">Login is failed. Try again or restart the app</string>
|
||||||
<string name="action_create_account">No account yet? Create one</string>
|
<string name="action_create_account">No account yet? Create one</string>
|
||||||
<string name="action_forgot_password">Forgot password?</string>
|
<string name="action_forgot_password">Forgot password?</string>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user