Explorar el Código

safety commit before system upgrade

master
peter hace 5 años
padre
commit
f7f770a40c
Se han modificado 36 ficheros con 650 adiciones y 124 borrados
  1. 43
    16
      src/backend/Components/Character/CharacterManager.ts
  2. 3
    1
      src/backend/Components/Character/Interface.ts
  3. 2
    0
      src/backend/Components/Character/RPCInterface.ts
  4. 8
    9
      src/backend/Components/Item/ItemManager.ts
  5. 3
    2
      src/backend/Components/Login/Interface.ts
  6. 50
    34
      src/backend/Components/Login/LoginManager.ts
  7. 2
    2
      src/backend/Components/Raid/Interface.ts
  8. 31
    17
      src/backend/Components/Raid/RaidManager.ts
  9. 3
    3
      src/backend/Injector/Injector.ts
  10. 3
    3
      src/backend/Injector/ServiceDecorator.ts
  11. 16
    2
      src/backend/Types/PlayerSpecs.ts
  12. 13
    8
      src/backend/Types/Types.ts
  13. 3
    3
      src/frontend/package-lock.json
  14. 1
    1
      src/frontend/package.json
  15. 1
    1
      src/frontend/src/app/@theme/components/header/header.component.html
  16. 3
    1
      src/frontend/src/app/@theme/components/header/header.component.ts
  17. 1
    0
      src/frontend/src/app/app-routing.module.ts
  18. 0
    1
      src/frontend/src/app/app.module.ts
  19. 1
    1
      src/frontend/src/app/frontcraft/auth/register/register.component.html
  20. 18
    1
      src/frontend/src/app/frontcraft/auth/register/register.component.ts
  21. 10
    0
      src/frontend/src/app/frontcraft/pages/character/character.component.html
  22. 34
    0
      src/frontend/src/app/frontcraft/pages/character/character.component.ts
  23. 35
    1
      src/frontend/src/app/frontcraft/pages/dashboard/dashboard.component.html
  24. 42
    0
      src/frontend/src/app/frontcraft/pages/dashboard/dashboard.component.scss
  25. 54
    7
      src/frontend/src/app/frontcraft/pages/dashboard/dashboard.component.ts
  26. 10
    0
      src/frontend/src/app/frontcraft/pages/dashboard/tree-grid-shared.scss
  27. 10
    1
      src/frontend/src/app/frontcraft/pages/pages-layout.component.ts
  28. 15
    0
      src/frontend/src/app/frontcraft/pages/pages-routing.module.ts
  29. 9
    1
      src/frontend/src/app/frontcraft/pages/pages.module.ts
  30. 36
    0
      src/frontend/src/app/frontcraft/pages/people/people.component.html
  31. 42
    0
      src/frontend/src/app/frontcraft/pages/people/people.component.scss
  32. 64
    0
      src/frontend/src/app/frontcraft/pages/people/people.component.ts
  33. 10
    0
      src/frontend/src/app/frontcraft/pages/people/tree-grid-shared.scss
  34. 24
    0
      src/frontend/src/app/frontcraft/pages/user/user.component.html
  35. 38
    0
      src/frontend/src/app/frontcraft/pages/user/user.component.ts
  36. 12
    8
      src/frontend/src/app/frontcraft/services/login-api.ts

+ 43
- 16
src/backend/Components/Character/CharacterManager.ts Ver fichero

@@ -1,6 +1,6 @@
1 1
 import { RPCInterface } from "rpclibrary";
2 2
 import { Inject, Module } from "../../Injector/ServiceDecorator";
3
-import { TableDefiniton, Character } from "../../Types/Types";
3
+import { TableDefiniton, Character, Spec, User } from "../../Types/Types";
4 4
 import { CharacterManagerIfc } from "./RPCInterface";
5 5
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
6 6
 import { getSpecTableData, SpecT } from "../../Types/PlayerSpecs";
@@ -18,12 +18,21 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
18 18
     private admin: IAdmin   
19 19
 
20 20
     @Inject(ILoginManager)
21
-    private loginManager : any
21
+    private loginManager : ILoginManager
22 22
 
23 23
     exportRPCs = () => [
24 24
         {
25
-           name: 'getSpecId' as 'getSpecId',
26
-           call: this.getSpecId
25
+            name: 'getSpecId' as 'getSpecId',
26
+            call: this.getSpecId
27
+        },{
28
+            name: 'getCharacterByName' as 'getCharacterByName',
29
+            call: this.getCharacterByName
30
+        },{
31
+            name: 'getCharacters' as 'getCharacters',
32
+            call: this.getCharacters
33
+        },{
34
+            name: 'getCharactersOfUser' as 'getCharactersOfUser',
35
+            call: this.getCharactersOfUser
27 36
         }
28 37
     ]
29 38
 
@@ -44,7 +53,7 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
44 53
             name: 'characters',
45 54
             tableBuilder: (table) => {
46 55
                 table.increments("id").primary()
47
-                table.string("name").notNullable().unique()
56
+                table.string("charactername").notNullable().unique()
48 57
                 table.integer("specid").notNullable()
49 58
                 table.foreign("specid").references("specs.id")
50 59
                 table.integer("userid").notNullable()
@@ -55,8 +64,8 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
55 64
             tableBuilder: (table) => {
56 65
                 table.increments("id")
57 66
                 table.string('class')
58
-                table.string('name')
59
-                table.unique(['class', 'name'])
67
+                table.string('specname')
68
+                table.unique(['class', 'specname'])
60 69
             }
61 70
         }
62 71
     ]
@@ -64,17 +73,14 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
64 73
     private initialized = false
65 74
     
66 75
     initialize = async () => {
67
-        if(!this.initialized)
68
-            this.initialized = true
69
-        //initialize spec table
70
-
71
-        getLogger('CharacterManager').debug('inserting specs')
72
-
76
+        if(this.initialized) return
77
+        this.initialized = true
73 78
         await this.admin.knex('specs').insert(getSpecTableData()).catch(e => { console.log("skipping spec insertion") })
74 79
     }
75 80
 
76 81
     createCharacter = async (userToken: string, character : Character) : Promise<Character> => {
77 82
         try{
83
+            character.charactername = character.charactername.toLowerCase()
78 84
             const user = this.loginManager.getUserRecordByToken(userToken)
79 85
             await this.admin.knex('characters').insert(character)
80 86
             const char : Character = await this.admin.knex.select('*').from('characters').where(character).first()
@@ -90,12 +96,33 @@ implements FrontworkComponent<CharacterManagerIfc, RPCInterface>, ICharacterMana
90 96
         return this.admin.knex.select('*').from('characters')
91 97
     }
92 98
 
99
+    getCharacterByName = async(charactername: string) : Promise<(Character & User & Spec) | void> => {
100
+        charactername = charactername.toLowerCase()
101
+        return await this.admin.knex('characters as c')
102
+        .join('specs as s', 's.id', '=', 'c.specid')
103
+        .join('users as u', 'u.id', '=', 'c.userid')
104
+        .select('charactername', 'class', 'specname', 'username', 'rank', 'locked', )
105
+        .where('charactername', '=', charactername)
106
+        .first()
107
+    }
108
+
109
+    getCharactersOfUser = async(username: string) : Promise<(Character & Spec)[]> => {
110
+        username = username.toLowerCase()
111
+        return await this.admin.knex('characters as c')
112
+        .join('users as u', 'u.id', '=', 'c.userid')
113
+        .join('specs as s', 's.id', '=', 'c.specid')
114
+        .select('class', 'charactername', 'class', 'specname')
115
+        .where('u.username', '=', username)
116
+    }
117
+
93 118
     getSpecId = async <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => await this.admin.knex
94 119
     .from('specs')
95 120
     .select('id')
96
-    .where({
121
+    .where(<Spec>{
97 122
         class: clazz,
98
-        name: name
99
-    }).first().then(spec => spec.id)
123
+        specname: name
124
+    })
125
+    .first()
126
+    .then(spec => spec.id)
100 127
 
101 128
 }

+ 3
- 1
src/backend/Components/Character/Interface.ts Ver fichero

@@ -1,4 +1,4 @@
1
-import { Character } from "../../Types/Types"
1
+import { Character, Spec, User } from "../../Types/Types"
2 2
 import { SpecT } from "../../Types/PlayerSpecs"
3 3
 
4 4
 
@@ -6,4 +6,6 @@ export class ICharacterManager{
6 6
     createCharacter: (usertoken: string, char : Character) => Promise<Character>
7 7
     getSpecId: <c extends keyof SpecT>(clazz: c, name: SpecT[c]) => Promise<number>
8 8
     getCharacters: () => Promise<Character[]>
9
+    getCharacterByName: (charactername: string) => Promise<(Character & User & Spec) | void>
10
+    getCharactersOfUser: (username: string) => Promise<(Character & Spec)[]>
9 11
 }

+ 2
- 0
src/backend/Components/Character/RPCInterface.ts Ver fichero

@@ -5,6 +5,8 @@ export type CharacterManagerIfc = {
5 5
     CharacterManager: {
6 6
         getSpecId : ICharacterManager['getSpecId']
7 7
         getCharacters : ICharacterManager['getCharacters']
8
+        getCharacterByName : ICharacterManager['getCharacterByName']
9
+        getCharactersOfUser: ICharacterManager['getCharactersOfUser']
8 10
     }
9 11
 }
10 12
 

+ 8
- 9
src/backend/Components/Item/ItemManager.ts Ver fichero

@@ -44,7 +44,7 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
44 44
 
45 45
         try{
46 46
             return <Item>{
47
-                name: r.wowhead.item[0].name[0],
47
+                itemname: r.wowhead.item[0].name[0],
48 48
                 iconname: r.wowhead.item[0].icon[0]._,
49 49
                 url: r.wowhead.item[0].link[0],
50 50
                 quality: r.wowhead.item[0].quality[0]._,
@@ -58,20 +58,19 @@ implements FrontworkComponent<ItemManagerIfc, ItemManagerFeatureIfc>, TableDefin
58 58
     getTableDefinitions(): TableDefiniton[] {
59 59
         return [
60 60
             {
61
-                name: 'reservations',
61
+                name: 'tokens',
62 62
                 tableBuilder: (table) => {
63
-                    table.integer("user_id").primary()
64
-                    table.foreign("user_id").references("id").inTable('users')
65
-                    table.integer("item_id").primary()
66
-                    table.foreign("item_id").references("id").inTable('items')
67
-                    table.integer("raid_id").primary()
68
-                    table.foreign("raid_id").references("id").inTable('raids')
63
+                    table.integer("characterid").primary()
64
+                    table.foreign("characterid").references("id").inTable('characters')
65
+                    table.integer("itemid").primary()
66
+                    table.foreign("itemid").references("id").inTable('items')
67
+                    table.integer("level")
69 68
                 }
70 69
             },{
71 70
                 name: 'items',
72 71
                 tableBuilder: (table) => {
73 72
                     table.increments("id").primary()
74
-                    table.string('name').unique().notNullable()
73
+                    table.string('itemname').unique().notNullable()
75 74
                     table.string('iconname').notNullable()
76 75
                     table.string('url').notNullable()
77 76
                     table.string('quality').defaultTo('Epic').notNullable()

+ 3
- 2
src/backend/Components/Login/Interface.ts Ver fichero

@@ -1,11 +1,12 @@
1
-import { Auth, Rank, User, RPCPermission } from "../../Types/Types"
1
+import { Auth, Rank, User, RPCPermission, UserRecord } from "../../Types/Types"
2 2
 
3 3
 export class ILoginManager{
4 4
     login: (username:string, pwHash:string) => Promise<Auth>
5 5
     logout: (username: string, tokenValue :string) => Promise<void>
6
-    getAuth: (tokenValue: string) => Promise<Auth>
6
+    getAuth: (tokenValue: string) => Promise<Auth | void>
7 7
     createUser: (user:User) => Promise<User>
8 8
     setPermission: (perm: RPCPermission) => Promise<void>
9 9
     getPermissions: () => Promise<RPCPermission[]>
10 10
     checkToken: (token: string, rank: Rank) => boolean
11
+    getUserRecordByToken: (tokenValue: string) => UserRecord | void
11 12
 }

+ 50
- 34
src/backend/Components/Login/LoginManager.ts Ver fichero

@@ -7,10 +7,10 @@ import { RaidManager } from "../Raid/RaidManager";
7 7
 import { CharacterManager } from "../Character/CharacterManager";
8 8
 import { LoginManagerIfc, LoginManagerFeatureIfc } from "./RPCInterface";
9 9
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
10
-import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token } from "../../Types/Types";
10
+import { Rank, User, Auth, _Rank, TableDefiniton, RPCPermission, FrontcraftFeatureIfc, AnyRPCExporter, Token, UserRecord } from "../../Types/Types";
11 11
 import { IAdmin } from "../../Admin/Interface";
12 12
 import { ILoginManager } from "./Interface";
13
-import { getLogger } from "log4js";
13
+import { getLogger, Logger } from "log4js";
14 14
 
15 15
 const uuid = require('uuid/v4')
16 16
 
@@ -45,11 +45,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
45 45
     
46 46
     exporters :any[] = []
47 47
     rankServers : {[rank in Rank] : Serverstate}
48
-    userLogins : {[username in string] : {
49
-        user: User
50
-        connections: {[port in number]: Socket}
51
-        auth: Auth
52
-    }} = {}
48
+    userLogins : {[username in string] : UserRecord} = {}
53 49
 
54 50
     exportRPCs = () => [
55 51
         {
@@ -89,7 +85,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
89 85
             name: 'users',
90 86
             tableBuilder: (table) => {
91 87
                 table.increments("id").primary()
92
-                table.string("name").notNullable().unique()
88
+                table.string("username").notNullable().unique()
93 89
                 table.string("pwhash").notNullable()
94 90
                 table.string("rank").notNullable()
95 91
                 table.string("email").nullable().unique()
@@ -98,7 +94,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
98 94
         },{
99 95
             name: 'rpcpermissions',
100 96
             tableBuilder: (table) => {
101
-                table.string("name").primary().notNullable()
97
+                table.string("rpcname").primary().notNullable()
102 98
                 _Rank.forEach(r => {
103 99
                     if(r === 'ADMIN')
104 100
                         table.boolean(r).defaultTo(true).notNullable()
@@ -118,7 +114,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
118 114
         await Promise.all( 
119 115
             [this, ...this.exporters].flatMap(exp => exp.exportRPCFeatures().map(async (feature) => {
120 116
             try{
121
-                await this.admin.knex.insert({ name: feature.name }).into('rpcpermissions')
117
+                await this.admin.knex.insert({ rpcname: feature.name }).into('rpcpermissions')
122 118
             }catch(e){
123 119
                 console.log(e);
124 120
             }
@@ -163,32 +159,37 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
163 159
         Object.values(this.userLogins).map(userLogin => {
164 160
             const auth = userLogin.auth
165 161
             if(!this.checkToken(auth.token.value, auth.user.rank)){
166
-                this.logout(auth.user.name, auth.token.value)
162
+                this.logout(auth.user.username, auth.token.value)
167 163
             }
168 164
         })
169 165
     }
170 166
 
171 167
     checkConnection = async (socket: Socket) => {
168
+        
172 169
         let data : any
173 170
         let tries = 0
174 171
         while(!data){
175 172
             tries ++
176 173
             if(tries === 5){
177 174
                 getLogger('LoginManager').debug('Connection check failed for connection *'+socket.port)
178
-
179 175
                 socket.destroy()
180
-                return
176
+                return false
181 177
             }
182
-            data = await Promise.race([socket.call('getUserData'), new Promise((res, rej) => { setTimeout(res, 250);})])
183
-        } 
184
-        this.userLogins[data.user.name].connections[socket.port] = socket
178
+            data = await Promise.race([socket.call('getUserData'), new Promise((res, rej) => { setTimeout(res, 1000);})])
179
+        }
180
+        if(!this.userLogins[data.user.username]){
181
+            await this.logout(data.user.username, data.token.value)
182
+            return false
183
+        }
184
+
185
+        this.userLogins[data.user.username].connections[socket.port] = socket
185 186
         await socket.call('navigate', ["/frontcraft/dashboard"])
186 187
         return true
187 188
     }
188 189
 
189 190
     setPermission = async (permission: RPCPermission) => {
190 191
         await this.admin.knex('rpcpermissions')
191
-        .where('rpcname', '=', permission.name)
192
+        .where('rpcname', '=', permission.rpcnamename)
192 193
         .update(permission)
193 194
     }
194 195
 
@@ -200,7 +201,7 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
200 201
         const perm : RPCPermission[] = await this.admin.knex
201 202
             .select(rank)
202 203
             .from('rpcpermissions')
203
-            .where('name', '=', <string>feature)
204
+            .where('rpcname', '=', <string>feature)
204 205
 
205 206
         if(perm.length === 0) return false
206 207
         return perm[0][rank]
@@ -233,6 +234,8 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
233 234
 
234 235
             user.locked = false
235 236
         }
237
+        user.username = user.username.toLowerCase()
238
+
236 239
         await this.admin.knex('users')
237 240
         .insert(user)
238 241
 
@@ -246,10 +249,20 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
246 249
 
247 250
     logout = async (username:string, tokenValue : string) : Promise<void> => {
248 251
         try{
252
+            username = username.toLowerCase()
253
+            const maybeRecord = this.getUserRecordByToken(tokenValue)
254
+            if(maybeRecord && maybeRecord.auth.user.username != username){
255
+                getLogger('LoginManager').warn(`Bad logout attempt
256
+                token by: ${maybeRecord.auth.user.username}
257
+                tried to logout: ${username}`)
258
+                return
259
+            } 
249 260
 
250
-            await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
251
-                await sock.call('navigate', '/auth/login')
252
-            }))
261
+            if(this.userLogins[username]){
262
+                await Promise.all (Object.values(this.userLogins[username].connections).map(async (sock) => {
263
+                    await sock.call('navigate', '/auth/login')
264
+                }))
265
+            }
253 266
 
254 267
             Object.values(this.rankServers)
255 268
                 .forEach(state => {
@@ -263,10 +276,11 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
263 276
     }
264 277
 
265 278
     login = async(username:string, pwHash:string) : Promise<Auth> => {
279
+        username = username.toLowerCase()
266 280
         const res:User[] = await this.admin.knex
267 281
         .select('*')
268 282
         .from('users')
269
-        .where({ name: username })
283
+        .where({ username: username })
270 284
 
271 285
         if(res.length > 0 && pwHash === res[0].pwhash){
272 286
             const user:User = res[0]
@@ -284,9 +298,8 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
284 298
                 port: this.rankServers[user.rank].port
285 299
             }
286 300
 
287
-            this.userLogins[user.name] = {connections: {}, auth: userAuth, user:user}
301
+            this.userLogins[user.username] = {connections: {}, auth: userAuth, user:user}
288 302
             this.rankServers[user.rank].allowed.push(token.value)
289
-
290 303
             return userAuth 
291 304
         }
292 305
 
@@ -294,16 +307,14 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
294 307
     }
295 308
 
296 309
     getUserRecordByToken(tokenValue: string){
297
-        const maybeRecord = Object.values(this.userLogins).find(login => login.auth.token.value === tokenValue)
298
-        return maybeRecord?maybeRecord:undefined
310
+        return Object.values(this.userLogins).find(login => login.auth.token.value === tokenValue)
299 311
     }
300 312
 
301
-    getAuth = async (tokenValue:string) : Promise<Auth> => {
313
+    getAuth = async (tokenValue:string) : Promise<Auth | void> => {
302 314
         const maybeAuth = this.getUserRecordByToken(tokenValue)
303 315
         if(maybeAuth)
304 316
             return maybeAuth.auth
305
-
306
-        throw new Error("Bad token")
317
+        return
307 318
     }
308 319
 
309 320
     startRankServer = async (rank : Rank, port: number) : Promise<RPCServer> => {
@@ -322,9 +333,14 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
322 333
             
323 334
                         },
324 335
                         connectionHandler: (socket) => {
325
-                            this.checkConnection(socket).catch((e) => {
326
-                                console.log(e);
327
-                            }) //sometimes times out if you go too fast
336
+                            this.checkConnection(socket).then(res => {
337
+                                if(!res){
338
+                                    socket.destroy();
339
+                                }
340
+                            }).catch((e) => {
341
+                                socket.destroy();
342
+                                getLogger('LoginManager').warn(e);
343
+                            })
328 344
                         },
329 345
                         errorHandler: (socket, e, rpcName, args) => {
330 346
                             console.log(rpcName, args);
@@ -346,8 +362,8 @@ implements FrontworkComponent<LoginManagerIfc, LoginManagerFeatureIfc>, ILoginMa
346 362
 
347 363
     createToken = (user:User): Token => {
348 364
         
349
-        if(this.userLogins[user.name]){
350
-            return this.userLogins[user.name].auth.token
365
+        if(this.userLogins[user.username]){
366
+            return this.userLogins[user.username].auth.token
351 367
         }
352 368
 
353 369
         const token:Token = {

+ 2
- 2
src/backend/Components/Raid/Interface.ts Ver fichero

@@ -1,4 +1,4 @@
1
-import { User, Raid, Signup } from "../../Types/Types"
1
+import { Raid, Signup, Character } from "../../Types/Types"
2 2
 
3 3
 export class IRaidManager{
4 4
     getRaids: () => Promise<Raid[]>
@@ -6,5 +6,5 @@ export class IRaidManager{
6 6
     addSignup: (signup: Signup) => Promise<any>
7 7
     removeSignup: (signup: Signup) => Promise<any>    
8 8
     getSignups: (raid:Raid) => Promise<Signup[]>
9
-    sign: (user:User, raid:Raid, attending:boolean) => Promise<any>
9
+    sign: (userToken: string, character:Character, raid:Raid, attending:boolean) => Promise<any>
10 10
 }

+ 31
- 17
src/backend/Components/Raid/RaidManager.ts Ver fichero

@@ -1,9 +1,10 @@
1 1
 import { Inject, Module } from "../../Injector/ServiceDecorator";
2 2
 import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
3 3
 import { FrontworkComponent } from "../../Types/FrontworkComponent";
4
-import { TableDefiniton, Signup, Raid, User } from "../../Types/Types";
4
+import { TableDefiniton, Signup, Raid, User, Character } from "../../Types/Types";
5 5
 import { IAdmin } from "../../Admin/Interface";
6 6
 import { IRaidManager } from "./Interface";
7
+import { ILoginManager } from "../Login/Interface";
7 8
 
8 9
 @Module(IRaidManager)
9 10
 export class RaidManager
@@ -13,6 +14,9 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
13 14
     @Inject(IAdmin)
14 15
     private admin: IAdmin
15 16
 
17
+    @Inject(ILoginManager)
18
+    private login: ILoginManager
19
+
16 20
     exportRPCs = () => [{
17 21
         name: 'getRaids' as 'getRaids',
18 22
         call: this.getRaids
@@ -57,11 +61,11 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
57 61
             },{
58 62
                 name: 'signups',
59 63
                 tableBuilder: (table) => {
60
-                    table.primary(['raid_id', 'user_id'])
61
-                    table.integer('raid_id')
62
-                    table.foreign('raid_id').references('id').inTable('raids')
63
-                    table.integer('user_id')
64
-                    table.foreign('user_id').references('id').inTable('users')
64
+                    table.primary(['raidid', 'characterid'])
65
+                    table.integer('raidid')
66
+                    table.foreign('raidid').references('id').inTable('raids')
67
+                    table.integer('characterid')
68
+                    table.foreign('characterid').references('id').inTable('characters')
65 69
                 }
66 70
             }            
67 71
         ]
@@ -78,8 +82,8 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
78 82
     removeSignup = async (signup: Signup) => await this.admin
79 83
     .knex('signups')
80 84
     .where({
81
-        raid_id: signup.raid_id, 
82
-        user_id: signup.user_id
85
+        raid_id: signup.raidid, 
86
+        character_id: signup.characterid
83 87
     })
84 88
     .delete()
85 89
 
@@ -87,15 +91,25 @@ implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>, IRaidManag
87 91
     .select('*')
88 92
     .from('raids')
89 93
     
90
-    getSignups = async (raid:Raid) : Promise<Signup[]> => await this.admin.knex
94
+    getSignups = async (raid:Raid) : Promise<Signup[]> => await this.admin
95
+    .knex('signups')
96
+    .join('characters as c', 'c.id', '=', 'characterid')
97
+    .join('specs as s', 's.id', '=', 'specid')
98
+    .join('users as u', 'u.id', '=', 'userid')
91 99
     .select('*')
92
-    .from('signups')
93
-    .where('raid_id', '=', raid.id!)
100
+    .where('raidid', '=', raid.id!)
94 101
     
95
-    sign = async (user:User, raid:Raid) => await this.admin
96
-    .knex('signups')
97
-    .insert({
98
-        raid_id: raid.id!,
99
-        user_id: user.id!
100
-    })
102
+    sign = async (usertoken:string, character:Character, raid:Raid) => {
103
+        const maybeUserRecord = this.login.getUserRecordByToken(usertoken)
104
+        if(!maybeUserRecord || maybeUserRecord.user.id != character.userid){
105
+            throw new Error("Bad Usertoken")
106
+        }
107
+
108
+        await this.admin
109
+        .knex('signups')
110
+        .insert({
111
+            raidid: raid.id!,
112
+            characterid: character.id!
113
+        })
114
+    }
101 115
 }

+ 3
- 3
src/backend/Injector/Injector.ts Ver fichero

@@ -13,7 +13,7 @@ export const Injector = new class {
13 13
   rootInterface : Type<any>
14 14
   root : Type<any>
15 15
   rootModules: Type<any>[] = []
16
-  modules : {ifc?: Type<any>, implementation: Type<any>}[] = []
16
+  modules : {implements?: Type<any>, implementation: Type<any>}[] = []
17 17
 
18 18
   moduleObjs : {[key in string] : FrontworkComponent} = {}
19 19
 
@@ -31,8 +31,8 @@ export const Injector = new class {
31 31
     if(target.name === this.rootInterface.name || target.name === this.root.name){
32 32
       let modules = this.modules.map(m => {
33 33
         const module = new m.implementation()
34
-        if(m.ifc)
35
-          this.moduleObjs[m.ifc.name] = module
34
+        if(m.implements)
35
+          this.moduleObjs[m.implements.name] = module
36 36
         this.moduleObjs[m.implementation.name] = module
37 37
         return module
38 38
       })

+ 3
- 3
src/backend/Injector/ServiceDecorator.ts Ver fichero

@@ -9,7 +9,7 @@ import { FrontworkComponent } from "../Types/FrontworkComponent";
9 9
 export const Module = (ifc?: Type<any>) : GenericClassDecorator<Type<any>> => {
10 10
   return (target: Type<any>) => {
11 11
     Injector.modules.push({
12
-      ifc: ifc,
12
+      extends: ifc,
13 13
       implementation: target
14 14
     })
15 15
   }
@@ -20,12 +20,12 @@ export const Module = (ifc?: Type<any>) : GenericClassDecorator<Type<any>> => {
20 20
  * @constructor
21 21
  */
22 22
 export const RootComponent = (config : {
23
-    rootInterface : Type<any>
23
+    implements : Type<any>
24 24
     imports : Type<FrontworkComponent>[]
25 25
   }) : GenericClassDecorator<Type<any>> => {
26 26
   return (target: Type<any>) => {
27 27
     Injector.rootModules = config.imports
28
-    Injector.rootInterface = config.rootInterface
28
+    Injector.rootInterface = config.implements
29 29
     Injector.root = target
30 30
   }
31 31
 }

+ 16
- 2
src/backend/Types/PlayerSpecs.ts Ver fichero

@@ -1,4 +1,4 @@
1
-import { Spec, _Class } from "./Types"
1
+import { Spec, _Class, Class } from "./Types"
2 2
 
3 3
 export type SpecT = {
4 4
     Warrior : 'Arms' | 'Fury' | 'Protection'
@@ -74,9 +74,23 @@ export function getSpecTableData() : Spec[]{
74 74
         const specNames : string[] = specs[_class]
75 75
         return specNames.map(specName => {
76 76
             return {
77
-                name: specName,
77
+                specname: specName,
78 78
                 class: _class
79 79
             }
80 80
         })
81 81
     })
82
+}
83
+
84
+export function getClassColor(c: Class) : string{
85
+    switch(c){
86
+        case "Warrior": return "#C79C6E"
87
+        case "Warlock": return "#8787ED"
88
+        case "Shaman": return "#0070DE"
89
+        case "Rogue": return "#FFF569"
90
+        case "Priest": return "#FFFFFF"
91
+        case "Paladin": return "#F58CBA"
92
+        case "Mage": return "#40C7EB"
93
+        case "Druid": return "#FF7D0A"
94
+        case "Hunter": return "#A9D271"
95
+    }
82 96
 }

+ 13
- 8
src/backend/Types/Types.ts Ver fichero

@@ -1,5 +1,5 @@
1 1
 import * as Knex from "knex"
2
-import { RPCExporter } from "rpclibrary";
2
+import { RPCExporter, Socket } from "rpclibrary";
3 3
 import { RaidManagerIfc, RaidManagerFeatureIfc } from "../Components/Raid/RPCInterface";
4 4
 import { LoginManagerIfc, LoginManagerFeatureIfc } from "../Components/Login/RPCInterface";
5 5
 import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
@@ -33,14 +33,14 @@ export const _Class : Class[] = ["Warrior" , "Rogue" , "Hunter" , "Mage" , "Warl
33 33
 export type AnyRPCExporter = RPCExporter<any,any>
34 34
 
35 35
 export type RPCPermission = {
36
-    name: string
36
+    rpcnamename: string
37 37
 } & {
38 38
     [rank in Rank] : boolean
39 39
 }
40 40
 
41 41
 export type Item = {
42 42
     id?:number
43
-    name:string
43
+    itemname:string
44 44
     iconname:string
45 45
     url:string
46 46
     quality:string
@@ -49,7 +49,7 @@ export type Item = {
49 49
 
50 50
 export type User = {
51 51
     id?: number
52
-    name: string
52
+    username: string
53 53
     pwhash: string
54 54
     rank: Rank
55 55
     email?: string
@@ -65,13 +65,13 @@ export type Raid = {
65 65
 }
66 66
 
67 67
 export type Signup = {
68
-    raid_id: number
69
-    user_id: number
68
+    raidid: number
69
+    characterid: number
70 70
 }
71 71
 
72 72
 export type Character = {
73 73
     id? : number
74
-    name : string
74
+    charactername : string
75 75
     specid : number
76 76
     userid : number
77 77
 }
@@ -84,11 +84,16 @@ export type Token = {
84 84
 
85 85
 export type Auth = {port: number, user: User, token: Token}
86 86
 
87
+export type UserRecord = {
88
+    user: User
89
+    connections: {[port in number]: Socket}
90
+    auth: Auth
91
+}
87 92
 
88 93
 export type Spec = {
89 94
     id?: number,
90 95
     class: Class,
91
-    name: string
96
+    specname: string
92 97
 }
93 98
 
94 99
 export type SomeOf<T> = {

+ 3
- 3
src/frontend/package-lock.json Ver fichero

@@ -17366,9 +17366,9 @@
17366 17366
       }
17367 17367
     },
17368 17368
     "tslib": {
17369
-      "version": "1.9.0",
17370
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz",
17371
-      "integrity": "sha512-f/qGG2tUkrISBlQZEjEqoZ3B2+npJjIf04H1wuAv9iA8i04Icp+61KRXxFdha22670NJopsZCIjhC3SnjPRKrQ=="
17369
+      "version": "1.10.0",
17370
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
17371
+      "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
17372 17372
     },
17373 17373
     "tslint": {
17374 17374
       "version": "5.7.0",

+ 1
- 1
src/frontend/package.json Ver fichero

@@ -74,7 +74,7 @@
74 74
     "rxjs-compat": "6.3.0",
75 75
     "socicon": "3.0.5",
76 76
     "tinymce": "4.5.7",
77
-    "tslib": "^1.9.0",
77
+    "tslib": "^1.10.0",
78 78
     "typeface-exo": "0.0.22",
79 79
     "web-animations-js": "github:angular/web-animations-js#release_pr208",
80 80
     "zone.js": "~0.9.1"

+ 1
- 1
src/frontend/src/app/@theme/components/header/header.component.html Ver fichero

@@ -16,7 +16,7 @@
16 16
     <nb-action class="user-action">
17 17
       <nb-user [nbContextMenu]="userMenu"
18 18
                [onlyPicture]="false"
19
-               [name]="user?.name"
19
+               [name]="user?.username"
20 20
                [picture]="user?.picture">
21 21
       </nb-user>
22 22
     </nb-action>

+ 3
- 1
src/frontend/src/app/@theme/components/header/header.component.ts Ver fichero

@@ -39,7 +39,7 @@ export class HeaderComponent implements OnInit, OnDestroy {
39 39
 
40 40
   currentTheme = 'dark';
41 41
 
42
-  userMenu : NbMenuItem[] = [ { title: 'Profile' }, { title: 'Log out', url: '/auth/logout' } ];
42
+  userMenu : NbMenuItem[] = [ { title: 'Log out', link: '/auth/logout' } ];
43 43
 
44 44
   constructor(private sidebarService: NbSidebarService,
45 45
               private menuService: NbMenuService,
@@ -53,6 +53,8 @@ export class HeaderComponent implements OnInit, OnDestroy {
53 53
     this.currentTheme = this.themeService.currentTheme;
54 54
 
55 55
     this.user = this.loginService.getCurrentUser()
56
+    if(this.user)
57
+      this.userMenu.unshift({ title: 'Profile', link: '/frontcraft/user/'+this.user.username });
56 58
 
57 59
     /*
58 60
     this.userService.getUsers()

+ 1
- 0
src/frontend/src/app/app-routing.module.ts Ver fichero

@@ -2,6 +2,7 @@ import { ExtraOptions, RouterModule, Routes } from '@angular/router';
2 2
 import { NgModule } from '@angular/core';
3 3
 
4 4
 const routes: Routes = [
5
+
5 6
   {
6 7
     path: 'auth',
7 8
     loadChildren: () => import('./frontcraft/auth/auth.module')

+ 0
- 1
src/frontend/src/app/app.module.ts Ver fichero

@@ -20,7 +20,6 @@ import {
20 20
   NbToastrModule,
21 21
   NbWindowModule,
22 22
 } from '@nebular/theme';
23
-import { LoginApiService } from './frontcraft/services/login-api';
24 23
 
25 24
 @NgModule({
26 25
   declarations: [AppComponent],

+ 1
- 1
src/frontend/src/app/frontcraft/auth/register/register.component.html Ver fichero

@@ -21,7 +21,7 @@
21 21
     <label class="label" for="input-username">Username:</label>
22 22
     <input nbInput
23 23
            fullWidth
24
-           [(ngModel)]="user.name"
24
+           [(ngModel)]="user.username"
25 25
            #email="ngModel"
26 26
            name="name"
27 27
            id="input-username"

+ 18
- 1
src/frontend/src/app/frontcraft/auth/register/register.component.ts Ver fichero

@@ -52,6 +52,7 @@ export class RegisterComponent implements OnInit{
52 52
   }
53 53
 
54 54
   async onSubmit(){
55
+    const pw = this.user.pwhash
55 56
     this.user.pwhash = await hash(this.user.pwhash)
56 57
     const user = this.user
57 58
     this.user = {} as User
@@ -60,9 +61,25 @@ export class RegisterComponent implements OnInit{
60 61
 
61 62
     try{
62 63
       const usr = await this.loginApi.getUnprivilegedSocket().Authenticator.createUser(user)
63
-      
64 64
     }catch(e){
65 65
       alert("Error creating user"+e)
66
+      return
67
+    }
68
+
69
+    try{
70
+      await this.loginApi.login(user.username, pw)
71
+      await this.loginApi.getFeature('createCharacter').then(async feature => {
72
+        if(!feature) return
73
+        const specid = await this.loginApi.getUnprivilegedSocket().CharacterManager.getSpecId(char['class'], char['spec'])
74
+        await feature.createCharacter(this.loginApi.getAuth().token.value, {
75
+          charactername: char.name,
76
+          specid: specid,
77
+          userid: this.loginApi.getAuth().user.id!
78
+        })
79
+      })
80
+    }catch(e){
81
+      alert("Error creating character"+e)
82
+      return
66 83
     }
67 84
   }
68 85
 

+ 10
- 0
src/frontend/src/app/frontcraft/pages/character/character.component.html Ver fichero

@@ -0,0 +1,10 @@
1
+<nb-card 
2
+status="control">
3
+    <nb-card-header [ngStyle]="{'color': color}" style="text-transform: capitalize;">
4
+        {{char.charactername}}
5
+    </nb-card-header>
6
+    <nb-card-body>
7
+        {{char.specname}} {{char.class}}<br />
8
+        Owned by <a [routerLink]="'/frontcraft/user/'+char.username"> {{char.username}} ({{char.rank}})</a>
9
+    </nb-card-body>
10
+</nb-card>

+ 34
- 0
src/frontend/src/app/frontcraft/pages/character/character.component.ts Ver fichero

@@ -0,0 +1,34 @@
1
+import { Component, OnInit } from '@angular/core';
2
+import { ActivatedRoute, Router } from '@angular/router';
3
+import { LoginApiService } from '../../services/login-api';
4
+import { Spec, User, Character } from '../../../../../../backend/Types/Types';
5
+import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
+
7
+@Component({
8
+  selector: 'character',
9
+  templateUrl: './character.component.html',
10
+})
11
+export class FrontcraftCharacterComponent implements OnInit{
12
+
13
+    char : (Character & User & Spec) = {} as any
14
+    color : string
15
+
16
+    constructor(
17
+      private login: LoginApiService,
18
+      private route: ActivatedRoute,
19
+      private router: Router,
20
+    ){}
21
+
22
+    async ngOnInit(){
23
+      const param = this.route.snapshot.paramMap.get('name');
24
+      this.login.getUnprivilegedSocket()      
25
+      .CharacterManager
26
+      .getCharacterByName(param)
27
+      .then((char) => {
28
+        if(char){
29
+          this.color = getClassColor(char.class)
30
+          this.char = char
31
+        }
32
+      })
33
+    }
34
+}

+ 35
- 1
src/frontend/src/app/frontcraft/pages/dashboard/dashboard.component.html Ver fichero

@@ -1 +1,35 @@
1
-<strong> Dashboard </strong>
1
+<nb-card>
2
+    <nb-card-body>
3
+
4
+        <label class="search-label" for="search">Search:</label>
5
+        <input nbInput [nbFilterInput]="dataSource" id="search" class="search-input">
6
+
7
+        <table [nbTreeGrid]="dataSource" [nbSort]="dataSource" (sort)="updateSort($event)">
8
+
9
+            <tr nbTreeGridHeaderRow *nbTreeGridHeaderRowDef="allColumns"></tr>
10
+            <tr nbTreeGridRow *nbTreeGridRowDef="let row; columns: allColumns"></tr>
11
+
12
+            <ng-container [nbTreeGridColumnDef]="customColumn">
13
+                <th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(customColumn)" *nbTreeGridHeaderCellDef>
14
+                {{customColumn}}
15
+                </th>
16
+                <td nbTreeGridCell *nbTreeGridCellDef="let row">
17
+                    <nb-tree-grid-row-toggle
18
+                        *ngIf="row.children && row.children.length">
19
+                    </nb-tree-grid-row-toggle>
20
+                    
21
+                    {{row.data[customColumn]}}
22
+                </td>
23
+            </ng-container>
24
+
25
+            <ng-container *ngFor="let column of defaultColumns; let index = index"
26
+                            [nbTreeGridColumnDef]="column"
27
+                            [showOn]="getShowOn(index)">
28
+                <th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(column)" *nbTreeGridHeaderCellDef>
29
+                {{column}}
30
+                </th>
31
+                <td nbTreeGridCell *nbTreeGridCellDef="let row">{{row.data[column] || '-'}}</td>
32
+            </ng-container>
33
+        </table>
34
+    </nb-card-body>
35
+</nb-card>

+ 42
- 0
src/frontend/src/app/frontcraft/pages/dashboard/dashboard.component.scss Ver fichero

@@ -0,0 +1,42 @@
1
+button[nbTreeGridRowToggle] {
2
+    background: transparent;
3
+    border: none;
4
+    padding: 0;
5
+  }
6
+  
7
+  .search-label {
8
+    display: block;
9
+  }
10
+  .search-input {
11
+    margin-bottom: 1rem;
12
+  }
13
+  
14
+  .nb-column-name {
15
+    width: 100%;
16
+  }
17
+  
18
+  @media screen and (min-width: 400px) {
19
+    .nb-column-name,
20
+    .nb-column-size {
21
+      width: 50%;
22
+    }
23
+  }
24
+  
25
+  @media screen and (min-width: 500px) {
26
+    .nb-column-name,
27
+    .nb-column-size,
28
+    .nb-column-kind {
29
+      width: 33.333%;
30
+    }
31
+  }
32
+  
33
+  @media screen and (min-width: 600px) {
34
+    .nb-column-name {
35
+      width: 31%;
36
+    }
37
+    .nb-column-size,
38
+    .nb-column-kind,
39
+    .nb-column-items {
40
+      width: 23%;
41
+    }
42
+  }

+ 54
- 7
src/frontend/src/app/frontcraft/pages/dashboard/dashboard.component.ts Ver fichero

@@ -1,16 +1,63 @@
1
-import { Component, OnInit } from '@angular/core';
2
-import { LoginApiService } from '../../services/login-api';
1
+import { Component } from '@angular/core';
2
+import { NbSortDirection, NbSortRequest, NbTreeGridDataSourceBuilder, NbTreeGridDataSource } from '@nebular/theme';
3
+
4
+interface TreeNode<T> {
5
+  data: T;
6
+  children?: TreeNode<T>[];
7
+  expanded?: boolean;
8
+}
9
+
10
+interface Row {
11
+  name: string,
12
+  character: any,
13
+  SRC: any,
14
+}
15
+
16
+type TreeType = TreeNode<Row>
3 17
 
4 18
 @Component({
5 19
   selector: 'dashboard',
6 20
   templateUrl: './dashboard.component.html',
21
+  styleUrls: ['./tree-grid-shared.scss', './dashboard.component.scss'],
7 22
 })
8
-export class FrontcraftDashboardComponent implements OnInit{
23
+export class FrontcraftDashboardComponent{
24
+  customColumn = 'name';
25
+  defaultColumns = [ 'character', 'SRC'/*, 'Profile'*/ ];
26
+  allColumns = [ this.customColumn, ...this.defaultColumns ];
27
+
28
+  dataSource: NbTreeGridDataSource<TreeType>;
9 29
 
10
-    constructor(private loginApi : LoginApiService){}
30
+  sortColumn: string;
31
+  sortDirection: NbSortDirection = NbSortDirection.NONE;
11 32
 
12
-    ngOnInit(){
13
-        console.log(this.loginApi)
33
+  constructor(private dataSourceBuilder: NbTreeGridDataSourceBuilder<TreeType>) {
34
+    this.dataSource = this.dataSourceBuilder.create(this.data);
35
+  }
36
+
37
+  updateSort(sortRequest: NbSortRequest): void {
38
+    this.sortColumn = sortRequest.column;
39
+    this.sortDirection = sortRequest.direction;
40
+  }
41
+
42
+  getSortDirection(column: string): NbSortDirection {
43
+    if (this.sortColumn === column) {
44
+      return this.sortDirection;
14 45
     }
46
+    return NbSortDirection.NONE;
47
+  }
48
+
49
+  private data: TreeType[] = [
50
+   {
51
+     data: {name: 'a', character: 2, SRC: 0},
52
+     children: [
53
+       {data: {name: 'a', character: 'Warrior', SRC: 'Arms'}}
54
+     ]
55
+   }
56
+  ];
15 57
 
16
-}
58
+  getShowOn(index: number) {
59
+    const minWithForMultipleColumns = 400;
60
+    const nextColumnStep = 100;
61
+    return minWithForMultipleColumns + (nextColumnStep * index);
62
+  }
63
+}

+ 10
- 0
src/frontend/src/app/frontcraft/pages/dashboard/tree-grid-shared.scss Ver fichero

@@ -0,0 +1,10 @@
1
+::ng-deep {
2
+    body {
3
+      min-height: 20rem;
4
+    }
5
+  
6
+    .nb-tree-grid-header-cell,
7
+    .nb-tree-grid-header-cell button {
8
+      text-transform: capitalize;
9
+    }
10
+  }

+ 10
- 1
src/frontend/src/app/frontcraft/pages/pages-layout.component.ts Ver fichero

@@ -17,10 +17,19 @@ import { Router } from '@angular/router';
17 17
 export class PagesLayoutComponent implements OnInit{
18 18
   menu:NbMenuItem[] = [{
19 19
     icon: 'people-outline',
20
-    title: 'People'
20
+    title: 'People',
21
+    link: '/frontcraft/people'
21 22
   },{
22 23
     icon: 'clock-outline',
23 24
     title: 'Raids'
25
+  },{
26
+    icon: 'clock-outline',
27
+    title: 'character',
28
+    link: '/frontcraft/character/a'
29
+  },{
30
+    icon: 'clock-outline',
31
+    title: 'user',
32
+    link: '/frontcraft/user/a'
24 33
   }]
25 34
   
26 35
   constructor(

+ 15
- 0
src/frontend/src/app/frontcraft/pages/pages-routing.module.ts Ver fichero

@@ -2,12 +2,27 @@ import { NgModule } from '@angular/core';
2 2
 import { RouterModule, Routes } from '@angular/router';
3 3
 import { FrontcraftDashboardComponent } from './dashboard/dashboard.component';
4 4
 import { PagesLayoutComponent } from './pages-layout.component';
5
+import { FrontcraftCharacterComponent } from './character/character.component';
6
+import { FrontcraftUserComponent } from './user/user.component';
7
+import { FrontcraftPeopleComponent } from './people/people.component';
5 8
 
6 9
 export const routes: Routes = [
7 10
     {
8 11
         path: '',
9 12
         component: PagesLayoutComponent,
10 13
         children: [
14
+            {
15
+                path: 'people',
16
+                component: FrontcraftPeopleComponent
17
+            },
18
+            {
19
+                path: 'user/:name',
20
+                component: FrontcraftUserComponent
21
+            },
22
+            {
23
+                path: 'character/:name',
24
+                component: FrontcraftCharacterComponent
25
+            },
11 26
             {
12 27
                 path: 'dashboard',
13 28
                 component: FrontcraftDashboardComponent,

+ 9
- 1
src/frontend/src/app/frontcraft/pages/pages.module.ts Ver fichero

@@ -9,7 +9,8 @@ import {
9 9
   NbCheckboxModule,
10 10
   NbInputModule,
11 11
   NbMenuModule,
12
-  NbCardModule
12
+  NbCardModule,
13
+  NbTreeGridModule
13 14
 } from '@nebular/theme';
14 15
 import { MyAuthRoutingModule } from './pages-routing.module';
15 16
 import { FrontcraftDashboardComponent } from './dashboard/dashboard.component';
@@ -18,11 +19,15 @@ import { ThemeModule } from '../../@theme/theme.module';
18 19
 import { DashboardModule } from '../../demo_pages/dashboard/dashboard.module';
19 20
 import { ECommerceModule } from '../../demo_pages/e-commerce/e-commerce.module';
20 21
 import { MiscellaneousModule } from '../../demo_pages/miscellaneous/miscellaneous.module';
22
+import { FrontcraftCharacterComponent } from './character/character.component';
23
+import { FrontcraftUserComponent } from './user/user.component';
24
+import { FrontcraftPeopleComponent } from './people/people.component';
21 25
 
22 26
 
23 27
 @NgModule({
24 28
   imports: [
25 29
     MyAuthRoutingModule,
30
+    NbTreeGridModule,
26 31
     CommonModule,
27 32
     FormsModule,
28 33
     RouterModule,
@@ -39,6 +44,9 @@ import { MiscellaneousModule } from '../../demo_pages/miscellaneous/miscellaneou
39 44
     
40 45
   ],
41 46
   declarations: [
47
+    FrontcraftPeopleComponent,
48
+    FrontcraftUserComponent,
49
+    FrontcraftCharacterComponent,
42 50
     PagesLayoutComponent,
43 51
     FrontcraftDashboardComponent
44 52
   ],

+ 36
- 0
src/frontend/src/app/frontcraft/pages/people/people.component.html Ver fichero

@@ -0,0 +1,36 @@
1
+<nb-card>
2
+    <nb-card-body>
3
+
4
+        <label class="search-label" for="search">Search:</label>
5
+        <input nbInput [nbFilterInput]="dataSource" id="search" class="search-input">
6
+
7
+        <table [nbTreeGrid]="dataSource" [nbSort]="dataSource" (sort)="updateSort($event)">
8
+
9
+            <tr nbTreeGridHeaderRow *nbTreeGridHeaderRowDef="allColumns"></tr>
10
+            <tr nbTreeGridRow *nbTreeGridRowDef="let row; columns: allColumns"></tr>
11
+
12
+            <ng-container [nbTreeGridColumnDef]="customColumn">
13
+                <th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(customColumn)" *nbTreeGridHeaderCellDef>
14
+                {{customColumn}}
15
+                </th>
16
+                <td nbTreeGridCell *nbTreeGridCellDef="let row">
17
+                    <nb-tree-grid-row-toggle
18
+                        *ngIf="row.children && row.children.length">
19
+                    </nb-tree-grid-row-toggle>
20
+                    <span style="text-transform: capitalize;">
21
+                        {{row.data[customColumn]}}
22
+                    </span>
23
+                </td>
24
+            </ng-container>
25
+
26
+            <ng-container *ngFor="let column of defaultColumns; let index = index"
27
+                            [nbTreeGridColumnDef]="column"
28
+                            [showOn]="getShowOn(index)">
29
+                <th nbTreeGridHeaderCell [nbSortHeader]="getSortDirection(column)" *nbTreeGridHeaderCellDef>
30
+                {{column}}
31
+                </th>
32
+                <td nbTreeGridCell *nbTreeGridCellDef="let row">{{row.data[column] || '-'}}</td>
33
+            </ng-container>
34
+        </table>
35
+    </nb-card-body>
36
+</nb-card>

+ 42
- 0
src/frontend/src/app/frontcraft/pages/people/people.component.scss Ver fichero

@@ -0,0 +1,42 @@
1
+button[nbTreeGridRowToggle] {
2
+    background: transparent;
3
+    border: none;
4
+    padding: 0;
5
+  }
6
+  
7
+  .search-label {
8
+    display: block;
9
+  }
10
+  .search-input {
11
+    margin-bottom: 1rem;
12
+  }
13
+  
14
+  .nb-column-name {
15
+    width: 100%;
16
+  }
17
+  
18
+  @media screen and (min-width: 400px) {
19
+    .nb-column-name,
20
+    .nb-column-size {
21
+      width: 50%;
22
+    }
23
+  }
24
+  
25
+  @media screen and (min-width: 500px) {
26
+    .nb-column-name,
27
+    .nb-column-size,
28
+    .nb-column-kind {
29
+      width: 33.333%;
30
+    }
31
+  }
32
+  
33
+  @media screen and (min-width: 600px) {
34
+    .nb-column-name {
35
+      width: 31%;
36
+    }
37
+    .nb-column-size,
38
+    .nb-column-kind,
39
+    .nb-column-items {
40
+      width: 23%;
41
+    }
42
+  }

+ 64
- 0
src/frontend/src/app/frontcraft/pages/people/people.component.ts Ver fichero

@@ -0,0 +1,64 @@
1
+import { Component } from '@angular/core';
2
+import { NbSortDirection, NbSortRequest, NbTreeGridDataSourceBuilder, NbTreeGridDataSource } from '@nebular/theme';
3
+
4
+interface TreeNode<T> {
5
+  data: T;
6
+  children?: TreeNode<T>[];
7
+  expanded?: boolean;
8
+}
9
+
10
+interface Row {
11
+  name: string,
12
+  character: any,
13
+  SRC: any,
14
+  kind: 'Character' | 'Account'
15
+}
16
+
17
+type TreeType = TreeNode<Row>
18
+
19
+@Component({
20
+  selector: 'people-component',
21
+  templateUrl: './people.component.html',
22
+  styleUrls: ['./tree-grid-shared.scss', './people.component.scss'],
23
+})
24
+export class FrontcraftPeopleComponent{
25
+  customColumn = 'name';
26
+  defaultColumns = [ 'character', 'SRC'/*, 'Profile'*/ ];
27
+  allColumns = [ this.customColumn, ...this.defaultColumns ];
28
+
29
+  dataSource: NbTreeGridDataSource<TreeType>;
30
+
31
+  sortColumn: string;
32
+  sortDirection: NbSortDirection = NbSortDirection.NONE;
33
+
34
+  constructor(private dataSourceBuilder: NbTreeGridDataSourceBuilder<TreeType>) {
35
+    this.dataSource = this.dataSourceBuilder.create(this.data);
36
+  }
37
+
38
+  updateSort(sortRequest: NbSortRequest): void {
39
+    this.sortColumn = sortRequest.column;
40
+    this.sortDirection = sortRequest.direction;
41
+  }
42
+
43
+  getSortDirection(column: string): NbSortDirection {
44
+    if (this.sortColumn === column) {
45
+      return this.sortDirection;
46
+    }
47
+    return NbSortDirection.NONE;
48
+  }
49
+
50
+  private data: TreeType[] = [
51
+   {
52
+     data: {name: 'a', character: 2, SRC: 0, kind: 'Account'},
53
+     children: [
54
+       {data: {name: 'a', character: 'Warrior', SRC: 'Arms', kind: 'Character'}}
55
+     ]
56
+   }
57
+  ];
58
+
59
+  getShowOn(index: number) {
60
+    const minWithForMultipleColumns = 400;
61
+    const nextColumnStep = 100;
62
+    return minWithForMultipleColumns + (nextColumnStep * index);
63
+  }
64
+}

+ 10
- 0
src/frontend/src/app/frontcraft/pages/people/tree-grid-shared.scss Ver fichero

@@ -0,0 +1,10 @@
1
+::ng-deep {
2
+    body {
3
+      min-height: 20rem;
4
+    }
5
+  
6
+    .nb-tree-grid-header-cell,
7
+    .nb-tree-grid-header-cell button {
8
+      text-transform: capitalize;
9
+    }
10
+  }

+ 24
- 0
src/frontend/src/app/frontcraft/pages/user/user.component.html Ver fichero

@@ -0,0 +1,24 @@
1
+
2
+
3
+<nb-card
4
+accent="info">
5
+    <nb-card-header>
6
+        <h2 style="text-transform: capitalize;">{{user.username}}</h2>
7
+    </nb-card-header>
8
+    <nb-card-body>
9
+      <nb-card
10
+      accent="control"
11
+      *ngFor="let char of characters">
12
+          <nb-card-header>
13
+              <h4>
14
+                  <a [ngStyle]="{'color': char.color}" style="text-transform: capitalize;" [routerLink]="'/frontcraft/character/'+char.charactername">
15
+                      {{char.charactername}}
16
+                  </a>
17
+              </h4>
18
+          </nb-card-header>
19
+          <nb-card-body>
20
+              {{char.specname}} {{char.class}}
21
+          </nb-card-body>
22
+      </nb-card>
23
+    </nb-card-body>
24
+</nb-card>

+ 38
- 0
src/frontend/src/app/frontcraft/pages/user/user.component.ts Ver fichero

@@ -0,0 +1,38 @@
1
+import { Component, OnInit } from '@angular/core';
2
+import { LoginApiService } from '../../services/login-api';
3
+import { Router } from '@angular/router';
4
+import { User, Spec, Character } from '../../../../../../backend/Types/Types';
5
+import { getClassColor } from '../../../../../../backend/Types/PlayerSpecs';
6
+
7
+@Component({
8
+  selector: 'user-component',
9
+  templateUrl: './user.component.html',
10
+})
11
+export class FrontcraftUserComponent implements OnInit{
12
+
13
+  user:User = {} as any
14
+  characters : (Character & Spec)[] = []
15
+
16
+  constructor(
17
+    private router : Router,  
18
+    private loginApi : LoginApiService
19
+  ){}
20
+
21
+  ngOnInit(){
22
+    const auth = this.loginApi.getAuth()
23
+    if(!auth){
24
+      this.router.navigateByUrl('/auth/login')
25
+      return
26
+    }
27
+    this.user = auth.user
28
+    this.loginApi.getUnprivilegedSocket()
29
+    .CharacterManager
30
+    .getCharactersOfUser(this.user.username)
31
+    .then((characters) => {
32
+      characters.forEach(c => {
33
+        c['color'] = getClassColor(c.class)
34
+      })
35
+      this.characters = characters
36
+    })  
37
+  }
38
+}

+ 12
- 8
src/frontend/src/app/frontcraft/services/login-api.ts Ver fichero

@@ -31,18 +31,20 @@ export class LoginApiService{
31 31
            
32 32
             const authSock = await sock.connect<RPCSocket & SomeOf<FrontcraftFeatureIfc>>(auth.token.value)
33 33
 
34
-            sock.hook('kick', () => this.logout())
34
+            sock.hook('kick', () => {
35
+                console.log("I got kicked");
36
+            })
35 37
             sock.hook('getUserData', () => auth)
36 38
             sock.hook('navigate', (where:string) => {
37
-                this.ngZone.run(() => {
38
-                    this.injector.get(Router).navigateByUrl(where);
39
+                this.ngZone.run( () => {
40
+                    this.injector.get(Router).navigateByUrl('/')
39 41
                 })
40 42
             })
41 43
             sock.on('error', (e) => {
42
-                console.log('Socket error',  e)
43
-                this.logout()
44
+                sock.destroy();
45
+                
44 46
             })
45
-
47
+            
46 48
             this.auth = auth
47 49
             this.privSocket = authSock
48 50
             this.cookieSvc.set('token', JSON.stringify(auth))
@@ -62,7 +64,9 @@ export class LoginApiService{
62 64
         }
63 65
     }
64 66
 
65
-    getCurrentUser = () : User | undefined => this.auth?this.auth.user:undefined
67
+    getCurrentUser = () : User | undefined => {
68
+        return this.auth?this.auth.user:undefined
69
+    }
66 70
 
67 71
     login = async (username: string, password: string) : Promise<RPCSocket & SomeOf<FrontcraftFeatureIfc>> => {
68 72
         const pwHash = await hash(password)
@@ -78,7 +82,7 @@ export class LoginApiService{
78 82
 
79 83
     logout = async () => {
80 84
         this.cookieSvc.set('token', undefined)
81
-        if(this.auth) await this.socket.Authenticator.logout(this.auth.user.name, this.auth.token.value)
85
+        if(this.auth) await this.socket.Authenticator.logout(this.auth.user.username, this.auth.token.value)
82 86
         if(this.privSocket) this.privSocket.destroy()
83 87
         this.privSocket = null
84 88
         this.auth  = null

Loading…
Cancelar
Guardar