feature_user #15

Manually merged
noemi3 merged 16 commits from feature_user into develop 2019-11-22 08:38:08 +00:00
17 changed files with 967 additions and 9 deletions

View File

@ -0,0 +1,20 @@
package wekan.wrapper.api;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
import wekan.wrapper.entity.UserPrototype;
public interface LoginService {
/**
*
* @param username
* @param password
* @return User id and token
*/
@FormUrlEncoded
@POST("/users/login")
Call<UserPrototype> login(@Field("username") String username, @Field("password") String password);
}

View File

@ -0,0 +1,73 @@
package wekan.wrapper.api;
import retrofit2.Call;
import retrofit2.http.*;
import wekan.wrapper.entity.Action;
import wekan.wrapper.entity.Board;
import wekan.wrapper.entity.BoardPrototype;
import wekan.wrapper.entity.User;
import java.util.List;
public interface UserService {
/**
* Get all users.
*
* @return the list with all users
*/
@GET("api/users")
Call<List<User>> getAllUser();
/**
* Get user information
*
* @param userId ID user
* @return user information
*/
@GET("api/users/{user}")
Call<User> getUser(@Path("user") String userId);
/**
* Get current User
* @return the current user
*/
@GET("api/user")
Call<User> getCurrentUser();
/**
* Delete user
* @param userId
* @return
*/
@DELETE("api/users/{user}")
Call<User> delete(@Path("user") String userId);
/******************** Don't work ****************************************************/
@FormUrlEncoded
@POST("api/users")
@Headers("Content-Type: multipart/form-data")
Call<User> newUser(@Field("username") String username,
@Field("email") String email,
@Field("password") String password
);
@FormUrlEncoded
@Headers("Content-Type: multipart/form-data")
@POST("/api/boards/{board}/members/{user}/add")
Call<Board> addMemberToBoard(@Path("board") String boardId, @Path("user") String userId,
@Field("action") String action,
@Field("isAdmin") boolean b1,
@Field("isNoComments") boolean b2,
@Field("isCommentOnly") boolean b3);
@POST("api/boards/{board}/members/{user}/remove")
Call<Void> removeUserFromBoard(@Path("board") String boardId, @Path("user") String userId,
@Body Action action);
}

View File

@ -0,0 +1,13 @@
package wekan.wrapper.entity;
import com.google.gson.annotations.SerializedName;
public enum Action {
@SerializedName("takeOwnership")
TAKE_OWNERSHIP,
@SerializedName("disableLogin")
DISABLE_LOGIN,
@SerializedName("enableLogin")
ENABLE_LOGIN
}

View File

@ -0,0 +1,13 @@
package wekan.wrapper.entity;
import com.google.gson.annotations.SerializedName;
public enum BoardView {
@SerializedName("board-view-lists")
BOARD_VIEW_LISTS,
@SerializedName("board-view-swimlanes")
BOARD_VIEW_SWIMLANES,
@SerializedName("board-view-cal")
BOARD_VIEW_CAL
}

View File

@ -17,6 +17,14 @@ public class Card {
public Card() { public Card() {
} }
public String getAuthorId() {
return authorId;
}
public void setAuthorId(String authorId) {
this.authorId = authorId;
}
public String getId() { public String getId() {
return id; return id;
} }
@ -217,13 +225,6 @@ public class Card {
isOvertime = overtime; isOvertime = overtime;
} }
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public int getSort() { public int getSort() {
return sort; return sort;
@ -285,7 +286,7 @@ public class Card {
", endAt='" + endAt + '\'' + ", endAt='" + endAt + '\'' +
", spentTime=" + spentTime + ", spentTime=" + spentTime +
", isOvertime=" + isOvertime + ", isOvertime=" + isOvertime +
", userId='" + userId + '\'' + ", userId='" + authorId + '\'' +
", sort=" + sort + ", sort=" + sort +
", subtaskSort=" + subtaskSort + ", subtaskSort=" + subtaskSort +
", type='" + type + '\'' + ", type='" + type + '\'' +
@ -319,10 +320,11 @@ public class Card {
private Date endAt; private Date endAt;
private int spentTime; private int spentTime;
private Boolean isOvertime; private Boolean isOvertime;
private String userId; //private String userId;
private int sort; private int sort;
private int subtaskSort; private int subtaskSort;
private String type; private String type;
private String linkedId; private String linkedId;
@SerializedName(value = "authorId", alternate = "userId")
private String authorId; private String authorId;
} }

View File

@ -0,0 +1,24 @@
package wekan.wrapper.entity;
import java.util.List;
public class Email {
@Override
public String toString() {
return "email{" +
"verificationTokens=" + verificationTokens +
'}';
}
public List<VerificationToken> getVerificationTokens() {
return verificationTokens;
}
public void setVerificationTokens(List<VerificationToken> verificationTokens) {
this.verificationTokens = verificationTokens;
}
private List<VerificationToken> verificationTokens;
}

View File

@ -0,0 +1,19 @@
package wekan.wrapper.entity;
import com.google.gson.annotations.SerializedName;
public enum ListSortBy {
@SerializedName("-modifiedAt")
_MODIFIEDAT,
@SerializedName("modifiedAt")
MODIFIEDAT,
@SerializedName("-title")
_TITLE,
@SerializedName("title")
TITLE,
@SerializedName("-sort")
_SORT,
@SerializedName("sort")
SORT
}

View File

@ -0,0 +1,35 @@
package wekan.wrapper.entity;
/**
* contains the hash code of the access token and the date of that access
*/
public class LoginToken {
public String getWhen() {
return when;
}
public void setWhen(String when) {
this.when = when;
}
public String getHashedToken() {
return hashedToken;
}
public void setHashedToken(String hashedToken) {
this.hashedToken = hashedToken;
}
@Override
public String toString() {
return "LoginToken{" +
"when='" + when + '\'' +
", hashedToken='" + hashedToken + '\'' +
'}';
}
private String when;
private String hashedToken;
}

View File

@ -0,0 +1,21 @@
package wekan.wrapper.entity;
public class Password {
@Override
public String toString() {
return "Password{" +
"bcrypt='" + bcrypt + '\'' +
'}';
}
public String getBcrypt() {
return bcrypt;
}
public void setBcrypt(String bcrypt) {
this.bcrypt = bcrypt;
}
private String bcrypt;
}

View File

@ -0,0 +1,30 @@
package wekan.wrapper.entity;
import java.util.List;
/**
* Keeps track of access through the LoginToken list
* LoginToken contains the hash code of the access token
* and the date of that access
*
*/
public class Resume {
public List<LoginToken> getLoginTokens() {
return loginTokens;
}
public void setLoginTokens(List<LoginToken> loginTokens) {
this.loginTokens = loginTokens;
}
@Override
public String toString() {
return "Resume{" +
"loginTokens=" + loginTokens +
'}';
}
private List<LoginToken> loginTokens;
}

View File

@ -0,0 +1,41 @@
package wekan.wrapper.entity;
public class Service {
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
public Resume getResume() {
return resume;
}
public void setResume(Resume resume) {
this.resume = resume;
}
public Password getPassword() {
return password;
}
public void setPassword(Password password) {
this.password = password;
}
@Override
public String toString() {
return "Service{" +
"email=" + email +
", resume=" + resume +
", password=" + password +
'}';
}
private Email email;
private Resume resume;
private Password password;
}

View File

@ -0,0 +1,139 @@
package wekan.wrapper.entity;
import com.google.gson.annotations.SerializedName;
import java.util.Date;
import java.util.List;
public class User {
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<UserEmail> getEmails() {
return emails;
}
public void setEmails(List<UserEmail> emails) {
this.emails = emails;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getModifiedAt() {
return modifiedAt;
}
public void setModifiedAt(Date modifiedAt) {
this.modifiedAt = modifiedAt;
}
public UserProfile getProfile() {
return profile;
}
public void setProfile(UserProfile profile) {
this.profile = profile;
}
public String getHeartbeat() {
return heartbeat;
}
public void setHeartbeat(String heartbeat) {
this.heartbeat = heartbeat;
}
public boolean isAdmin() {
return isAdmin;
}
public void setAdmin(boolean admin) {
isAdmin = admin;
}
public boolean isCreatedThroughApi() {
return createdThroughApi;
}
public void setCreatedThroughApi(boolean createdThroughApi) {
this.createdThroughApi = createdThroughApi;
}
public boolean isLoginDisabled() {
return loginDisabled;
}
public void setLoginDisabled(boolean loginDisabled) {
this.loginDisabled = loginDisabled;
}
public String getAuthenticationMethod() {
return authenticationMethod;
}
public void setAuthenticationMethod(String authenticationMethod) {
this.authenticationMethod = authenticationMethod;
}
public Service getServices() {
return services;
}
public void setServices(Service services) {
this.services = services;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", emails=" + emails +
", createdAt=" + createdAt +
", modifiedAt=" + modifiedAt +
", profile=" + profile +
", heartbeat='" + heartbeat + '\'' +
", isAdmin=" + isAdmin +
", createdThroughApi=" + createdThroughApi +
", loginDisabled=" + loginDisabled +
", authenticationMethod='" + authenticationMethod + '\'' +
", services='" + services + '\'' +
'}';
}
@SerializedName("_id")
private String id;
private String username;
private List<UserEmail> emails;
private Date createdAt;
private Date modifiedAt;
private UserProfile profile;
private Service services;
private String heartbeat;
private boolean isAdmin;
private boolean createdThroughApi;
private boolean loginDisabled;
private String authenticationMethod;
}

View File

@ -0,0 +1,30 @@
package wekan.wrapper.entity;
public class UserEmail {
public String getEmail() {
return address;
}
public void setEmail(String email) {
this.address = email;
}
public boolean isVerified() {
return verified;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
@Override
public String toString() {
return "UserEmail{" +
"adrress='" + address + '\'' +
", verified=" + verified +
'}';
}
private String address;
private boolean verified;
}

View File

@ -0,0 +1,204 @@
package wekan.wrapper.entity;
import java.util.List;
public class UserProfile {
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(String avatarUrl) {
this.avatarUrl = avatarUrl;
}
public List<String> getEmailBuffer() {
return emailBuffer;
}
public void setEmailBuffer(List<String> emailBuffer) {
this.emailBuffer = emailBuffer;
}
public String getFullname() {
return fullname;
}
public void setFullname(String fullname) {
this.fullname = fullname;
}
public boolean isShowDesktopDragHandles() {
return showDesktopDragHandles;
}
public void setShowDesktopDragHandles(boolean showDesktopDragHandles) {
this.showDesktopDragHandles = showDesktopDragHandles;
}
public boolean isHiddenSystemMessages() {
return hiddenSystemMessages;
}
public void setHiddenSystemMessages(boolean hiddenSystemMessages) {
this.hiddenSystemMessages = hiddenSystemMessages;
}
public boolean isHiddenMinicardLabelText() {
return hiddenMinicardLabelText;
}
public void setHiddenMinicardLabelText(boolean hiddenMinicardLabelText) {
this.hiddenMinicardLabelText = hiddenMinicardLabelText;
}
public String getInitials() {
return initials;
}
public void setInitials(String initials) {
this.initials = initials;
}
public List<String> getInvitedBoards() {
return invitedBoards;
}
public void setInvitedBoards(List<String> invitedBoards) {
this.invitedBoards = invitedBoards;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public List<String> getNotifications() {
return notifications;
}
public void setNotifications(List<String> notifications) {
this.notifications = notifications;
}
public int getShowCardsCountAt() {
return showCardsCountAt;
}
public void setShowCardsCountAt(int showCardsCountAt) {
this.showCardsCountAt = showCardsCountAt;
}
public List<String> getStarredBoards() {
return starredBoards;
}
public void setStarredBoards(List<String> starredBoards) {
this.starredBoards = starredBoards;
}
public String getIcode() {
return icode;
}
public void setIcode(String icode) {
this.icode = icode;
}
public BoardView getBoardView() {
return boardView;
}
public void setBoardView(BoardView boardView) {
this.boardView = boardView;
}
public ListSortBy getListSortBy() {
return listSortBy;
}
public void setListSortBy(ListSortBy listSortBy) {
this.listSortBy = listSortBy;
}
public String getTemplatesBoardId() {
return templatesBoardId;
}
public void setTemplatesBoardId(String templatesBoardId) {
this.templatesBoardId = templatesBoardId;
}
public String getCardTemplatesSwimlaneId() {
return cardTemplatesSwimlaneId;
}
public void setCardTemplatesSwimlaneId(String cardTemplatesSwimlaneId) {
this.cardTemplatesSwimlaneId = cardTemplatesSwimlaneId;
}
public String getListTemplatesSwimlaneId() {
return listTemplatesSwimlaneId;
}
public void setListTemplatesSwimlaneId(String listTemplatesSwimlaneId) {
this.listTemplatesSwimlaneId = listTemplatesSwimlaneId;
}
public String getBoardTemplatesSwimlaneId() {
return boardTemplatesSwimlaneId;
}
public void setBoardTemplatesSwimlaneId(String boardTemplatesSwimlaneId) {
this.boardTemplatesSwimlaneId = boardTemplatesSwimlaneId;
}
@Override
public String toString() {
return "UserProfile{" +
"avatarUrl='" + avatarUrl + '\'' +
", emailBuffer=" + emailBuffer +
", fullname='" + fullname + '\'' +
", showDesktopDragHandles=" + showDesktopDragHandles +
", hiddenSystemMessages=" + hiddenSystemMessages +
", hiddenMinicardLabelText=" + hiddenMinicardLabelText +
", initials='" + initials + '\'' +
", invitedBoards=" + invitedBoards +
", language='" + language + '\'' +
", notifications=" + notifications +
", showCardsCountAt=" + showCardsCountAt +
", starredBoards=" + starredBoards +
", icode='" + icode + '\'' +
", boardView=" + boardView +
", listSortBy=" + listSortBy +
", templatesBoardId='" + templatesBoardId + '\'' +
", cardTemplatesSwimlaneId='" + cardTemplatesSwimlaneId + '\'' +
", listTemplatesSwimlaneId='" + listTemplatesSwimlaneId + '\'' +
", boardTemplatesSwimlaneId='" + boardTemplatesSwimlaneId + '\'' +
'}';
}
private String avatarUrl;
private List<String> emailBuffer;
private String fullname;
private boolean showDesktopDragHandles;
private boolean hiddenSystemMessages;
private boolean hiddenMinicardLabelText;
private String initials;
private List<String> invitedBoards;
private String language;
private List<String> notifications;
private int showCardsCountAt;
private List<String> starredBoards;
private String icode;
private BoardView boardView;
private ListSortBy listSortBy;
private String templatesBoardId;
private String cardTemplatesSwimlaneId;
private String listTemplatesSwimlaneId;
private String boardTemplatesSwimlaneId;
}

View File

@ -0,0 +1,47 @@
package wekan.wrapper.entity;
public class UserPrototype {
public UserPrototype(String id, String token, String tokenExpires) {
this.id = id;
this.token = token;
this.tokenExpires = tokenExpires;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", token='" + token + '\'' +
", tokenExpires='" + tokenExpires + '\'' +
'}';
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getTokenExpires() {
return tokenExpires;
}
public void setTokenExpires(String tokenExpires) {
this.tokenExpires = tokenExpires;
}
private String id;
private String token;
private String tokenExpires;
}

View File

@ -0,0 +1,43 @@
package wekan.wrapper.entity;
import java.util.Date;
public class VerificationToken {
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getWhen() {
return when;
}
public void setWhen(Date when) {
this.when = when;
}
@Override
public String toString() {
return "VerificationToken{" +
"token='" + token + '\'' +
", address='" + address + '\'' +
", when=" + when +
'}';
}
private String token;
private String address;
private Date when;
}

View File

@ -0,0 +1,204 @@
package wekan.wrapper.api;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import wekan.wrapper.entity.Service;
import wekan.wrapper.entity.User;
import wekan.wrapper.entity.UserEmail;
import wekan.wrapper.entity.UserProfile;
import javax.jws.soap.SOAPBinding;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.List;
public class UserServiceTest {
private MockWebServer mockWebServer = new MockWebServer();
private UserService service = null;
@Before
public void setUp() {
try {
mockWebServer.start();
service = new Retrofit.Builder()
.baseUrl(mockWebServer.url("/"))
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(UserService.class);
} catch (IOException e) {
e.printStackTrace();
}
}
@After
public void teardown() {
try {
mockWebServer.shutdown();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void getAllUsersTest(){
MockResponse response = new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(
"[{\"_id\":\"Si69gNgkJfQuk6uiJ\",\"username\":\"norangebit\"}," +
"{\"_id\":\"8rsnfEPkfMS49Pv6q\",\"username\":\"noemi\"}," +
"{\"_id\":\"jPdkf3a9bmfZWx3GR\",\"username\":\"umberto\"}]"
);
mockWebServer.enqueue(response);
try{
List<User> users = service.getAllUser().execute().body();
assertNotNull(users);
assertEquals("Si69gNgkJfQuk6uiJ", users.get(0).getId());
assertEquals("norangebit", users.get(0).getUsername());
assertEquals("8rsnfEPkfMS49Pv6q", users.get(1).getId());
assertEquals("noemi", users.get(1).getUsername());
assertEquals("jPdkf3a9bmfZWx3GR", users.get(2).getId());
assertEquals("umberto", users.get(2).getUsername());
}
catch (IOException e){
e.printStackTrace();
}
}
@Test
public void getUser(){
MockResponse response = new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(user1);
mockWebServer.enqueue(response);
try {
User user = service.getUser("jPdkf3a9bmfZWx3GR").execute().body();
assert user != null;
List<UserEmail> userEmail = user.getEmails();
UserProfile userProfile = user.getProfile();
Service ser = user.getServices();
assertEquals("jPdkf3a9bmfZWx3GR", user.getId());
assertEquals("umberto", user.getUsername());
assertEquals("password", user.getAuthenticationMethod());
assertTrue(user.isAdmin());
//assertEquals("Mon Oct 14 20:14:38 CEST 2019", user.getCreatedAt());
assertFalse(userEmail.isEmpty());
assertEquals("my@email.com", userEmail.get(0).getEmail());
assertFalse(userEmail.get(0).isVerified());
assertEquals("BOARD_VIEW_SWIMLANES", userProfile.getBoardView().toString());
assertEquals("zo82BZYxFTNBpb7jX", userProfile.getCardTemplatesSwimlaneId());
assertEquals("_MODIFIEDAT", userProfile.getListSortBy().toString());
assertEquals(1, ser.getEmail().getVerificationTokens().size());
assertEquals("my@email.com",
ser.getEmail().getVerificationTokens().get(0).getAddress());
assertEquals("$2a$10$CRZrpT4x.VpG2FdJxR3rN.9m0NbQb0OPsSPBDAZukggxrskMtWA8.",
ser.getPassword().getBcrypt());
assertEquals(2, ser.getResume().getLoginTokens().size());
assertEquals("CY/PWeDa3fAkl+k94+GWzCtpB5nPcVxLzzzjXs4kI3A=", ser.getResume().getLoginTokens().get(0).getHashedToken());
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void getCurrentUser(){
MockResponse mockResponse = new MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(user2);
mockWebServer.enqueue(mockResponse);
try {
User user = service.getCurrentUser().execute().body();
assert user != null;
UserProfile userProfile = user.getProfile();
assertNotNull(user);
assertEquals("jPdkf3a9bmfZWx3GR", user.getId());
assertEquals("umberto", user.getUsername());
assertEquals("password", user.getAuthenticationMethod());
assertTrue(user.isAdmin());
assertFalse(user.isLoginDisabled());
assertFalse(user.getEmails().isEmpty());
assertEquals(1, user.getEmails().size());
assertEquals("my@email.com", user.getEmails().get(0).getEmail());
assertNotNull(userProfile);
assertEquals("zo82BZYxFTNBpb7jX",
userProfile.getCardTemplatesSwimlaneId());
assertEquals("j6ZuPbwaN9nsCDxyS",
userProfile.getBoardTemplatesSwimlaneId());
} catch (IOException e) {
e.printStackTrace();
}
}
private static final String user1 = "{" +
"\"_id\":\"jPdkf3a9bmfZWx3GR\"," +
"\"username\":\"umberto\"," +
"\"emails\":[{\"address\":\"my@email.com\",\"verified\":false}]," +
"\"authenticationMethod\":\"password\"," +
"\"isAdmin\":\"true\"," +
"\"loginDisabled\":\"true\"," +
"\"profile\":{\"boardView\":\"board-view-swimlanes\",\"templatesBoardId\":\"eLvE8FnqvACfC9Rtb\"," +
"\"cardTemplatesSwimlaneId\":\"zo82BZYxFTNBpb7jX\",\"listTemplatesSwimlaneId\":\"Kja32A85P2HADWKFA\"," +
"\"boardTemplatesSwimlaneId\":\"j6ZuPbwaN9nsCDxyS\",\"listSortBy\":\"-modifiedAt\"}," +
"\"createdAt\":\"2019-10-14T18:14:38.249Z\","+
"\"modifiedAt\":\"2019-11-09T17:55:36.976Z\"," +
"\"services\":{\n" +
" \"password\":{\n" +
" \"bcrypt\":\"$2a$10$CRZrpT4x.VpG2FdJxR3rN.9m0NbQb0OPsSPBDAZukggxrskMtWA8.\"\n" +
" },\n" +
" \"email\":{\n" +
" \"verificationTokens\":[\n" +
" {\n" +
" \"token\":\"8rzwpq_So2PVYHVSfrcc5f5QZnuV2wEtu7QRQGwOJx8\",\n" +
" \"address\":\"my@email.com\",\n" +
" \"when\":\"2017-09-13T06:45:53.157Z\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"resume\":{\n" +
" \"loginTokens\":[\n" +
" {\n" +
" \"when\":\"2017-09-13T06:45:53.265Z\",\n" +
" \"hashedToken\":\"CY/PWeDa3fAkl+k94+GWzCtpB5nPcVxLzzzjXs4kI3A=\"\n" +
" },\n" +
" {\n" +
" \"when\":\"2017-09-16T06:06:19.741Z\",\n" +
" \"hashedToken\":\"74MQNXfsgjkItx/gpgPb29Y0MSNAvBrsnSGQmr4YGvQ=\"\n" +
" }\n" +
" ]\n" +
" }\n" +
"}\n" +
"}";
private final String user2 = "{" +
"\"_id\":\"jPdkf3a9bmfZWx3GR\"," +
"\"createdAt\":\"2019-10-14T18:14:38.249Z\"," +
"\"username\":\"umberto\"," +
"\"emails\":[{\"address\":\"my@email.com\"," +
"\"verified\":false}]," +
"\"modifiedAt\":\"2019-11-09T17:55:36.976Z\"," +
"\"profile\":{\"boardView\":\"board-view-swimlanes\"," +
"\"templatesBoardId\":\"eLvE8FnqvACfC9Rtb\"," +
"\"cardTemplatesSwimlaneId\":\"zo82BZYxFTNBpb7jX\"," +
"\"listTemplatesSwimlaneId\":\"Kja32A85P2HADWKFA\"," +
"\"boardTemplatesSwimlaneId\":\"j6ZuPbwaN9nsCDxyS\"," +
"\"listSortBy\":\"-modifiedAt\"}," +
"\"authenticationMethod\":\"password\"," +
"\"isAdmin\":true," +
"\"loginDisabled\":false}";
}