Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
C
console
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
console
Commits
9f0c79f8
Commit
9f0c79f8
authored
Aug 19, 2021
by
nanahira
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
complete package
parent
f6959604
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
159 additions
and
26 deletions
+159
-26
console-api/src/app.controller.ts
console-api/src/app.controller.ts
+45
-11
console-api/src/app.service.ts
console-api/src/app.service.ts
+76
-11
console-api/src/dto/Depot.dto.ts
console-api/src/dto/Depot.dto.ts
+26
-0
console-api/src/dto/ReturnMessage.dto.ts
console-api/src/dto/ReturnMessage.dto.ts
+6
-0
console-api/src/entities/Build.entity.ts
console-api/src/entities/Build.entity.ts
+4
-3
console-api/src/entities/Depot.entity.ts
console-api/src/entities/Depot.entity.ts
+2
-1
No files found.
console-api/src/app.controller.ts
View file @
9f0c79f8
import
{
Body
,
Controller
,
Get
,
Param
,
Post
,
Query
,
Req
,
UploadedFile
,
UseGuards
,
UseInterceptors
,
ValidationPipe
}
from
'
@nestjs/common
'
;
import
{
Body
,
Controller
,
Delete
,
Get
,
Param
,
Post
,
Query
,
Req
,
UploadedFile
,
UseGuards
,
UseInterceptors
,
ValidationPipe
,
}
from
'
@nestjs/common
'
;
import
{
AppService
}
from
'
./app.service
'
;
import
{
ApiBody
,
ApiConsumes
,
ApiCreatedResponse
,
ApiOkResponse
,
ApiOperation
,
ApiParam
,
ApiQuery
}
from
'
@nestjs/swagger
'
;
import
{
BlankReturnMessageDto
,
GetAppReturnMessageDto
,
ReturnMessageDto
,
StringReturnMessageDto
}
from
'
./dto/ReturnMessage.dto
'
;
import
{
BlankReturnMessageDto
,
BuildReturnMessageDto
,
GetAppReturnMessageDto
,
ReturnMessageDto
,
StringReturnMessageDto
,
}
from
'
./dto/ReturnMessage.dto
'
;
import
{
FetchMyCardUser
,
MyCardUser
}
from
'
./utility/mycard-auth
'
;
import
{
AppsJson
}
from
'
./utility/apps-json-type
'
;
import
{
MyCardAppMaintainerGuard
}
from
'
./my-card-app-maintainer.guard
'
;
...
...
@@ -14,6 +33,7 @@ import { Stream } from 'stream';
import
{
PackageResult
}
from
'
./dto/PackageResult.dto
'
;
import
{
platform
}
from
'
os
'
;
import
AppClass
=
AppsJson
.
AppClass
;
import
{
DepotDto
}
from
'
./dto/Depot.dto
'
;
@
Controller
(
'
api
'
)
export
class
AppController
{
...
...
@@ -70,27 +90,41 @@ export class AppController {
}
}
@
Post
(
'
build/:id/:platform/:locale/:version
'
)
@
Delete
(
'
build/:id/:version
'
)
@
ApiOperation
({
summary
:
'
删除打包
'
,
description
:
'
删除的打包会被彻底删除
'
,
})
@
ApiParam
({
name
:
'
id
'
,
description
:
'
APP 的 id
'
})
@
ApiParam
({
name
:
'
version
'
,
description
:
'
APP 的版本号
'
})
@
ApiQuery
({
type
:
DepotDto
,
description
:
'
APP 的类型
'
})
async
removeBuild
(
@
FetchMyCardUser
()
user
:
MyCardUser
,
@
Param
(
'
id
'
)
id
:
string
,
@
Query
(
new
ValidationPipe
({
transform
:
true
}))
depot
:
DepotDto
,
@
Param
(
'
version
'
)
version
:
string
):
Promise
<
BlankReturnMessageDto
>
{
return
this
.
appService
.
removeBuild
(
user
,
id
,
depot
,
version
);
}
@
Post
(
'
build/:id/:version
'
)
@
ApiOperation
({
summary
:
'
打包文件
'
,
description
:
'
必须登录用户且必须是管理员或者拥有1个 app 才能上传
'
,
})
@
ApiConsumes
(
'
multipart/form-data
'
)
@
ApiParam
({
name
:
'
id
'
,
description
:
'
APP 的 id
'
})
@
ApiParam
({
name
:
'
platform
'
,
description
:
'
APP 的 版本号
'
,
enum
:
AppsJson
.
Platform
})
@
ApiParam
({
name
:
'
locale
'
,
description
:
'
APP 的 版本号
'
,
enum
:
AppsJson
.
Locale
})
@
ApiParam
({
name
:
'
version
'
,
description
:
'
APP 的 版本号
'
})
@
ApiParam
({
name
:
'
version
'
,
description
:
'
APP 的版本号
'
})
@
ApiQuery
({
type
:
DepotDto
,
description
:
'
APP 的类型
'
})
@
ApiBody
({
description
:
'
app 的 tar.gz 文件
'
,
type
:
FileUploadDto
,
})
@
ApiCreatedResponse
({
type
:
B
lank
ReturnMessageDto
})
@
ApiCreatedResponse
({
type
:
B
uild
ReturnMessageDto
})
async
makeBuild
(
@
FetchMyCardUser
()
user
:
MyCardUser
,
//@UploadedFile() file: Express.Multer.File,
@
Param
(
'
id
'
)
id
:
string
,
@
Param
(
'
platform
'
)
platform
:
AppsJson
.
Platform
,
@
Param
(
'
locale
'
)
locale
:
AppsJson
.
Locale
,
@
Query
(
new
ValidationPipe
({
transform
:
true
}))
depot
:
DepotDto
,
@
Param
(
'
version
'
)
version
:
string
,
@
Req
()
req
:
Request
)
{
...
...
@@ -111,7 +145,7 @@ export class AppController {
// console.log(`got file ${fieldname}`);
const
stream
=
new
Stream
.
Readable
().
wrap
(
fileStream
);
try
{
resolve
(
await
this
.
appService
.
makeBuild
(
user
,
stream
,
id
,
platform
,
locale
,
version
));
resolve
(
await
this
.
appService
.
makeBuild
(
user
,
stream
,
id
,
depot
,
version
));
}
catch
(
e
)
{
stream
.
destroy
();
reject
(
e
);
...
...
console-api/src/app.service.ts
View file @
9f0c79f8
...
...
@@ -7,15 +7,23 @@ import { BlankReturnMessageDto, ReturnMessageDto } from './dto/ReturnMessage.dto
import
{
MyCardUser
}
from
'
./utility/mycard-auth
'
;
import
{
PackagerService
}
from
'
./packager/packager.service
'
;
import
internal
from
'
stream
'
;
import
{
Depot
}
from
'
./entities/Depot.entity
'
;
import
{
DepotDto
}
from
'
./dto/Depot.dto
'
;
import
{
Build
}
from
'
./entities/Build.entity
'
;
import
{
ConfigService
}
from
'
@nestjs/config
'
;
import
{
Archive
}
from
'
./entities/Archive.entity
'
;
@
Injectable
()
export
class
AppService
extends
ConsoleLogger
{
private
readonly
packageVersionTraceCount
:
number
;
constructor
(
@
InjectConnection
(
'
app
'
)
private
db
:
Connection
,
private
packager
:
PackagerService
private
packager
:
PackagerService
,
config
:
ConfigService
)
{
super
(
'
app
'
);
this
.
packageVersionTraceCount
=
parseInt
(
config
.
get
(
'
PACKAGE_VERSION_TRACE_COUNT
'
))
||
5
;
}
async
getAppsJson
()
{
...
...
@@ -132,14 +140,26 @@ export class AppService extends ConsoleLogger {
},
201
);
}
async
makeBuild
(
user
:
MyCardUser
,
stream
:
internal
.
Readable
,
id
:
string
,
platform
:
AppsJson
.
Platform
,
locale
:
AppsJson
.
Locale
,
version
:
string
)
{
async
getOrCreateDepot
(
app
:
App
,
depotDto
:
DepotDto
)
{
const
depotOption
=
depotDto
.
toActual
;
let
depot
=
await
this
.
db
.
getRepository
(
Depot
).
findOne
({
where
:
{
app
,
...
depotOption
}
});
if
(
!
depot
)
{
depot
=
new
Depot
();
depot
.
app
=
app
;
depot
.
platform
=
depotOption
.
platform
;
depot
.
locale
=
depotOption
.
locale
;
depot
.
arch
=
depotOption
.
arch
;
depot
.
builds
=
[];
depot
=
await
this
.
db
.
getRepository
(
Depot
).
save
(
depot
);
}
return
depot
;
}
async
checkExistingBuild
(
depot
:
Depot
,
version
:
string
)
{
return
this
.
db
.
getRepository
(
Build
).
findOne
({
where
:
{
depot
,
version
},
select
:
[
'
id
'
]
});
}
async
makeBuild
(
user
:
MyCardUser
,
stream
:
internal
.
Readable
,
id
:
string
,
depotDto
:
DepotDto
,
version
:
string
)
{
if
(
!
user
)
{
throw
new
BlankReturnMessageDto
(
401
,
'
Needs login
'
).
toException
();
}
...
...
@@ -154,9 +174,54 @@ export class AppService extends ConsoleLogger {
if
(
!
app
.
isUserCanEditApp
(
user
))
{
throw
new
BlankReturnMessageDto
(
403
,
'
Permission denied
'
).
toException
();
}
const
depot
=
await
this
.
getOrCreateDepot
(
app
,
depotDto
);
if
(
await
this
.
checkExistingBuild
(
depot
,
version
))
{
throw
new
BlankReturnMessageDto
(
404
,
'
Build exists
'
).
toException
();
}
const
build
=
new
Build
();
build
.
depot
=
depot
;
build
.
version
=
version
;
this
.
log
(
`Start packaging
${
app
.
id
}
.`
);
const
result
=
await
this
.
packager
.
build
(
stream
,
app
.
packagePrefix
);
return
new
ReturnMessageDto
(
201
,
'
success
'
,
result
);
try
{
const
previousTracingBuildChecksums
=
(
await
this
.
db
.
getRepository
(
Build
)
.
find
({
where
:
{
depot
},
order
:
{
id
:
'
DESC
'
},
select
:
[
'
id
'
,
'
checksum
'
],
take
:
this
.
packageVersionTraceCount
})
).
map
((
b
)
=>
b
.
checksum
);
const
result
=
await
this
.
packager
.
build
(
stream
,
app
.
packagePrefix
,
previousTracingBuildChecksums
);
build
.
checksum
=
result
.
checksum
;
build
.
archives
=
result
.
archives
;
return
new
ReturnMessageDto
(
201
,
'
success
'
,
await
this
.
db
.
getRepository
(
Build
).
save
(
build
));
}
catch
(
e
)
{
this
.
error
(
`Build
${
app
.
id
}
${
JSON
.
stringify
(
depotDto
.
toActual
)}
${
build
.
version
}
failed:
${
e
.
toString
()}
`
);
throw
new
BlankReturnMessageDto
(
500
,
'
Build failed
'
).
toException
();
}
}
async
removeBuild
(
user
:
MyCardUser
,
id
:
string
,
depotDto
:
DepotDto
,
version
:
string
)
{
if
(
!
user
)
{
throw
new
BlankReturnMessageDto
(
401
,
'
Needs login
'
).
toException
();
}
const
app
=
await
this
.
db
.
getRepository
(
App
).
findOne
({
where
:
{
id
},
select
:
[
'
id
'
,
'
author
'
],
});
if
(
!
app
)
{
throw
new
BlankReturnMessageDto
(
404
,
'
App not found
'
).
toException
();
}
if
(
!
app
.
isUserCanEditApp
(
user
))
{
throw
new
BlankReturnMessageDto
(
403
,
'
Permission denied
'
).
toException
();
}
const
depot
=
await
this
.
getOrCreateDepot
(
app
,
depotDto
);
const
build
=
await
this
.
checkExistingBuild
(
depot
,
version
);
if
(
!
build
)
{
throw
new
BlankReturnMessageDto
(
404
,
'
Build not found
'
).
toException
();
}
await
this
.
db
.
transaction
(
async
(
edb
)
=>
{
await
edb
.
getRepository
(
Archive
).
delete
({
build
});
await
edb
.
getRepository
(
Build
).
delete
(
build
);
});
return
new
BlankReturnMessageDto
(
200
,
'
success
'
);
}
async
deleteApp
(
id
:
string
)
{
...
...
console-api/src/dto/Depot.dto.ts
0 → 100644
View file @
9f0c79f8
import
{
AppsJson
}
from
'
../utility/apps-json-type
'
;
import
Platform
=
AppsJson
.
Platform
;
import
Locale
=
AppsJson
.
Locale
;
import
{
ApiParam
,
ApiProperty
}
from
'
@nestjs/swagger
'
;
export
interface
DepotLike
{
platform
?:
string
;
arch
?:
string
;
locale
?:
string
;
}
export
class
DepotDto
implements
DepotLike
{
@
ApiProperty
({
description
:
'
APP 的平台
'
,
enum
:
AppsJson
.
Platform
})
platform
?:
string
;
@
ApiProperty
({
description
:
'
APP 的 arch
'
})
arch
?:
string
;
@
ApiProperty
({
description
:
'
APP 的语言
'
,
enum
:
AppsJson
.
Locale
})
locale
?:
string
;
get
toActual
():
DepotLike
{
return
{
platform
:
this
.
platform
||
'
generic
'
,
arch
:
this
.
arch
||
'
generic
'
,
locale
:
this
.
locale
||
'
generic
'
,
};
}
}
console-api/src/dto/ReturnMessage.dto.ts
View file @
9f0c79f8
import
{
ApiProperty
}
from
'
@nestjs/swagger
'
;
import
{
HttpException
}
from
'
@nestjs/common
'
;
import
{
AppsJson
}
from
'
../utility/apps-json-type
'
;
import
{
Build
}
from
'
../entities/Build.entity
'
;
export
class
BlankReturnMessageDto
{
@
ApiProperty
({
description
:
'
返回状态
'
})
...
...
@@ -55,3 +56,8 @@ export class UploadAssignInfoReturnMessageDto extends BlankReturnMessageDto {
@
ApiProperty
({
description
:
'
返回内容
'
})
data
?:
UploadAssignInfo
;
}
export
class
BuildReturnMessageDto
extends
BlankReturnMessageDto
{
@
ApiProperty
({
description
:
'
返回内容
'
})
data
?:
Build
;
}
console-api/src/entities/Build.entity.ts
View file @
9f0c79f8
import
{
Column
,
Entity
,
ManyToOne
,
OneToMany
,
PrimaryGeneratedColumn
}
from
'
typeorm
'
;
import
{
Column
,
Entity
,
ManyToOne
,
OneToMany
,
PrimaryGeneratedColumn
,
Unique
}
from
'
typeorm
'
;
import
{
Depot
}
from
'
./Depot.entity
'
;
import
{
Archive
}
from
'
./Archive.entity
'
;
import
{
Index
}
from
'
typeorm
'
;
import
{
TimeBase
}
from
'
./TimeBase.entity
'
;
@
Entity
()
@
Index
((
b
)
=>
[
b
.
depot
,
b
.
version
])
export
class
Build
extends
TimeBase
{
@
PrimaryGeneratedColumn
()
id
:
number
;
...
...
@@ -13,10 +14,10 @@ export class Build extends TimeBase {
@
Column
()
version
:
string
;
@
ManyToOne
((
type
)
=>
Depot
,
(
depot
)
=>
depot
.
builds
)
@
ManyToOne
(()
=>
Depot
,
(
depot
)
=>
depot
.
builds
)
depot
:
Depot
;
@
OneToMany
((
type
)
=>
Archive
,
(
archive
)
=>
archive
.
build
)
@
OneToMany
((
)
=>
Archive
,
(
archive
)
=>
archive
.
build
,
{
cascade
:
true
}
)
archives
:
Archive
[];
@
Column
({
type
:
'
hstore
'
,
hstoreType
:
'
object
'
})
...
...
console-api/src/entities/Depot.entity.ts
View file @
9f0c79f8
...
...
@@ -2,10 +2,11 @@ import { Column, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn } f
import
{
App
}
from
'
./App.entity
'
;
import
{
Build
}
from
'
./Build.entity
'
;
import
{
TimeBase
}
from
'
./TimeBase.entity
'
;
import
{
DepotLike
}
from
'
../dto/Depot.dto
'
;
@
Index
((
d
)
=>
[
d
.
app
,
d
.
locale
,
d
.
platform
,
d
.
arch
],
{
unique
:
true
})
@
Entity
()
export
class
Depot
extends
TimeBase
{
export
class
Depot
extends
TimeBase
implements
DepotLike
{
@
PrimaryGeneratedColumn
()
id
:
number
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment